in reply to Re: Are lvalue methods (as properties) a good idea?
in thread Are lvalue methods (as properties) a good idea?

I hear this quite a bit but I never see anyone provide concrete references that really explain why getters and setters are such a horrible thing. I would really love to see more information on this.

Cheers,
Ovid

New address of my CGI Course.

  • Comment on Re^2: Are lvalue methods (as properties) a good idea?

Replies are listed 'Best First'.
•Re^3: Are lvalue methods (as properties) a good idea?
by merlyn (Sage) on Jan 12, 2005 at 21:50 UTC
    Nothing wrong with doing them if you think it all through. But blindly providing getters and setters for all your member variables means you've published your invidual attributes as a public interface for your object, which means that any new version of your object has to support at least that specific interface.

    Your public interface should be carefully considered. If some parts of that interface map into a simple setter or getter, fine, do it. But don't do it blindly.

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

      That sounds perfectly reasonable and is the best defense I've heard of the Anonymous Monk's assertion. However, I have heard (more than once) comments which suggest that all getters and setters violate encapsulation. Such blanket assertions usually make me very suspicious as to whether or not the person making the statement has really thought things through. Dogma scares me.

      Cheers,
      Ovid

      New address of my CGI Course.

Re^3: Are lvalue methods (as properties) a good idea?
by jplindstrom (Monsignor) on Jan 12, 2005 at 23:14 UTC
    It's not the getters and setters that ar bad, but using them to upset Mr Demeter.

    See also: Re^4: Law of Demeter and Class::DBI

    IMHO the Law of Demeter isn't like the speed of light, but it's a pretty good heuristic for OO design.

    /J

      I tried to find a concise explanation of the Law of Demeter, and my brain melted.

      The best I could find was wikipedia's entry on law of demeter.

      "More formally, the Law of Demeter for functions requires that a method called from an object may only invoke the methods of the following kinds of objects:
      1. itself
      2. its parameters
      3. any objects it creates/instantiates
      4. its direct component objects
      In particular, an object should avoid invoking methods of a member object returned by another method."

      There is TONS written about LoD when googled, but nothing that gave me a real "aha" feeling. It all left me wondering, is this real insight, or cargo cult programming?

      Hopefully the above definition will help a bit.

      thomas.

        As I understand it, the LoD is about not spreading knowledge (about the relationship between objects) all over the place.

        Let's say object A has a method foo() that does something useful. Object a (instance-of class A) has-an object b that implements the useful thing.

        So the call chain is a->b->foo(). But that exposes the fact that a has-a b, when in fact that information could be private to class A. According to the LoD, the call chain would be a->foo(), and that foo() would be implemented as b->foo().

        Taken to an extreme, this is the “bloated middlemen classes full of forwarding methods.” that Aristotle talks about in Re^3: Are lvalue methods (as properties) a good idea?. If large parts of the interface of B is duplicated in A, what's the point? Isn't A and B pretty tightly coupled anyway?

        On the other hand... What if the call chain is a->b->c->d->foo(), and you type this monster at 108 different places in your program? Wouldn't it be a bit nicer to type a->foo() and encapsulate the knowledge of b->c->d->foo() so it doesn't break at 108 different places if any of b, c, or d changes?

        This is why the LoD shouldn't be a "law" to be followed at all times, but a rather a guideline. Or as the Pragmatic guys phrased it in an article I read somewhere: The Pretty Good Idea of Demeter.

        (hey, I just found it. The Art of Enbugging. It's really good and, of course, explains it a lot better than I can).

        IMHO,

        /J

        I don't think the Law of Demeter should be called a “Law”, FWIW. It should more reasonably be called a “Rule” or maybe even just “Guideline”. I've seen someone aptly describe the effect of dogmatic adherence to the LoD in large frameworks as “bloated middlemen classes full of forwarding methods.” Clearly, while tight coupling and low cohesion are undesirable, decoupling and cohesion taken to the extreme mean that a unit fulfills an infinitely narrow task with infinitely minimal communication with the rest of the world — in other words, it's useless.

        In a GUI widget whose purpose is to contain other widgets, f.ex, it's fine to assume knowledge that an instance of this class will have children, and to reach for these children through the container class.

        Makeshifts last the longest.

Re^3: Are lvalue methods (as properties) a good idea?
by eyepopslikeamosquito (Archbishop) on Jan 14, 2005 at 01:43 UTC
    I never see anyone provide concrete references that really explain why getters and setters are such a horrible thing

    Yes, I dislike emotional words like horrible and evil; writers employ these words as attention grabbers. As merlyn explains nicely, they are not always horrible or evil ... but can be if used unwisely. As usual, there are tradeoffs involved and mindless slogans cannot replace sound judgement, experience and good taste.

    A couple of general references that discuss this are:

    Allen Holub JavaWorld article Why getters/setters are evil
    AccessorsAreEvil
    TellDontAsk

      That javaworld article just seems to be saying that if a field should not be accessible outside the object then adding setters and getters is a bad idea. Of course it is, if people are doing this then they're very very silly.

      He doesn't seem to address what, for me, is the main reason to use setters/getters, that is add even more encapsualtion and hiding by protecting the user of the object from it's internal representation. As far as I can tell from the article, he thinks raw field access is OK if the fields are part of the public interface. This causes plenty of problems too when you want to change the internal representation of the object's data. If you have lots of code that goes poking around inside the fields directly then all that code will break if you want to change a field.

      This is a similar sin to the one he's trying to avoid. They both come from including things in the public interface that are not necessary and which could change in the future.

      The "answer" for me is that fields should never be part of the public interface and for those fields that need to be accessed from outside, you should write public getters/setters so that if those fields ever change their meaning or you change your object from using x,y coordinates to using r, theta then you just have to rewrite getX, setX, getY and setY and all your old code will still work.

      Having said that some languages (Perl with lvalue methods, Object Pascal with properties) allow you to have fields that seem to be normal fields but actually they result in a call to a getter/setter method. This to me seems to be the ideal solution. For example in Object Pascal when you write object.Field = 5 you don't know whether that will directly write to memory or whether it will call object.setField(5). What's great here is that the user of a class doesn't need to deal with setters and getters but the implementor get all the advantages that they bring.

      Finally he uses the example of getX where the return value changes from an integer to a double and he says that all the code that uses getX will need to change to cope with that. Perfectly true but I don't see how you can blame that on getX. If, instead, you access the X field directly then you're still going to need to change all your code. Seems like a silly example to me.