Discussions

News: Use J2SE 5 annotations to eliminate getters and setters?

  1. Allen Holub points out that the getter/setter idiom has always been problematic; it allows too-broad access to the implementation of your classes, degrading maintainability as a consequence. The J2SE 5 annotation (or metadata) feature provides an alternative. Rather than using introspection to find get/set methods, you can "tag" an object with an annotation and then access that annotation at either compilation or at runtime. He's written an article both describes the annotation mechanism and presents the output side of an XML-based persistence mechanism that uses annotations to tag persistent classes and fields.

    He presents a pretty simple example of annotation, but effectively demonstrates how to use an annotation at runtime to eliminate the getter/setter-based tagging idiom. All of the introspection-related classes (like Class, Method, and Field) have a getAnnotation() method that you can use to access the annotations. He states that this is just one part of the puzzle, because annotations are often best used at the compiler, not the runtime level.

    While Mr. Holub doesn't mention EJB3 persistence specifically, his article describes a mechanism very similar to what EJB3 persistence will be.

    See:
    See Also:

    Threaded Messages (45)

  2. Why Getter and Setter Methods are Evil," also by Allen Holub
    I have been looking for that article. I've mentioned it in a few posts.
  3. Why Getter and Setter Methods are Evil," also by Allen Holub
    I have been looking for that article. I've mentioned it in a few posts.
    Thought I like alot of what he says, two things bother me. Constructors (or methods) with more than a few parameters. I think Java 5.0 solves some of that with named parameters. Also, how to work out "displayYourself" when the same object is used in multiple view technologies in the same project.
  4. Constructors (or methods) with more than a few parameters. I think Java 5.0 solves some of that with named parameters.
    There's no such thing as named parameters in JDK5. Besides, you can emulate them very easily with constructs such as:

    new Windows().width(100).height(40).color(BLUE);

    --
    Cedric
  5. Constructors (or methods) with more than a few parameters. I think Java 5.0 solves some of that with named parameters.
    There's no such thing as named parameters in JDK5. Besides, you can emulate them very easily with constructs such as:new Windows().width(100).height(40).color(BLUE);-- Cedric
    Ok. Not sure where I saw that then. Oh well.

    Right, that is a cool way to do it (smalltalk like?) but that isn't the same as having many parameters for method.
  6. Why Getter and Setter Methods are Evil," also by Allen Holub
    I have been looking for that article. I've mentioned it in a few posts.

    Holubs article is utter nonsense, IMHO.

    He makes two points, both of which is invalidated by the fact that most well-designed applications separates domain objects from service objects. The objects that have getters and setters (a.k.a. attributes) are the domain objects. This is information and information is typed. His point about the difficulty of changing type is also plain stupid - ever heard of refactoring tools?

    Getter/Setter have lots of positive sides, though, like improved tooling support, interception and implementing optimization of how stuff like collections are processed (for instance, lazy persistence/serialization.)
  7. Holubs article is utter nonsense, IMHO.
    I wouldn't say it is utter nonsense. I would, however, like to see the "displayYourself" fleshed out.
  8. Mr. Holubs makes a lot of flamboyant claims like the comment in the Java World article dated 2003: "Why getter and setter methods are evil". In this article Mr. Holubs states: "Though getter/setter methods are commonplace in Java, they are not particularly object oriented (OO). In fact, they can damage your code's maintainability".

    But yet, Mr. Holubs fails to state with any real empirical data (as in how much time spent in maintaining code, MTBF, etc...) how setter & getters damage code's maintainability.

    Going around and advocating setter & getters are evil is really irresponsible. If Mr. Holubs was acquainted with “real” OO languages like Smalltalk he would appreciate the fact the only way you could make private data public is through setters and getters!

    Furthermore, Mr. Holbubs fails to understand there are 3rd party tools like Toplink and Cocobase that REQUIRE setters & getters.

    NO, SETTERS & GETTERS are not evil, people like Mr. Holubs who publish garbage opinions are evil (garbage opinions - because he has not established any empirical data to substantiate his opinions)

    Mr. Holubs, show us your really know what your talking about and produce real empirical data that proves your point.
  9. Mr. Holbubs fails to understand there are 3rd party tools like Toplink and Cocobase that REQUIRE setters & getters.NO, SETTERS & GETTERS are not evil, people like Mr. Holubs who publish garbage opinions are evil (garbage opinions - because he has not established any empirical data to substantiate his opinions)Mr. Holubs, show us your really know what your talking about and produce real empirical data that proves your point.

    Toplink doesn't require getters and setters. It can use reflection to modify and read the private variables. This is as it should be --> the persistence here is trying to be orthogonal. I'm no great fan of Toplink, but I can verify first hand that getters and setters don't need to be provided. That part of your argument is pointing only to a (imaginary) limitation in the reflection API.

    Getters and setters allow you to violate a number of fundamental principles of OO --> you can break encapsulation, and if you also expose connected objects, you can break the "law of demeter". Whether this qualifies the getter / setter concept as "evil" is another question entirely, but it certainly doesn't help enforce OO maxims.

    Andrew
  10. Maybe I'm not as good of a java developer as I thought I was...

    Why would you slow down the performance of your application for the sole reason of implementation flexibility? And I'm not talking about something like a data service layer which uses reflection to determine the type of a result value in order to know how to convert it.

    I kind of think the other way.. Getters and setters support OOP. If I don't have a setter or a getter for an attribute, then I don't have access to that data element. Refleciton allows for overriding that principle. And there are some cases where reflection is useful.

    Sure, there are coupling concerns. But the cases where the coupling is a concern, the application should be aware it is necessary for whatever reason. You don't destroy performance for the sake of implementation flexibility.

    Think of it this way: If I have a chair made out of wood and one made out of plastic, doesn't the person using that chair know and make the decision based on the properties at that point? I have coupled myself with that chair for specifc reasons. It takes work to change it, but I as the implementer know made that decision.
  11. Getters and setters support OOP. If I don't have a setter or a getter for an attribute, then I don't have access to that data element.

    This is the reverse of conventional OO thinking :-) OO is all about encapsulation of data, and allocating appropriate responsibilities to classes. So, a class should not expose its "insides", but should provide a reasonable service / methods which allow the correct effects to be achieved. To take a real world analog, the ideal of encapsulation is having a TV with a button to turn it on, rather than allowing anyone to fiddle with the inside mechanics and circuitry (via setters and getters). The logic about how it is turned on is contained solely within the TV set, and because the internal state is only manipulated by the set, then the TV logic can make assumptions about the fact that the state is consistent.

    The bottom line with setters is that they quickly break the principle of encapsulation and a class can no longer assume that it is control of its own state. Dealing with an arbitrary set of states (on the assumption that anyone can change the state at any time) is a much harder problem than dealing with the subset of states that you (as the class owner) will set.
    Refleciton allows for overriding that principle.

    Exactly so. Reflection provides a way to bypass encapsulation, generally for the purposes of building infrastructure. In many cases, you can think of this infrastructure as being at the same level as the fundamental building blocks of the language. In the CLOS MOP (common lisp), you use reflection to actually extend the language. i.e. if you don't like the way multiple inheritance works, customise it! The idea is to use the power of reflection to build up powerful mechanisms which then subject general programmers to the rules you have set down. The idea isn't to allow reflection for its own sake, so that people can dig into a class whenever they want to set the state.

    Andrew
  12. This is the reverse of conventional OO thinking :-) OO is all about encapsulation of data, and allocating appropriate responsibilities to classes. So, a class should not expose its "insides", but should provide a reasonable service / methods which allow the correct effects to be achieved.

    That was my basic point. The gettters and setters allow objects to access its insides when needed.. That doesn't imply that there should be getters and setters for all attributes, just those that the outside world needs access to. All other attributes should be manipulated as needed from the internal to the class.

    Reflection is kind of like X-Ray devices.. Good when authorized and required, bad when in the wrong hands :)
  13. What about an object whose sole intent is to store some data while being transported from one layer to another? Such is the role of a VO, or a struct in C++. Wouldn't it be reasonable in this specific situation to provide getters and setters, since it would be part of the object's responsabilities to be able to store and retrive bits of data for layer communication? In other cases, I igree getters and setters would be "evil", but in this specific one, it seems they are part of the object's behaviour. Unless there are other ways an object can present its data besides using getters/setters (GOF's state pattern, for example?).

    Regards,
    Henrique Steckelberg
  14. I meant GOF's Memento pattern, instead of State pattern.
  15. What about an object whose sole intent is to store some data while being transported from one layer to another?

    If I understand your comment, then you are basically looking at a situation where it is necessary for an object to be able to know all about the internals of another object. I don't have a problem with having getters and setters for all attributes, if there is also a security mechanism around them. I'm not talking about private/protected type.

    My appendix is private to me, but I'll allow a doctor to operate on it. No one else. That doesn't mean, that I'm going to allow just ANY doctor to look at my appendix. He has to go through a strict process to gain access. Reflection is the guy who just ties you down and cuts you up.
  16. Reflection is the guy who just ties you down and cuts you up.

    Shouldn't your bodyguard (the SecurityManager) prevent that?
  17. What about an object whose sole intent is to store some data while being transported from one layer to another?
    Then that object really doesn't need accessors - if that is its sole intent. If it does anything more than that it isn't a DTO/VO/struct.
  18. What about an object whose sole intent is to store some data while being transported from one layer to another? Such is the role of a VO, or a struct in C++. Wouldn't it be reasonable in this specific situation to provide getters and setters, since it would be part of the object's responsabilities to be able to store and retrive bits of data for layer communication?

    Yes -- it is reasonable for exactly the sorts of situations your mention. The key is to be pragmatic, and recognise that it is not setters and getters you want to get rid of specifically, but rather that you want to promote the use of encapsulation for your application, and appropriate allocation of behaviour, and getting rid of them is a side effect of this. You do this to increase maintainability, amongst other reasons.

    I have used pure data structures many times for communication, or persistence (i.e. the MOF in UML uses this approach), but I try to keep the data classes, and the classes containing the app logic separate.
     In other cases, I igree getters and setters would be "evil", but in this specific one, it seems they are part of the object's behaviour. Unless there are other ways an object can present its data besides using getters/setters (GOF's state pattern, for example?).Regards,Henrique Steckelberg

    I'm not sure that "evil" is a particularly helpful word for Mr Holub to have used. As an alternative to getters, as you mention there are sometimes patterns, such as double dispatch and memento, which can be used to allow each class to handle its serialisation, rather than exposing all the insides. I've used this approach for undo/redo support in a graphical case tool, which avoids having to expose all the insides of each object. Again, it's "horses for courses", but the general principle is to try to encapsulate where possible.

    "Behaviour" is generally more complex than a simple get or set, unless it is a pure value object. If the get is more complex than a simple field translation, it probably can't be called a getter any longer, and falls into the category of the class' behaviour, and should be designed and treated as such.

    Cheers,
    Andrew
  19. Putting out the fire...[ Go to top ]

    It seems to have been Allen Holub's intention to document this issue in such way in order to ignite so flames... I suspect it is difficult otherwise for someone to get out of their usual, known and comfortable ways of doing things. Once the flames attract enough attention it's responses like Andrew McVeigh's that package this [same!] content in a way that is easily considered and hopefully accepted. Good job Andrew! :-)
  20. typo[ Go to top ]

    so flames...
    Meant to type 'some flames...'
  21. More on getters and setters
  22. What about an object whose sole intent is to store some data while being transported from one layer to another? Such is the role of a VO, or a struct in C++. Wouldn't it be reasonable in this specific situation to provide getters and setters, since it would be part of the object's responsabilities to be able to store and retrive bits of data for layer communication? In other cases, I igree getters and setters would be "evil", but in this specific one, it seems they are part of the object's behaviour. Unless there are other ways an object can present its data besides using getters/setters (GOF's state pattern, for example?).Regards,Henrique Steckelberg

    A class with public members.
  23. That’s what happens, in my opinion, when certain methodologies or believes are taken beyond any reason… Author suggests that if we have, for a example, a class Person (with usual fields) we must not have getName() method but instead have printNameInHtml(), printNameInSwing(), saveNameIntoDbRow(), etc… so that Person class has minimal external coupling possible (never mind the fact that this class will be internally coupled to half of J2EE by the time author adds all the necessary methods to it).

    Obvious absurdness of this approach doesn’t deter the author from claiming that this is the only right way to do OOP. Even more bizarre is that many other suggestions are reasonable and well-understood such as hiding implementation, balancing cohesion/coupling, etc.

    Best,
    Nikita.
  24. Obvious absurdness of this approach doesn’t deter the author from claiming that this is the only right way to do OOP.
    He may be right - but pure OO isn't always the best design.
    Proven architectural strategies such as layering are often at odds with OO encapsulation. I don't see too many designs that really bundle data and behaviour together in each object.

    Using pure OO for larger systems would result in a lot of the scattering and tangling problems pointed out by the AOP crowd.
  25. Getters and setters are *not* evil[ Go to top ]

    For a rebuttal to Holub's article, see:

    http://www.beust.com/weblog/archives/000022.html

    --
    Cedric
  26. Here lies the difference between an engineer and a programmer. Stating that getters/setters are "evil" due to type safety is what I would expect a first to second year programmer to say. Rarely does the type of data you deal with change, it is what you do with it that does (and that is what OO helps you to change). For the sake of argument, lets say that your type of data is volatile. Then perhaps you should not be using a typesafe langauge. My point here is that if you understand the problem and you actually sit down and design a solution you won't have these "problems".

    The author seems so surprised that when the requirements change, (gasp), code has to change. Again, this comes to design. When you first sit down, you go and target areas in which customization/changes will most likely occur and design for it.
  27. That’s what happens, in my opinion, when certain methodologies or believes are taken beyond any reason… Author suggests that if we have, for a example, a class Person (with usual fields) we must not have getName() method but instead have printNameInHtml(), printNameInSwing(), saveNameIntoDbRow(), etc… so that Person class has minimal external coupling possible (never mind the fact that this class will be internally coupled to half of J2EE by the time author adds all the necessary methods to it).Obvious absurdness of this approach doesn’t deter the author from claiming that this is the only right way to do OOP. Even more bizarre is that many other suggestions are reasonable and well-understood such as hiding implementation, balancing cohesion/coupling, etc. Best,Nikita.

    While reading Mr. Holub's threading book (where he claims that the entire Java multithreading model is fundamentally flawed, then goes on to state that Windows and Unix too are fundamentally flawed) became convinced he's not at all the Java guru he claims to be but rather a Java (if not OO in general) adversary who doesn't really know what he's talking about.
    His postings I've seen elsewhere since have only strenghtened that conviction.
  28. [I] became convinced he's not at all the Java guru he claims to be but rather a Java (if not OO in general) adversary who doesn't really know what he's talking about. His postings I've seen elsewhere since have only strenghtened that conviction.

    He's an author of C programming books for DOS. I owned and read most of them. Back then, I had a lot of respect for him.

    Unfortunately, basically everything he has said with respect to Object Oriented programming has been completely at odds with my understanding of OO. While I admit that he could be right and I could be wrong, a brief look at his most recent article shows that his understanding of even basic facts are wrong.

    To start with:
    .. about the downside of the getter/setter idiom. This idiom was originally introduced in the JavaBeans spec as a way of "tagging" properties of an object so that an external UI-layout tool (called a BeanBox) could build a property sheet for that object.

    This is incorrect. The Javabeans specification was short, sweet and to the point. (I've read it. It was underwhelming.) It provided extremely simple requirements (a no-parameter public constructor and a naming convention for property accessors and mutators) so that classes could be written in such a way that they would be understandable and usable by software tools in general, and by other programmers too. The UI-layout tool called the BeanBox was just a proof-of-concept that this could be applied to graphical components.
    The BeanBox uses the introspection APIs of the Class class to get a list of methods ..

    Again, this is incorrect. Introspection is part of the java.beans package. The java.lang.Class class provides reflection. (Introspection is a higher-level concept that is largely built on reflection.) If a junior-level Java engineer did not know the difference between these two in an interview, it would weigh heavily against their hiring. For a supposed expert who writes books about technology, this ability to put incorrect things into print is beyond belief.

    I hate to be so negative, especially about someone that in the past taught me so much through his writing, but the facts are hard to ignore.

    Peace,

    Cameron Purdy
    Tangosol, Inc.
    Coherence: Cluster your POJOs!
  29. The BeanBox uses the introspection APIs of the Class class to get a list of methods ..
    Again, this is incorrect. Introspection is part of the java.beans package. The java.lang.Class class provides reflection. (Introspection is a higher-level concept that is largely built on reflection.) If a junior-level Java engineer did not know the difference between these two in an interview, it would weigh heavily against their hiring. For a supposed expert who writes books about technology, this ability to put incorrect things into print is beyond belief.
    I'm not a junior programmer, which probably explains why I've heard the term introspection (with a lowercase i) being commonly used as a synonym for "reflection" in Java publications. That's not to downplay the importance of using the right terms, but I don't think its such a big deal.
    One such example is
    http://www.javaworld.com/javaworld/jw-09-1997/jw-09-indepth.html
    If a company asked me the difference between the two in an interview, it would weigh not so heavily against my joining them :-)
    Howard
  30. Again, this is incorrect. Introspection is part of the java.beans package. The java.lang.Class class provides reflection. (Introspection is a higher-level concept that is largely built on reflection.) If a junior-level Java engineer did not know the difference between these two in an interview, it would weigh heavily against their hiring. For a supposed expert who writes books about technology, this ability to put incorrect things into print is beyond belief.

    Although Introspection (capital I, indicating an API presumably) may mean what you indicate, the generic term "introspection" has been around since the old CLOS days and before, and simply refers to the ability of a reflection layer to allow data to be read. The flipside is "intercession", the ability to modify behaviour. Is it not possible that the original poster was using the generic term, or came from a wider background than just Java?

    Part of the problem here is that the Java universe is using (and possibly redefining or subsetting) terms which were in common use when Java was just a twinkle in someone's eye. If you don't know about the older (and better, I might say) technologies such as the CLOS MOP, then this is not the failing of the original poster.

    Sorry to be so negative in response to a negative comment, but the Java reflection APIs and layers above this, although extremely useful, are a poor approximation of the real thing.

    Whatever,
    Andrew
  31. my understanding of OO.[ Go to top ]

    Unfortunately, basically everything he has said with respect to Object Oriented programming has been completely at odds with my understanding of OO.
    Understanding of OO is not equal to understanding of the Sun Java Introspection API, Java's reflection mechanism or the JavaBeans spec... Getters and Setters do break encapsulation - period. Now, how frequently you choose to do so, depends on your situation. Over-the-wire value objects are probably a bad reason to do so! Security risks with serialization should be a reason not to. Check J.Bloch's Effective Java (2nd ed.). Persistence frameworks should also not be a good reason. These frameworks can work without these accessors! Spring DI? Maybe. Just.
  32. Back then, I had a lot of respect for him.
    I hate to be so negative, especially about someone that in the past taught me so much through his writing, but the facts are hard to ignore.
    The little devil on my side wonders if these are related: Why extends is evil Inheritance Depth Record (bad little devil!)
  33. Great news![ Go to top ]

    Reading this article (a good introduction to annotations it is), and looking at the EJB3 Persistence API convinces me that products like JDO and Toplink have a future after all!
  34. An Annotation-based Persistence Framework
    Hmm, I use Annotation-based Persistence for a few years already: that is XDoclet + Hibernate.

    As for getters and setters - they should give way to property keyword of Delphi (Opbject Pascal) style, not annotation:

    property MyType prop;[read getObjectSomehow;][write storeObjectToo;]

    Please do not copy C# ridiculous syntax.
  35. Please do not copy C# ridiculous syntax.

    C# has a clever syntax and it follows the unified access principle [see Meyer].
  36. Personally, I love the way descriptors work in Python...except for the fact that they can become really, really slow when you start doing complicated stuff. But that could be cleaned up by the compiler.

    I've eliminated huge amounts of code in Python by using custom descriptors. I wish they could be added to Java.
  37. Please do not copy C# ridiculous syntax.

    The C# syntax for getters and setters is one of the best out there, along with Ruby's. Both languages allow you to:

    - Respect the Uniform Access Principle and
    - Declare DAO in a couple of lines.

    But maybe you can offer another syntax that's better?

    --
    Cedric
  38. Please do not copy C# ridiculous syntax.
    The C# syntax for getters and setters is one of the best out there, along with Ruby's. Both languages allow you to:- Respect the Uniform Access Principle and - Declare DAO in a couple of lines.But maybe you can offer another syntax that's better?-- Cedric
    It exists for a decade already
  39. Please do not copy C# ridiculous syntax.
    The C# syntax for getters and setters is one of the best out there, along with Ruby's. Both languages allow you to:- Respect the Uniform Access Principle and - Declare DAO in a couple of lines.But maybe you can offer another syntax that's better?-- Cedric
    It exists for a decade already

    Anders Hejlsberg is chief architect for C#. He also created Delphi, so I think we have a draw :)

    http://en.wikipedia.org/wiki/Anders_Hejlsberg
  40. It exists for a decade already

    But isn't this similar to C#'s syntax. It is just a matter of who takes the credit of inventing it.
  41. Great tutorial[ Go to top ]

    He once again proves that he's the master of packaging his controversial opinion in nice written tutorial!

    Last time, he packaged his OO purist ideal into a nice but naive OOP tutorial. This time, he packaged the same opinion in a nice but naive Java annotation tutorial.

    But he made two great progresses this time:

    1. He's more subtle this time by puting his opinion as the sub-title instead of the title.

    2. He finally acknowledges that adding methods like exportToXML() is not the best way, or at least not the only acceptable way, to use an object.
  42. Annotation processor[ Go to top ]

    The article mentions that APT allows us to generate souce code. I didn't find any support for code generation. I am assuming that we need to use something like Velocity for that ?
  43. about Apt[ Go to top ]

    Apt is only for discovering information. And is much like
    JavaDoc Api, but output rendered by Doclet Api.
    And besides Mirror Api (which stands behind apt) is experimental and is subject to change.
  44. He makes at least one incorrect assumption, that a getter method is tightly coupled to the internal field. The fact that a getter returns an int and that the field is an int is purely coincidental and to think otherwise is a mistake.

    "...If you need to change the way the object is implemented in such a way that the type of X changes, you're in deep trouble. ... "

    If my getter returns an int that is the result of a determination that the int is of sufficient precision to satisfy a contract that the object has with the code that uses it. If internally I want to use a long or a float, there is no implication that my getter method also changes; my implementation has changed and not the contract with other objects.

    An example of this might be a sensor aggregator that collects input from multiple sources and perhaps increments internally in steps of .05 and stores it in a double. It may have a getter that returns the value as an int, if that is what the design calls for then, so be it. In such a case, a floating point internal representation is appropriate while representing it externally as an int is equally so.

    It's also possible to make the case that the value of the getter actually maps to multiple fields and doesn't even exist as a discrete unit. While he might have a point, making it too broadly is not wise.
  45. Obviously you cant handle objects[ Go to top ]

    You know, the alledged 'Getter/Setter' problem is way beyond you. I read your ridiculous nonsense about it and it's crap.

    Objects dont cut it alone. Ever hear of 'layered applications?' Like uh, MVC or anything that split the responsibilities in a complex system into layers?

    Duh! like only Business objects and Data transfer objects play the getter/setter game in a layered app and theres nothing wrong with the access they give. Its not direct field access you dufus. Its controlled public access. It cant implement every business rule on the setter but that why we have *rules engines* and other quote 'layers' to handle the complexity of the real world.

    Well, I guess if every class could naively assume all the roles an object needs to play in a *real* app they would be a hidin that data. But as things are now, they cant hide anything because there only role is to ahem...hold state! um gee how lame. Im sorry your OO is in a book the rest of our OO is in the real world.

    Yeah I'll try to do better on my data hiding on my old fashioned EJB's. If I can get them started. (I think its half gas and half oil in the tank).
  46. Article title misleading[ Go to top ]

    The title of this article is misleading. I was expecting Holub to discuss how to significantly reduce Java code bloat by using an annotation that would auto-magically create the necessary getter or setter in byte code (compile-time). After my disappointing discovery that this was not the topic of the article, he makes a slightly interesting point, but definitely does not solve the biggest (by far) JavaBean philosophy effect: massive code bloat! I've been looking at ways to create a Java annotation that would do what you can do in Ruby so well: class FXSpot < TradableSecurity   attr_accessor :base_currency, :quote_currency, :rate end </code> One line replaces 15 lines of code that you would write in Java (not including brace style preferences). If anyone does know how to create an annotation that will allow me to do something similar to the above Ruby code, please do post an article. According my limited trials and annotation specs it is impossible to add getters and setters at compile-time to the containing class, only super or sub classes. It also seems like Sun and the JCP are ignoring this issue until Dolphin or JDK 7. Who can wait this long? If I have real success I will also post my findings.