Opinion: Why getter and setter methods are evil

Discussions

News: Opinion: Why getter and setter methods are evil

  1. Opinion: Why getter and setter methods are evil (53 messages)

    Allen Holub is becoming the "Dr. Evil" of Java :) His latest opinion piece talks about why he feels getters and setters are overused, and how they violates the basic object-oriented (OO) principle of encapsulation, so you should avoid them. The article discusses getter/setter cons and offers an alternative design methodology.

    Note that he doesn't say that you should never use them, but is rather making a point about when you should use them.

    Read Why getter and setter methods are evil

    Allen's first article discussed Why extends is evil, and recieved a lot of comments.

    Threaded Messages (53)

  2. I certainly hope that no "new" Java developers read this. This article is borderline damaging.

    Although some of the design recommendations ARE valid, the author should not be blaming getters and setters (accessors and *mutators*) for bad design. Nor should he discourage their use. As with anything, there is potential for overuse. But this IS the standard way to manage the state of a COMPONENT in Java. Sure components have behavior, but they inevitably WILL have to either expose their state or allow manipulation of that state at some point. To discourage the exchange of data among system components and layers is actually LESS object oriented in my opinion and would seem to encourage monstrous classes (the "Classosaurus").

    If a domain object's property type changes from int to long, or long to String, or String to MyNewType: the *LEAST* of your worries will be the getters and setters! Think of the actual impact to the logic and semantics of the system! It likely means more than simply "I need a bigger number". It's more likely that it means "this number means something completely different". Not to mention, it's not just the getters and setters that suffer from this, it's EVERY method in the system that uses this data! Whether it's all bundled up into one class (as the author would seem to suggest), or if it's cleanly "componentized", you still have to change it! It's not like there's less code.

    Furthermore, making such changes has less to do with design, and more to do with methodology and practices IMHO. With an appropriate suite of unit tests and a refactoring strategy (and tool), such changes (if not easy) are at least controlled.

    Finally, the author speaks as though Java is the ONLY language with accessors and mutators and is therefore a flaw of Java alone. What about Delphi (Object Pascal) and C#? In these languages not only are accessors and mutators recommended by pattern, they are a FEATURE of the language (a feature I would like to have in Java --"real" properties).

    Just my opinion...

    Cheers,
    Clinton
  3. Opinion: Why getter and setter methods are evil[ Go to top ]

    Although some of the design recommendations ARE valid, the author should not be blaming getters and setters (accessors and *mutators*) for bad design.


    I'm not sure the author is blaming getters and setters for bad design. It's more the other way around: I think that the point he is trying to make is that too many public getters and setters may be a symptom of bad design, what Martin Fowler might call a "bad smell".

    I do agree with you, though, that this article is probably not a good one for beginners because they will read it as "don't use getters and setters" which isn't what it's saying. The article is better aimed at more experienced developers to challenge them to sit back and look at the habits they've built up and say "is this the best way to do it or can I do it a better way?".
  4. I think the author has a valid point. But I don't think he makes it very well. If I understand him right, then this is what I believe he is saying (summed up a great deal.)

    * Don't build objects which contains lots of _public_ get/setters. This avoids un-necessary exposure of any data which is not _explicitly_ needed.
    * Don't have one object which holds the data, and another which does things with it. One of the best ways I ever heard a class described was "A bunch of data that knows what to go do with itself." The class does the work and contains _most_ of the data needed to do it. The rest of the required data is passed into public method calls.
    * Don't confuse getXXX with getYYY. The "get" prefix may be incidental. One may simply return the value of a private field. The other may do a calculation. The former is to be avoided unless _absolutely necessary_ and the latter is the way an object is supposed to work.

    In certain cases we use a Memento design pattern, or a "value object" and in those cases we have get/set methods. A JavaBean, as generally used, is a classic example of this. This isn't bad, but we need to be careful. Again, the rule is simple. Don't expose information unless it's vital to do so and don't delegate business logic to some other class if you're the one with all the data.

    I think the points above are valid OO design considerations. Had they been stated that way I think the reaction may have been less contentious. :) As written, the article only makes sense to people who've experienced what the author is talking about in terms of spaghetti code. I do however, agree with his general point.

    As to the second post in this thread...yes, I agree that if an int changes to a long then it's possible it's part of a more fundamental change. But we should always design with change in mind. We know things will not remain the same, so why give out the field information unless we have to. If we can hide it behind a method call which does a calculation using that information then we're in better hands. I accept that if an private field used in a calculation behind a public method changes from int to long then the return value of the method probably also changes. However, a method call is probably used less than the corresponding 3 or 4 getXXX methods which then did the calculation.

    In the end it's all horses for courses. And in any event you can break any design paradigm if you try. If this were easy we wouldn't get much of a kick out of building things. :)

    Chz

    Tony
  5. <quote>
    > * Don't build objects which contains lots of _public_ get/setters. This avoids un-necessary exposure of any data which is not _explicitly_ needed.
    > * Don't have one object which holds the data, and another which does things with it. One of the best ways I ever heard a class described was "A bunch of data that knows what to go do with itself." The class does the work and contains _most_ of the data needed to do it. The rest of the required data is passed into public method calls.
    </qoute>

    Well.. as someone already pointed out, at the very least you need to set the initial state somehow and then later on represent that state to the outside world. Is a bunch of getters and setters more or less evil than one GS with a data object?

    Especially when you have the infamous crosscutting concerns that the same object needs to do - do you really want to put all in the same class? Isn't that something that's against good design principles as well?

    How does this reconcile with his previous "Extend is Evil" article? When I delegate something, I need to delegate (at least part of) state as well. I wouldn't have to if I did extend :).

    My thoughts on this are: make you instance variables private and provide protected level access getters/setters. Make the getter setter public if you have to, but not before. Try not to use getter setters before you have to - for example, if all you'd do is to delegate a call, put that delegation in the class itself.

    Unfortunately, a lot of this can lead to quite chunky classes that do nothing but delegation - and that could be reasonably easily machine generated. I hope that use of aspects (be it AspectJ or anything else) will help to do this more properly.

    Regards,
    Vlad
  6. beware of evil things ![ Go to top ]

    Did you notice the article "Why extends is evil" ?

    It reminds me a witch-hunt.

    What is gonna be considered evil next ?

    collections ? inner classes ?

    There are some valid points in those articles but the title....
  7. beware of evil things ![ Go to top ]

    How about "Why Inflammatory Article Titles are Evil"?

    I agree with most of the folks here: the basic point is sound, but the specific arguments made by the author are weak.
  8. beware of evil things ![ Go to top ]

    How about "Why Inflammatory Article Titles are Evil"?

    >
    > I agree with most of the folks here: the basic point is sound, but the specific arguments made by the author are weak.

    Already done :-)

    --
    Cedric
    http://beust.com/weblog
  9. ...and add SmallTalk

    >Finally, the author speaks as though Java is the ONLY language with accessors and mutators and is therefore a flaw of Java alone. What about Delphi (Object Pascal) and C#? In these languages not only are accessors and mutators recommended by pattern, they are a FEATURE of the language (a feature I would like to have in Java --"real" properties).
  10. C# does better in this field.

    Though C# still use accessors for fields, it hides the detail and provides transparent access for the fields:

    private int _count;
    public int count get { return _count; } set { _count = value; }


    This enables users to use "obj.count++;" instead of "obj.setCount(obj.getCount()+1);"

    I hope Java would provide similar solution in the language some day!
  11. Opinion: Why getter and setter methods are evil[ Go to top ]

    In a message by Bin Sun, they sayeth:
    >This enables users to use "obj.count++;" instead of
    >"obj.setCount(obj.getCount()+1);"

    >I hope Java would provide similar solution in the language some day!

    It does. It's called obj.addOneToCount()

    What you have done is exactly what the original paper was (badly) trying to convey, and what others have clarified.

    The interface should provide for the semantics of the object, and not just raw syntax for manipulation of the object. Why do we need a "setCount" if all that happens is that it is incremented ? Maybe the semantics are better expressed as:

    initCount()
    incrementCount()
    getCount()

    Cheers,
       -- jon
  12. Convience is always welcomed![ Go to top ]

    In a message by Bin Sun, they sayeth:

    > >This enables users to use "obj.count++;" instead of
    > >"obj.setCount(obj.getCount()+1);"
    >
    > >I hope Java would provide similar solution in the language some day!
    >
    > It does. It's called obj.addOneToCount()
    >
    > What you have done is exactly what the original paper was (badly) trying to convey, and what others have clarified.
    >
    > The interface should provide for the semantics of the object, and not just raw syntax for manipulation of the object. Why do we need a "setCount" if all that happens is that it is incremented ? Maybe the semantics are better expressed as:
    >
    > initCount()
    > incrementCount()
    > getCount()
    >
    > Cheers,
    >    -- jon

    Your solution brings some business logic to the class, and this is not desired for some designs which would seperate logic from data representation classes.

    Like generics in JDK1.5, programmers surely can write more code to do the same thing as typed collections, but we do like typed collections because it brings much convinience without harming readability of the code.

    I should say: convience is always welcomed, and this has always been the sharp weapon of Microsoft.
  13. C# does better in this field.

    > private int _count;
    > public int count get { return _count; } set { _count = value; }

    Indeed. But it wasn't Microsoft's idea. Many languages that predate Java use the same approach. The inventors of Java left this out on purpose (just like templates). They didn't want to commit to anything too grand in the beginning (which makes the "event" fiasco quite humorous). Simplicity was the order of the day and a goal of theirs was to have "only one way to do any given thing" (which makes AWT vs. Swing humorous). The idea was that code would be more consistent and clear, which I don't necessarily disagree with.

    I do however agree with you as well, that this seems to be proven enough that Java should now adopt such an approach, and in addition, include the appropriate reflective capabilities to "talk" to properties via the reflection API.

    Cheers,
    Clinton
  14. This is neither pro or against OO techniques and I think this guy is only suggesting we think about how we offer access to an objects properties.

    Having public accessors 'protecting' a private property would need a business case, this would more than likely become a method that would encapsulate more than one property and thus remove the need for a number getter/setter methods that may have to repeat some core functionality.

    So I kind of agree with Mr Holub on his larger point of design before code.
  15. The bulk of the article is, IMHO, nonsense, and is full of double-speak and loose terminology. The idea is simple, but the author conveys it very, very badly.

    All he had to say was "Don't design a class' API to mimic its internal structure - design the API to convey the semantics you want to expose. For simple classes, the internal structure may coincidentally mimic the API; for more complex cases, this is increasingly less likely to be so".

    The problem is, the author obsesses on accessors/mutators, and builds up an argument which is indefensible. Put simply - how do change an object's state with no mutators? How do I get any information out of an object without an accessor? According to the author, you should almost never let people get state information or change it - an object should just have a "drawMySelf()" or doIt method that magically does everything. Of course, this is circular reasoning - somewhere down the line someone's gonna have to give up their state, or allow users to change it.

    Most likely, the article wasn't written to convey the simple idea (class API should be semantics, not internal structure) because you can't sell that. It's too close to common sense to sell books and training courses on it.

       -Mike
  16. presuming good will?[ Go to top ]

    <fromMikeSpille1>
    The bulk of the article is, IMHO, nonsense, and is full of double-speak and loose terminology. The idea is simple, but the author conveys it very, very badly.
    </fromMikeSpille1>

    FWIW, I found it clear and interesting. Holub might also have added that a long list of accessors can clutter a class beyond recognition.

    <fromMikeSpille2>
    Most likely, the article wasn't written to convey the simple idea (class API should be semantics, not internal structure) because you can't sell that. It's too close to common sense to sell books and training courses on it.
    </fromMikeSpille2>

    That's certainly a stretch.
  17. presuming good will?[ Go to top ]

    \Bob Stine\
    FWIW, I found it clear and interesting. Holub might also have added that a long list of accessors can clutter a class beyond recognition.
    \Bob Stine\

    Well, he talks about getters/setters in some sections, and accessors in others (and doesn't seem to talk about mutators). He says that objects should mostly know what to do with themselves - the entire "Draw Thyself" section on page 2. He makes the argument that changing a return type to a getter breaks code. He implies strongly that you shouldn't get anything out of an object, or do anything to mutate it. Who goes onto say

      'Though getIdentity starts with "get," it's not an accessor because it doesn't just return a field. It returns a complex object that has reasonable behavior. Even when I have an Identity object, I still have no idea how an identity is represented internally.'

    In all, his idea seems to be (but it's confusing) that Java primitives should never be seen, that classes should work on contexts (which magically also don't expose getters/setters), and makes some content free suggestions like "Don't ask for the information you need to do the work; ask the object that has the information to do the work for you".

    The confusing rambling would have been much clearer if he wrote a 2-paragraph article around "Design your APIs towards desired semantics, not towards your implementation internals".

    <fromMikeSpille2>
    Most likely, the article wasn't written to convey the simple idea (class API should be semantics, not internal structure) because you can't sell that. It's too close to common sense to sell books and training courses on it.
    </fromMikeSpille2>

    \Bob Stine\
    That's certainly a stretch.
    \Bob Stine\

    You think so? From the end of the article: "Parts of this article are adapted from my forthcoming book, tentatively titled Holub on Patterns: Learning Design Patterns by Looking at Code, to be published by Apress (www.apress.com) this fall. "

    It sounds like the stretching is being done by the author.

        -Mike
  18. More Harm Than Good[ Go to top ]

    This article will do more harm than good. The title itself is very misleading and made worse by the fact that it was chosen just to get people's attention. Although it has some very important nuggets of truth (like designing to interfaces, limiting exposure of internal class data, etc.) it is written poorly (lots of useless and conflicting information with some omissions).

    The biggest omission by far is how changing underlying data in a class affects its public members. The author actually appears to associate getters and setters almost exclusively with just passing an internal field back and forth. In reality, getters and setters allow you to mask underlying data, perform validation, dynamically change types, and all sorts of other things (like derived properties). The author should have spent more time on this subject along with more detail on how inexperienced programmers can determine what data a class should and should not expose (and how to safely do it while protecting the internal implementation).

    I would recommend other publications for instruction on getters and setters. One of my favorites is J2EE Design and Development by Rod Johnson.

    What a shame. This article could have been so much better...
  19. Certain architectural layers require that an object expose it's data, such as UI or persistence layers.

    But objects in the business logic layer should model the operations the business fulfills, and while some state must often be exposed by these objects, it should be restricted to the bare miniumum. Use of many getters/setters in this layer probably indicates trouble with the design.

    And that sparks an interesting thought: If you accept that getters/setters should be restricted to certain layers (such as the UI), what techniques would you use to hide data in layers that shouldn't expose it?

    I'm assuming a given object has data that must be manipulated by an Actor and also has associated business operations. For example, an account has all the pertinent client data that must be CRUD'ed by some administration function - using getters/setters. However business logic such as transfering money between accounts requires little access to the client's data - the implementation of the operation should be hidden.

    How do you restrict the system such that administration functions in the UI can access the data but business logic in other layers only see the minimal data that must be exposed to business functions?
  20. I think you kind of nail it.

    The presentations of a particular object must have a far more relaxed access to its class, than, say, other objects. They conceptually belong to that object, so there is no problem having such access. There is a built-in way to do that in Eiffel, but it goes down to the level of method permissions, which I personally find to be too low for that purpose.

    The best way to implement this in Java, I think, is via interfaces -- an object exposes interface A to its UI classes (containing, say, getFirstName() and getLastName()) and a completely different, far more restrictive interface B to the other objects in the system (that does NOT have getFirstName(), etc, but may have getPresentation() instead).

    This is in a sense about architectural layers, but I think it is more accurate to say it is about "chimneys" within the layers -- the UI layer class of an object has relaxed access to the business layer class of that object, but it will have much more restricted access to the business layer classes of other objects. In other words, you can easily go down and up across the layers, but you cannot go left, right, or diagonally without some restrictions.

    P.S. Note that this is not only about interfaces -- you can easily put getX() and setX() methods in the interface that an object exposes. As described above, that would actually be quite appropriate in some cases as well. This is about providing appropriate interfaces (relaxed or rigid) to the appropriate classes.
  21. This article makes a good point that putting getters and setters on objects as a rule of thumb, can result in bad design. If too many attributes are exposed in this way then we are really using classes as namespaces and thus loosing encapsulation.

    What makes this article seem strange at first glance to J2EE developers is that we often use JavaBeans as DTOs and for UI work to set attributes automatically using JSPs. This usage is generally OK as such classes are just data holders.

    With complex domain or process classes getters/setters can result in the almighty god class, which has all the business logic and simply interrogates other classes for their data.
  22. Totally agree with Allen. There is no point to hide field as private, and to expose it immediately with an accessor. I totally agree that simple accessors/mutators should be used in javabeans/transfer objects only, where they are obligatory by corresponding API (UI or database).

    <Tendayi Mawushe>
    What makes this article seem strange at first glance to J2EE developers is that we often use JavaBeans as DTOs and for UI work to set attributes automatically using JSPs. This usage is generally OK as such classes are just data holders.
    </Tendayi Mawushe>

    He was talking about use of accessors in busienss objects, not in data transer objects. Business objects should perform tasks, not giving away their properties. Well, some properties like state could be exposed, but generally business methods of the object itself should be used instead to perform some meanigful task. The whole idea of an object is for it to be a "structure with behaviour". Exposing internal fields does not add up to the behaviour, it just makes for a more complex structure with indirect access to the fields.
  23. I read this article couple of days back and I was just thinking about this showing up on server-side and opening this huge discussion. I guess we just getting started.

    Here are my 2 cents on the article.

    I think the title is probably more controversial, than the actual article. The writer hasnt said anything new, if you really go ahead and read the entire thing, you would probably say yeah I think I already knew this. This just served as a nice reminder. The author also ends up saying that its just a design strategy, an alternative, no hard n fast rules. I think thats fair enough.

    Kapil
  24. The author has a little bit of a point, but runs with it in the wrong direction.

    The problem isn't the accessor methods -- the problem is the *interface* exposed by the objects. Objects and components need some mechanism to allow them to be configured before use, a JavaBeans properties are the "linga franca" for accomplishing this ... its a simple system, a good system and one that works.

    If invoking those accessor methods becomes a liability, then the accessor methods should simply not be part of the object or component's interface, they should be an implementation detail.

    Likewise, if there are other, non-accessor methods which have special semantics, those too should be in the implementation and not in the interface.

    To some degree, everything old is new again ... 10 years ago in C and PL/1 I had a header file (equivalent to the interface) and a source file (equivalent to the implementation class). Anything private to the class was simply not put in the header file.

    The mention of the @property construct from JDK 1.5 is misleading; the most likely implementation of that is a instance variable and a pair of accessor methods. The define property is still going to be part of the implementation class's interface in one form or another ... so you're back to the same point.

    One of the excellent things in HiveMind (http://jakarta.apache.org/commons/sandbox/hivemind/) is a very, very strong division between interface and implementation. Between all the proxies and interceptors, the service object that user code interacts with will almost never be the service implementation class ... you can't bypass the service interface to, say, set properties of the implementation class even if you KNOW the implementation class; the proxy or interceptor will be another class entirely (generated at runtime using Javassist).
  25. I agree with this. The JavaBeans/introspection APIs provides a great way to configure/initialize an object before it is used in a way that is flexible. I frequently use this pattern to read an object's configuration from a store and then set the state required for operation.

    If this state initialization only needs to happen once; right, simply make it an part of the internal implementation and not part of the public interface (the interface should be immutable and only expose necessary properties.)

    Alternatively, you can expose an initialize(Settings) method that takes a Settings data transfer object providing the state the object should initialize to. Or just use a constructor to do the same thing. In this case, some other object would be responsible for instantiating the object and initializing it. The implementation can then enforce this method is called only once.

    Here is an example:

    ServiceImpl implements Service

    ServiceImpl implementation setters for state:
      public void setName(String name) {...}
      public void setDescription(String description) {...}
      public void setPort(int port) {...}
      public void start() {...}
      public void stop() {...}
      
    Service interface only exposes getters:
      public int getPort()
      public String getName()
      public String getDescription()
      public void start()
      public void stop()

    One option: ServiceImpl could load herself from a persistent store and initialize herself.

    Another option: Some other object could access persistent store, and construct ServiceImpl object. Introspection could be used to map persisted Service state into a DynaBean or Settigns object to setters in implementation method. Clients are never exposed to this interface. I prefer this approach.
  26. Exactly but with a slight twist[ Go to top ]

    I agree with this idea, all we need is two interfaces for accessors and mutators seperatly, and then provide one implementation. Expose what is actually necessary through the interfaces. Use acessor interface for readonly tasks and uses mutators for read and write tasks.
  27. Opinion: The author is evil.[ Go to top ]

    "Getter and setter methods (also known as accessors) are dangerous for the same reason that public fields are dangerous: They provide external access to implementation details."

    No, they absolutely do not.
  28. Opinion: The author is evil.[ Go to top ]

    Agree,
    think about "lazyInitialization" without get/set.
  29. Misleading topic[ Go to top ]

    I agree with the author in term of design with less data (or logical representation of data) flowing around.

    However, the author tends to forget that a good design is the design that uses patterns, specifically the Value Object pattern. Design Patterns are never changed (or at least very static), whether we use getter/setter to assist the implementation of patterns or not, is the LEAST problem/issue that we need to worry about. Remember that architecturally are harder to fix than the compile error due to the getter/setter.

    Also remember OO do have its weakness. Hybrid (OO and Procedural) may be best for your particular solution.

    huy
  30. Re: Misleading topic[ Go to top ]

    a good design is the design that uses patterns


    No, good design has nothing to do with patterns. You can mess up completly with patterns (overdesign), as well as you can do great design without any patterns at all.

    Good design is good design, no matter if patterns are used.

    Design patterns is just a tool in the toolbox. Remember 'If all you have is a hammer, everything looks like nails'.
  31. Misleading article[ Go to top ]

    Typical Holub sensationalist style with not much meaningful content. I posted a few additional thoughts on my weblog about this one.

    --
    Cedric
    http://beust.com/weblog
  32. Misleading article[ Go to top ]

    Couldn't agree with you more.

    cheers
    huy
  33. Re: Misleading topic[ Go to top ]

    Agree with u that it is possible to achieve a good design without the need to use pattern (best practice). I would say it easier to achieve it with the use pattern where appropriate.

    At the mid to enterprised application I found that without patterns it getting harder for the developer to pickup and understand (especially some one new to the app). Also, it imposes guidelines (and good pratice) that make application growth/extendable abit easier.

    cheers
    huy
  34. Very valid if taken in the right sense[ Go to top ]

    I think this article is a PG13 artcle :-). "New" java developers should have "parental guidance" in reading this and when watched as a PG13, it is just an amazing artcle. I think I have seen enough code, which tempts developers to break open encapsulation because of getters. The get x from ClassA and y from ClassB and do the business logic related to ClassA in ClassC and totally break open the can of worms. I think the point the author is trying to make is clearer if you know CRC cards. A CRC cards based design session obviously will reduce the ocean of getters and setters you have. You will be more oriented towards collaboration between classes and "their" responsibilities than taking his responsibility and asking someone else to do it (bad!).

    I am sure anyone who has seen fresh guy;s code in any OO language would have seen this.

    -Sanjay
  35. Very valid if taken in the right sense[ Go to top ]

    Sorry for the sarcasm, but yes - if we see a bunch of hand-drawn diagrams on cheap index cards, all will be much, much clearer. If you use one card per class, and arrange the cards to show your class diagram, naturally your design will be much clearer and correct.

    I'm sorry, but CRC cards is one of the more ridiculous things I've seen come out of authors and consultants in the last few years.

        -Mike
  36. Very valid if taken in the right sense[ Go to top ]

    Mike:

    I am afraid you are wrong. CRC cards does not necessarily mean you need to carry those "hand drawn bunch of cards". The idea is that once you do it, you get the idea and you can do it again and again without those "bunch of cards". It actually changes the way you think and not taht you need to carry "bunch of cards" with you wherever you go. I beg to differ and as an example, many of the Fortune 20 (Dont ask me how i know) company dev. centers use it successfully for several years - the "idea", the "mindset for design" NOT the "bunch of cards".

    -Sanjay
  37. Allen speaks again...[ Go to top ]

    The getters and setters are quite necessary because Java breaks the fundamental idea of "uniform access method", coined by metrand meyer and now implemented in C#, Eiffel and Ruby.

    Allen Hobub is - as usual - completely of track. He is simply not a very smart guy, but he is unfortunately a good writer, making a lot of newbies believe his horseshit.

    His "damnations" series would be interesting if they contained technically plausible arguments. A very few of his point do, but most don't.
  38. Curious...[ Go to top ]

    Just curious...

    How many times have you seen (or written) JSP, Struts, or some other code like this in a _page_:

    <%= customer.getFirstName()%> <%= customer.getLastName() %>
    <img src="<%=customer.getPictureURL()%>">

    Do you think this is the right way to do things? Would it save you time at the end?

    And if your answer of the above is 'no', how would you do that "properly" in JSP? (or Struts, etc)
  39. Curious...[ Go to top ]

    Mmmm, I'd vote for

    ${customer.firstName} ${customer.lastName}
    <img src="${customer.pictureURL}">

    :) Is anyone (including AH) arguing that it'd be better to pull the HTML generation into the Customer object? <shudder> Think not.
  40. Curious...[ Go to top ]

    Hi,

    > Mmmm, I'd vote for
    >
    > ${customer.firstName} ${customer.lastName}
    > <img src="${customer.pictureURL}">

    Ok. In a typical web application the person will need to be shown on, say, 30 to 50 pages, and the above will be included in each of these pages.

    Now, suppose that the client comes knocking on your door in a hurry and says "You MUST also display the person's title! Professors and Doctors are extrmely sensitive when showing their title is concerned!". This is not a made up story -- I've had exactly the same request (requirements change) a couple of times since the beginning of the year.

    So, you go to each of these 50 pages and change the above code to:

    ${customer.title} ${customer.firstName} ${customer.lastName}
    <img src="${customer.pictureURL}">

    I am asking again: is this a good solution? Does it save you time? What is the alternative?
     
    > :) Is anyone (including AH) arguing that it'd be better to pull the HTML generation into the Customer object? <shudder> Think not.

    No, not at all. But please tell me what a better solution than the above would be.
  41. Curious...[ Go to top ]

    Ok. In a typical web application the person will need to be shown on, say, 30 to 50 pages, and the above will be included in each of these pages.

    <snip>
    > So, you go to each of these 50 pages and change the above code...
    <snip>
    > No, not at all. But please tell me what a better solution than the above would be.

    If you have exactly the same piece of display content used on 30 to 50 pages then surely you should have this in a separate jsp stub that you include into each page where you need it?
  42. Encapsulation of Display logic[ Go to top ]

    Well in JSPs you could create a Person JSP Tag. Then you use this tag on the 50 other pages that display a person. One place to change the code.

    This tag could be enhanced with more than one "formatters" to allow for different Person rendering strategies, if needed.
  43. Re: Encapsulation of Display logic[ Go to top ]

    Well in JSPs you could create a Person JSP Tag. Then you use this tag on the 50 other pages that display a person. One place to change the code.

     
    Thank you, this is exactly the concept I was looking for. I'd like to make a couple of observations:

    1) Once you have 'encapsulated views', the visual code outside those views (such as the page) does NOT need access to getTitle(), etc. What's more, it should not need such access -- it just uses the view(s) and that's it. Limiting it to using as few methods from Person as possible makes it completely resistant to changes in the Person class.

    2) The only places that would need more 'liberal' access to the object are those views. Only they would likely be affected by changes in the object's implementation. Thus, it is a good idea to keep them close to the object's class, so that when you make a change (a certainty), you would know exactly what else you would need to touch as well. Because of this, those views can be considered essentially a part of the large 'conceptual object' of Person.


    To put this differently, getters and setters like getTitle() do not NEED to be used in the code that is not a part of the 'conceptual object'. They are okay within it, but not outside. If you use them outside, then you doom your program to maintenance -- you will have to run around changing stuff at 50 places for something really small, as the example clearly shows.

    I hope this makes it clear why the article has a very strong practical dimension to it -- it is not just hot air and makes a lot of practical sense.

    Please note that this is just be a rule of thumb -- as AH makes an effort to explain in the beginning of the article, there are no absolute truths. Design is a series of tradeoffs.


    P.S. One final curve ball -- what do you do if the client comes back knocking on your door and says that he needs doctors and professors to be displayed differently than the rest (e.g. doctors in blue, professors with a picture on the left)? And you have that sneaking suspicion that other types of people may follow suit soon?
  44. Curious...[ Go to top ]

    We are also moving forward to JSP 2.0.

    Hope J2EE 1.4 finalizes soon!
  45. Hmm, I seem to be in a minority here, but I would recommend this article to new Java developers, or those new to OO. Mainly because I've seen way too much code written by inexperienced developers who seem to think that exposing every field in a class with a getter/setter is somehow "good OO", when, as this article points out, the reverse is usually true.

    Of course, in enterprise apps things get more complicated because we need to deal with Data Transfer Objects, binding classes (relational, XML) and so forth. But then everything's always more complicated in enterprise apps. :-) And, importantly, these tend to occur on the "boundaries" of the JVM (i.e. communicating with databases, browsers, other applications etc.).

    Okay, the "evil" tag might be over-the-top. But discouraging a knee-jerk approach of "okay, I have a field so I need a getter and a setter" is, on balance, a good thing I think.
  46. Law of Demeter[ Go to top ]

    Allen is speaking of the Law of Demeter.

    Since he referenced Ward and Kent in his article it's appropriate to see http://c2.com/cgi/wiki?LawOfDemeter for the full details and all the discussion you'd ever want on the subject.
  47. Law of Demeter[ Go to top ]

    Allen is speaking of the Law of Demeter.


    I think you are being too generous.First, Allen never uses 'LoD' in the article.
    Second,a strong form of the law uses accessors to access data members defined
    in parent classes:
    http://www.eli.sdsu.edu/courses/fall96/cs535/notes/Demeter/Demeter.html#RTFToC3
    I have heard real time developers advocate using using accessors to access an
    objects own members. This is hard to do without any accessors.

    >Since he referenced Ward and Kent in his article it's appropriate to see >wiki?LawOfDemeter for the full details and all the discussion you'd ever
    > want on the subject.

    You must be thinking of google ;)
    http://www.google.com/search?q=LawofDemeter
  48. "I have heard real time developers advocate using using accessors to access an

    >objects own members. This is hard to do without any accessors."

    Self Encapsulation is also refactoring:
    http://www.martinfowler.com/bliki/SelfEncapsulation.html

    Martin Fowler writes about encapsulating collections in his Bliki:
    http://www.martinfowler.com/bliki/EncapsulatedCollection.html
  49. Law Of Demeter[ Go to top ]

    I find it very odd that this article fails to discuss (or even reference)
    the Law Of Demeter:
    http://www.sharemation.com/dhunter/public/oop/oop.html#DEMETER


    > C# does better in this field.
    > I should say: convience is always welcomed, and this has always been the sharp
    > weapon of Microsoft.

    Convenience as a weapon? But Microsoft favours other weapons.
    C# is an innovation? - I don't think so:
    http://www.pbs.org/cringely/pulpit/pulpit20030904.html

    Microsoft is an innovator? - I don't think so:
    http://archive.infoworld.com/articles/hn/xml/02/12/23/021223hnsendo.xml
  50. equals without accessors[ Go to top ]

    Just out of curiosity, how do you implement/override - public boolean equals(Object o) with out having access to the state via accessors?
    Or, in regards to his previous article, is it evil to extend Object? ;-)
  51. equals without accessors[ Go to top ]

    Well, if you read the text carefully several times, it appears to me that the author is advocating a very Smalltalkian viewpoint. He talks about message sends, not method invocations, and constantly revisits the idea that primitives are bad, objects are good. In some ways I think he's had alot of exposure to Smalltalkers, and doesn't understand the ways in which Java is _not Smalltalk_.

        -Mike
  52. equals without accessors[ Go to top ]

    But you don't need accessors - instances of the same class have access to each other's private variables!!! Try a quick example yourself. ;)

    Paul Carter
  53. I believe the author is talking about an access control policy for an object on the one hand and then transposing that concept onto the getter/setter paradigm. The author talks about restricting access to member data that is available through getter/setters. He then uses an example of how a client of a class can use a getter, and then modify 'private' variables within the class. Duh! That is not a description of the problem he originally asserted.

    Firstly, the large purpose of getter/setter methods is to maintain object integrity for the data members, not for member data access control. For simple data objects such as an account where you can set and get the name of the person's name in the account, a setter object can validate a name to ensure that it is well formed, with a regex or something. When you retrieve a person's name you use a getter method. The author 'over-thinks' the idea and assumes that if you are using a getter method to retrieve a private variable, that you will automatically return a reference to the actual member. Of course this would allow a client of the class to by pass the regex test. So, the simple and obvious solution to the complaints the author has is to return a _copy_ of the data member in a new String for instance. *Boink*

    As for restricting access to getter/setter methods at runtime, well that is a totally different animal and would probably need some sort of proxy object that serves as a gateway to a collection of related objects (or something).

    In C++ you wouldn't think twice about returning a copy of a private data member because pass-by-value semantics are implicit in the language. Obviously with java you must make a copy 'manually' so to speak. The author's article is clearly an example of a 'over engineered' solution to a very trivial 'problem'. Hence, the quotes, because I do not believe getters/setters are actually a problem.

    So for people who agree with the author, yes it is true that returning a reference to a private member is not good design. However, the author is trying to dress this problem up in the clothes of runtime access control of some such confusion. So to summarize: Yes - returning references to private member data is bad design; No - it has nothing to do with a flaw in the getter/setter paradigm. Sheesh, this is covered in programming 101. Why is the author rehashing a solved problem?
  54. Some sanity[ Go to top ]

    For a refreshing view on this debate, read

    Anders Helsberg's interview

    My comments

    --
    Cedric