Saturday, August 2, 2008

Getters and setters are Evil

Getter and setter methods, also known as accessors, can be seen everywhere in Java classes. Developers usually create their classes with their attributes, and then use their IDE's code generation functionality to create simple getters and setters automatically for all attributes. Some frameworks, like Hibernate, promote the use of accessors everywhere.

At a first glance, getters and setters seem to promote encapsulation. After all, they seem to 'hide' the attributes of the class. In reality, accessor methods are just a more convoluted way to expose your attributes. That's why I think getters and setters are Evil: they give you the illusion of encapsulation, without actually providing it.

In an ideal object oriented system, you shouldn't have to get the data from an object and then perform some operation with that data. The right thing to do would be to ask the object who owns the data to perform the operation itself. This is object orientation at its finest. Then you would have real encapsulation: you have no idea, and you don't care, about the data contained in an object. All you know is that an object can provide you a service specified by a method.

In real life, things are trickier and you can't always do that. Sometimes it complicates the model unnecessarily. But whenever you find yourself calling myVariable = myObject.getSomeAttribute() in order to perform some operation with that variable think if it wouldn't be better if you place that operation inside myObject's class. Only expose the strictly necessary. You will find your model will be much cleaner and maintainable.

More information:

3 comments:

Tim said...

Hmm... I'm not so sure "evil" is the word I'd use. Inelegant, yes. But rare is the client-server beast that I have seen where your fully OO business classes can be blindly serialized across the ether without concerns for bandwidth and/or memory usage. The solution for this typically is a DTO. But then whose job is it to create the DTO? If your answer is the object itself, then you are digging yourself into the hole of presentation-specific concerns (what happens when the next screen wants to see different data?). Also, how do you create one of these objects from data entered by a user screen? A giant constructor?

I guess the point is that getters/setters provide false encapsulation. Ok, so go ahead and make the attributes public. The problem with that is when you finally decide you want to slip in that "if" statement before the value is gotten (or setten), for example for lazy loading and caching. To do that, you'd have to go back and manually change all direct references to the attribute.

So, if they're evil, I'd say they're a lesser evil, or just plain inelegant. C# got it right, IMHO. ALL references to attributes are implicit calls to getters or setters. You don't have to write the stupid method if all it does is return or set the value. But if the day comes when you DO want to slip in a Mickey, you can explicitly declare the mutator without any change to your class' clients.

Domingos Neto said...

Hi Tim,

If getters and setters are evil, making your attributes public is even worse :) This is not what I was trying to suggest here.

I understand your point about how to build a DTO and I agree that it should not be the Domain Object's responsibility to do it.

This is the kind of 'real life' problems I was talking about, and this is why I cannot be purist and advocate the end of getter and setter methods.

What is important is to make sure you expose only what is strictly necessary. If you have to add a setter or a getter fine, just ask yourself if you really need it before doing it.

M said...

Well, but how to handle interfaces to the things out of the system? For example, how to put/get data into/from databases? Or to/from GUI widgets?
You can cite Naked Objects, but that assumes OO is "the" way we all should interact with automated information systems, which I strongly disagree.