Fog Creek Software
Discussion Board




Artcile on the evils of getter/setter methods...

Though this article is located on JavaWorld and uses a few Java technologies to prove points, it's really an OO design article and thus, can be applied to any OO language.

http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html?

Anyway, this article was a real eye opener for me.  I've often felt that many of the getter/setters I put into software were somehow unnecessary, but I've never been able to articulate it quite so well as Allen Hollumb does in that article.

*WARNING: NEXT SECTION JAVA RELATED*
Also, he makes a point about the designer of Java beans only meant for the get/set method design thing to be used as a jumping off point until programmers could learn how to use beans "for real".  But I don't think I've ever read a programming example in a book or online that makes this point until now.  Seems like a huge oversight to me, if in fact what Hollumb said was actually the case.
*END JAVA SECTION*

Anyway, this was a great article.  Definitely worth reading.

Crimson
Friday, September 12, 2003

Hmmmm....
10 years of OO experience later and I feel that getters/setters are the very essence of encapsulation!
They allow you to define a public interface for your class properties without exposing the internal details (Like returning a date as a string in a specific format).
Also the example of an int property turning internally to a long is no problem at all. The old clients expect an int so the getter can cast the internal long to an int an in case of a data truncation throw an exception or something, and a new property can be introduced returning the long value for any new clients.

I might be missing the point but what is the bottom line of why getters/setters would be bad?

Geert-Jan Thomas
Friday, September 12, 2003

I agree though that the relation between classes should be defined by the message flow between them. But this is not all. Some classes are nothing but data carriers and some are nothing but function groupings. The former category is very well served with getters/setters without violating OO philosophy.

Geert-Jan Thomas
Friday, September 12, 2003

Cedric Beust (if you're into J2EE you've propably heard about him) disagrees. See
http://beust.com/weblog/archives/000022.html

Juha
Friday, September 12, 2003

I think these authors are both taking opposite positions just for the sake of having something to rant about.

I think it is pretty clear that if your class interface is littered with many trivial get/sets, then you should think twice about what the right abstraction is.  Basically the variable is a public member, and it is little better to have these accessors than to just make it a public member.  But usually get/sets that I use enforce some sort of guarantee, like restricting the values you can set it to.  Or provide some other useful abstraction, like caching a calculated value.  There are subtleties to it and I'm not exactly sure what specifically the two authors are talking about.

Basically accessors are part of your class's interface, so this is just a corollary of the rule of keeping your interfaces minimal (but complete).  Or a corollary of actually HAVING an interface, rather than a bunch of spaghetti disguised by adding useless get/sets on top of it.

Andy
Friday, September 12, 2003

