Saturday, October 29, 2005

I Heart Getters and Setters

Keith Lea: Java has had the concept of beans and getters and setters for a long time. I thought we had all agreed that they work and clearly show intent. I felt annoyed when I saw the java.util.regex package appear in Java 1.4 with methods like matcher(CharSequence) and group(int), when they should have started respectively with create and get. I didn’t like so much the new Java 5 util.concurrent methods Executors.callable(Runnable), which should be prefixed with get or create.
I know this sounds silly, but I can't convey how much dropping the get seriously upsets me. I understand the bean convention came second (look at String.length() for example), but getXxx() (as opposed to xxx()) now constitutes the vast majority of cases with good reason. The lack of consistency throws everything off. Method names should be verb phrases. In a world with ubiquitous auto-completion, prefixing method names names with get helps users find methods; it doesn't result in extra typing. Dropping the get actually causes more work for me because I always look for a getter first only to realize the author subscribed to this atrocious convention. I also can't say I've ever seen a case where a get meant the difference between wrapping or not wrapping a line. I've discovered many of the offending API designers spend most of their time in lower level Java libraries safely hidden from messy problems like automating UI design, handling HTTP requests, and mapping objects to relational databases and XML. The bean convention doesn't help them. They aren't aware that it enables frameworks which greatly simplify users' lives. Is it an ideal solution? No, but therein lies the nature of the domain. Java's lack of syntactic support for properties does not justify these egregious hacks. We have a real problem, but we shouldn't try to contort method calls to look like property accesses; it doesn't work. Let's take a page out of the BeanShell book and solve the problem by overloading field operators. Which do you think looks more readable?
Foo f = bar.foo();
bar.foo(f);
or
Foo f = bar.foo;
bar.foo = f;
For the latter case, in the absence of a visible field bar.foo, the compiler generates:
Foo f = bar.getFoo();
bar.setFoo(f);
Who exposes fields anyway? Nobody. Simple, eh? Some may scream, "operator overloading," but truthfully special cases like this are perfectly safe, backward compatible and in the Java spirit.

6 Comments:

Anonymous Anonymous said...

Hear hear. We really need to put pressure on Sun to abide by this convention that *they* created.

10:38 AM  
Anonymous Anonymous said...

Sorry, crazybob, but I think the get/set convention sucks bigtime. The convention was originally proposed so that javabean containers could have a standard way of introspecting javabean properties. Where and when this convention became the defacto 'standard' for POJOs beats me. And not just that - getters and setters violate encapsulation, and usually lead to code that's badly encapsulated and verbose.

Sander

4:57 AM  
Blogger Bob Lee said...

It has nothing to do with JavaBeans(TM). Method names should be verb phrases, plain and simple.

Getters and setters don't break ecapsulation. Methods that break encapsulation break encapsulation.

I personally think it's silly to try to make your code more "OO" by avioding getters and setters. If a property is appropriate for your API, use it.

Blindly avoiding getters and setters usually results in unnecessariky awkward code.

If you don't like seeing getXxx() and setXxx() all over your code, we should add syntax sugar to:

a) simlify get/set methods
b) let you use field syntax to invoke getters/setters

12:09 PM  
Anonymous Anonymous said...

Let me explain why getters and setters break encapsulation. In general, any mechanism that allows the internal properties of a class to be manipulated from outside itself breaks encapsulation - and the end of the day, there's no difference whatsoever if you expose them via getters / setters or via public fields. The reality, of course, is that you typically need to expose properties in order to render an object in the ui, or for persistence (Hibernate now supports field level access, so that's now at least taken care of).

Making your value objects immutable goes a long way towards improving (and simplifying) the design of a system (fewer state changes, hence fewer chances of your objects being in an inconsistent state, less code to 'maintain' your objects, basically). The problem with the javabean convention (or public fields) is that it allows the internal state of an object to be manipulated from outside the object itself - and *thats* what breaks encapsulation. Good OO *abstracts state*.

In the words of Alan Kay: "Doing encapsulation right is a commitment not just to abstraction of state, but to eliminate state oriented metaphors from programming." — Alan Kay, Early History of Smaltalk. (Got this from Nat Pryce's blog: http://nat.truemesh.com)

Mind you, I have no intention of coming across as an OO purist, if you will. My basic interest is in well designed systems with *less code*.

Sander

12:28 AM  
Blogger Bob Lee said...

If you have getters/setters that expose fields the user of your API doesn't need to know about, then yes, you've broken encapsulation.

But your API can still include getters/setters for properties the user does care about. As for the implementation of those getters and setters, the user doesn't care if you store the property value in a field or a map, or if you convert it to a different type, etc.

Yes, some developers abuse getters/setters unneccesarily exposing what should be private fields, but that doesn't mean you should avoid getters/setters altogether.

5:59 AM  
Anonymous Anonymous said...

"If you have getters/setters that expose fields the user of your API doesn't need to know about"...

Ideally, objects should not expose *any* field, just act by having methods called or events triggered.

The fact that pure OO seems impractical, might mean that in fact it's not so good for everything, after all.

nicolaken

7:25 AM  

Post a Comment

Links to this post:

Create a Link

<< Home