2010-08-01

Why we are actually writing getters and setters in Java

I now often hear the opinion that writing getters and setters has something to do with better encapsulation, that using “naked” fields is bad practice. To find out if this is true, we have to look at Java history. In the mid-nineties, Sun developed the Java Bean Specification as a component model for Java. This model was supposed to help with tool support for Java, e.g. when connecting a graphical user interface with domain objects. In this case, it is useful if one can observe changes made to fields and react to them (e.g. by updating the text displayed in a window). Alas, while there are some languages that allow this kind of meta-control (Python and Common Lisp come to mind), Java does not. Thus, Java Beans introduced standardized naming that allowed one to implement a field as a pair of methods which then would manually implement the observation.

I usually code as follows: If I need just a field, I use a public field (no getters and setters), because it helps me to get started quickly and introduces less clutter. If I later change my mind, I let Eclipse introduce the indirection of the getter and setter. That means that there is no penalty for such a change and no need to think ahead! Granted, having both public fields and getters/setters affects uniformity, but the added agility is worth it for me.

Obviously, it would be nice if Java had true observable (and optionally computable) fields. This feature was initially on the table for Java 7, but did not make the cut. Maybe IDEs could help by displaying getters and setters as if they were fields. Their source code would be hidden, with visual clues indicating if such a pseudo-field is read-only etc. Additionally, auto-expansion would be improved, because pseudo-getters (such as Collection.size()), getters/setters, and fields would all be part of the same category. No more typing “.get” and hoping that the information that you are looking for is available as a properly named getter. The same kind of grouping should also be made in JavaDoc. Lastly, one could display foo.setValue("abc") as foo.value = "abc". But I’m not sure if that makes sense.

Addendum (2010-08-07): I think I did not make my point clear. It was not “use public fields”, it was “don’t use getters and setters blindly”. I’m applying the coding style mentioned above during an exploratory phase of coding. IDEs such as Eclipse allow you to do this kind of quick and dirty exploration because real getters and setters are always just a refactoring away. I do agree that, as soon as the API and its client code are not in the same code base, you cannot do these refactorings, any more. Thus, you have to think ahead and freeze some things.

As for generating getters and setters: Yes, Eclipse does that for you. It even expands getFoo into foo getter source code and setFoo into foo setter source code. And it can also rename the setters and getters for you while renaming a field. Even then, getters and setters still add clutter.

2 comments:

Martín Vilugrón said...

I've always belived that the Get/Set idiom is a stopgap measure to get things working quickly. If the system is properly Object Oriented, it shouldn't be necessary to breach the encapsulation. I'm not saying that it's easy (it could be well above a order of magnitude up in complexity), but we haven't come up with a standarized and well known way to reverse the situation.
Saludos de la Patagonia!

Fatih Coşkun said...

Private fields (and hence getters and setters) are necessary in Java in order not to prevent code evolution without sacrificing backwards compatibility.

If you don't write public APIs, you don't need private fields. But it is always a good idea to develop as if you were writing public APIs.

This rule does not apply to object oriented languages in general. It is the lack of appropriate syntactic concepts in Java that makes private fields necessary.

Web Analytics