By way of comparison you might like to consider the manner in which Python addresses this issue. In python attributes are usually declared by their first usage, so the simple act of assignment creates the storage required to hold a value within an object. Actually, each object has a dictionary of name/value pairs, so assignment just adds an entry to this dictionary and access just does a lookup. More recently control over the value of the keys within this dictionary has been implemented by means of 'properties', and strict typing (because python is a weakly type language) by an add-on traits package (
http://www.scipy.org/site_content/traits).

I rather like this approach because it is so flexible. You can, for example, extend a class by adding extra attributes without having to sub-class it. I find this tends to encourage reusability. Likewise, I don't find it necessary to write many accessor (set/get) functions. Those which are needed tend to be because you want to achieve some side effect, like writing straight through to backing store. Even this, however, isn't really necessary now that meta-class programming is available; you just redefine the behaviour of assignment.

David Roper
Friday, September 12, 2003

A sentence from that article that sums the entire thing up nicely goes something like:
"Dont request information from a class to do some work, request the class to do the work itself"

really I dont see much to disagree with there.

I think its an idea worth remembering, and one of those points that its worth considering from time to time.

If you are calling an accessor a lot from many locations, or have a lot of accessors in a class, then you should prolly think carefully about the design and whether you are causing yourself problems further down the track.

FullNameRequired
Friday, September 12, 2003

I was hoping to see him comment in the article about the usual "reason" for using getters/setters; namely that IF the underlying implementation changes, you can easily modify the getter/setter method to seamlessly mask that change for consumers of that particular datum.

Foolish Jordan
Friday, September 12, 2003

Thanks for pointing out Hollub's article.  I thought his arguments were weak and unconvincing, though.  His notion of design and mine are often at odds, though, so that doesn't surprise me.

Anyhow, he mentions that it is a mistake to provide accessors and mutators in most cases.  But he claims that a method that returns an Address object is not an accessor.  This makes no sense to me - it's still returning a representation of the object's state and it still makes clients dependent on this representation.

If his argument was to expose state using abstract data rather than primitive values, I'd have to agree from a design perspective.  That wasn't what I took away from the article, though.  Anyone have a clear picture of what the article was really advising?

Also, the statement: "Dont request information from a class to do some work, request the class to do the work itself"  is kind of naive (though popular), I think.  What happens in a situation where you have two objects, each of which has part of the information you need to operate on?  Which one do you ask to do the work?  How does the one that does the work get the required information from the other one?  In real life, do you delegate everything you want done to someone else?  Don't you ever ask a few of your lackeys for some information which you combine in some way that no individual lackey was in a position to do?

Also, doesn't this bloat the hell out of the target class?  Make it do everything that can possibly be done with it and the class could get very large and be dependent on a large number of other facilities.

Finally, Hollub likes to go on, as usual, about how he's the only one doing true object work and everyone else has got it wrong (see similar statements in any number of his earlier articles).  I don't see it like that.  He appears to be in love with designing modules or components, but not what most folks I know would call objects.  He even bases his design squarely on individual use-cases, a technique which none other than Bertrand Meyer slams as reeking of having a procedural view of the world:

"You look at what the system must do ("use cases"), and deduce the system architecture from that analysis. This is the exact opposite of object-oriented design..."

http://archive.eiffel.com/doc/manuals/technology/bmarticles/uml/page.html


Anyhow, I think Allen Hollub is an excellent coder.  His books on compiler design are best in class, for sure.  He is also about as practical and pragmatic as they come, so he's a great read when you want to absorb practical material.  I don't think he has the last word on things object-oriented, though, and I typically take his advice with a grain of salt.

anon
Friday, September 12, 2003

P.S.  I do agree that getters and setters are wildly overused in most software and that you should think things through carefully before you commit to an implementation riddled with them.

anon
Friday, September 12, 2003

Getters and setters are useless Java bloat.  Reasonable OO languages (e.g. Python, and to a lesser extent, Eiffel) don't force the caller to know how an object determines a value, so the "reason" for using getters and setters in Java is to work around a language flaw.

As for "don't ask for info, make the object do it", there's always *some* object that can (and should) be made responsible for a given behavior.  Sure, sometimes you just get data from an object, but I find it's more usual to pass in something that you have the object perform part of the work on.  For example, generating an XML document from a bunch of objects, I'm more likely to pass an XML stream into a method on the objects, which they then write themselves to, rather than write a function to walk over all the objects, collect data from them, and write it to the stream.

Meanwhile, bloat is not an issue if you can use interface adaptation (Python w/PyProtocols), generic functions (Lisp, and other functional languages), or AOP (Java w/any number of AOP tools).  In each case, you can separate a particular concern into an interface, function, or aspect that is separate from the main body of each class, but still *together* with all the other code relating to that concern.

Phillip J. Eby
Friday, September 12, 2003

Geert:

>"Also the example of an int property turning internally to >a long is no problem at all. The old clients expect an int so >the getter can cast the internal long to an int an in case >of a data truncation throw an exception or something, >and a new property can be introduced returning the long >value for any new clients."

Well if you know for sure that a truely "long" numbers will be used for much of the time, that means a bunch of runtime exceptions will be thrown to the old clients...which kind of sucks for them.

>I might be missing the point but what is the bottom line of >why getters/setters would be bad?

I think Allen's point is that basically, they are no better than making private data members public in many cases.  That's something I definitely agree with and often wondered about when I was learning OO design and read simple examples.  In this case, I think adding get and set methods to a bunch of private fields *does* increase maintainability.

I'm not sure he got that across well though.  It's almost like he says that accessors are OK for objects, but not for primitives...or at least that's what I took away from statements like -- "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. "
IMO, statements like that muddy the waters a bit...ok, they muddy the waters a lot.

Crimson
Friday, September 12, 2003

Foolish Jordan:

>"I was hoping to see him comment in the article about the usual "reason" for using getters/setters; namely that IF the underlying implementation changes, you can easily modify the getter/setter method to seamlessly mask that change for consumers of that particular datum. "

He does address this.  His example with changing the int to a long is an example.  Geert provides as a solution to this, but it requires throwing an exception to old clients when data truncation occurs (which could be on every invocation if long data is used all the time where it might not have been before).

I think this is a classic case of one class relying on another class's implementation details. 

Crimson
Friday, September 12, 2003

One of the more useful rules-of-thumb that I've encountered is "keep things that change a lot apart from things that change rarely."  If the output format of the XML stream you are writing seldom changes, then it might make sense to have the objects know how to transcribe themselves onto an xml stream.  If the format changes a lot, though, or you need to support multiple formats, or whatever, then it might make sense to externalize this behavior from the objects being streamed.

I used to like Smalltalk's ability to pass in "blocks" (closures) for this purpose.  I think some of the anonymous class stuff in Java was a (mostly poor) attempt at something like this as well.  I assume the AOP/Lisp/Python stuff mentioned above is similar? 

anon
Friday, September 12, 2003

I can’t believe that nobody's mentioned the sweet syntactic candy .NET has provided: 'Properties' instead of horrible getters & setters.

anon
Friday, September 12, 2003

anon -

>"Anyhow, he mentions that it is a mistake to provide accessors and mutators in most cases.  But he claims that a method that returns an Address object is not an accessor.  This makes no sense to me - it's still returning a representation of the object's state and it still makes clients dependent on this representation.

Anyhow, he mentions that it is a mistake to provide accessors and mutators in most cases.  But he claims that a method that returns an Address object is not an accessor.  This makes no sense to me - it's still returning a representation of the object's state and it still makes clients dependent on this representation.

>If his argument was to expose state using abstract data rather than primitive values, I'd have to agree from a design perspective.  That wasn't what I took away from the article, though.  Anyone have a clear picture of what the article was really advising?"

Honestly, I'm not really 100% sure.  To me the point is what you said in that second paragraph -- expose state using an ADT rather than a primitive.  That pretty much seems to be the take home...only in some ways that means that accessors aren't all bad...which sort of goes against the title of his article.  The title would be "Getters/setters For Primitives Considered Evil".  This is mostly true.

>What happens in a situation where you have two objects, each of which has part of the information you need to operate on?  Which one do you ask to do the work?  How does the one that does the work get the required information from the other one?  In real life, do you delegate everything you want done to someone else?  Don't you ever ask a few of your lackeys for some information which you combine in some way that no individual lackey was in a position to do?


Exactly.  I think the extreme stance of Hollub's title got him into trouble in this case.  Accessors ARE useful in certain scenarios, but over use is bad.  That's what I THINK one of the take-home messages is.


>"He even bases his design squarely on individual use-cases, a technique which none other than Bertrand Meyer slams as reeking of having a procedural view of the world:

"You look at what the system must do ("use cases"), and deduce the system architecture from that analysis. This is the exact opposite of object-oriented design..."

http://archive.eiffel.com/doc/manuals/technology/bmarticles/uml/page.html "


I think this was a tongue-in-cheeck comment from Meyer on some OO "guru's" insistence on designing the system without understanding what it's supposed to do.

Crimson
Friday, September 12, 2003

"""If the output format of the XML stream you are writing seldom changes, then it might make sense to have the objects know how to transcribe themselves onto an xml stream. """

If it changes frequently, then you can abstract out the format, and pass in a stream writer that knows how to do the formatting.  I'd find that preferable to cramming everything into one hard-to-maintain routine.  (In general, I've found that programming problems always get easier if you can split up the work into more objects.  And just getting data from an object, generally means that that object isn't doing its fair share of the work!)


""" I used to like Smalltalk's ability to pass in "blocks" (closures) for this purpose.  I think some of the anonymous class stuff in Java was a (mostly poor) attempt at something like this as well.  I assume the AOP/Lisp/Python stuff mentioned above is similar?  """

No.  Quite different.  They are more like being able to sit down and define in one place, a bunch of methods that will actually be part of different classes.  So if I have ten or twelve classes that would need to know how to write the XML, I could write one generic function (or aspect, or protocol) to abstract the idea of "write this XML format".  I write the code for each base class's implementation of the operation, defining it as a specific part of the aspect, adapter, or generic function.

Now, you may ask, "how's that different from just writing one function and type-testing?"  Well, the resulting code can be extended anywhere.  Let's say I'm producing a variant of the base app or framework that now has a thirteenth class that needs to write the data.  I can create the definition for this new class' behavior *without* modifying the original aspect/generic function/protocol adapters.  This lets a package be "open to extension but closed to modification", in a way that wouldn't be possible with type-testing.

Phillip J. Eby
Friday, September 12, 2003

Looks like the sort of article one's come to expect from Holub and other columnists like him - mostly common sense, wrapped up in a tortuous presentation, and topped with a needlessly-inflammatory headline.

The whole thing comes down to:
" Define the interfaces between objects in an abstract fashion, and minimize the number of places where one object depends on the internal structure of another object"

or

"Encapsulation and abstraction are useful in OO design"

duh.

-Mark

Mark Bessey
Friday, September 12, 2003

> so the "reason" for using getters and setters in Java is to work around a language flaw.

We code in Java to work around the computer industry flaw that that's where a lot of the jobs are.

C# seems to be gaining ground job-wise, but I haven't seen much Python.

Portabella
Friday, September 12, 2003

Portabella, I didn't mean to start a language flame war.  I just wanted to note that people often look at getters or setters as something valuable in and of themselves, when the reality is that they're there to work around a language problem.

If I were programming in Java, I'd use getters and setters too...  but I'd either use a tool to write them for me, and/or use Jython where possible.

Anyway, I wasn't griping about Java...  if I were, I'd address more substantive issues than getters and setters!  :)

Phillip J. Eby
Friday, September 12, 2003

Geert:

>"Also the example of an int property turning internally to >a long is no problem at all. The old clients expect an int so >the getter can cast the internal long to an int an in case >of a data truncation throw an exception or something, >and a new property can be introduced returning the long >value for any new clients."

And how do you detect a truncation?  Java will just give a an unexpected int value (like -1 for the highest possible long value).

Russell

Russell Thackston
Friday, September 12, 2003

Phillip,

Thanks for the clarification.  What you describe sounds quite powerful, so I think I will be checking it out (the Python version, at least).

anon
Friday, September 12, 2003

For the Python version, start at:

http://peak.telecommunity.com/PyProtocols.html

Or just Google for PyProtocols.

Phillip J. Eby
Friday, September 12, 2003

Hmmm. AFAIK getters and setters initially have been designed as _transparent_ class methods, i.e. they are called automagically when you access a public property/attribute of a class.

Of course it's redundant to have some getFoo() and setFoo() when foo is simply an int, but it does make sense to define __getFoo__ to transparently make a conversion of that int.

Mutators have been designed in the same spirit. So I guess the whole rant about "getters and setters encourage serious clutter in your class interface" is a little bit off the map. And only because the Eclipse IDE implemented it in such a way it does not mean the original idea was a bad one.

Johnny Bravo
Friday, September 12, 2003

Hi Phillip,

Thanks for the link, the stuff looks pretty fascinating.  Can you (or any of you other folks) recommend a good book to use to study Python?  Links are fine too, but I usually prefer something I can cart around with me when I'm first studying something new.

anon
Friday, September 12, 2003

Dive Into Python.

Johnny Bravo
Saturday, September 13, 2003

... by infamous Mark Pilgrim.

http://www.diveintopython.org/toc/index.html

Johnny Bravo
Saturday, September 13, 2003

Dive Into Python is definitely cool.  Depending on what languages you're familiar with, there also are a number of "phrasebooks" available out there, e.g. Perl->Python, Java->Python, Lisp->Python, even VB->Python.  Name your poison.  :)

Java is an interesting special case, because it shares a lot of fundamental concepts and constructs with Python, usually with relatively minor twists.  For example, in both languages you import classes from packages, but Python has a slightly more flexible import construct.  Both languages have try/except and try/finally, but Python doesn't let you combine both in the same block.  Both languages have immutable string objects with methods, but Python strings are 8-bit unless you explicitly identify them as unicode.  There's a nice quick comparison chart (not quite a phrasebook) at:

http://www.ferg.org/projects/python_java_side-by-side.html

Last, but not least, Python's manuals can be found at:

http://www.python.org/doc/

Of particular use for the beginner to read through are the Tutorial and the Language Reference.  The library reference is nice to skim through, but don't try reading it cover to cover, it's immense.  Just peek at the table of contents and jump into whatever stuff looks interesting.

Phillip J. Eby
Sunday, September 14, 2003

Thanks for the links.  I picked up a copy of Python in a Nutshell over the weekend too, and I'm happily getting productive with it already.  So refreshingly slim and straightforward.

anon
Sunday, September 14, 2003

Holub is very opinionated.

In his "Taming Java Threads" book he has a good old-fashioned rant about Win32 threading / synchronization and how bad it is, but unfortunately some of the "facts" he states are flat out wrong (or at least directly contradict folks like Richter). So... he has a big credibility problem, with me at least.


Sunday, September 14, 2003

*  Recent Topics

*  Fog Creek Home