Core Java

Getters/Setters. Evil. Period.

There is an old debate, started in 2003 by Allen Holub in this Why getter and setter methods are evil famous article, about whether getters/setters is an anti-pattern and should be avoided or if it is something we inevitably need in object-oriented programming. I’ll try to add my two cents to this discussion.

The gist of the following text is this: getters and setters is a terrible practice and those who use it can’t be excused. Again, to avoid any misunderstanding, I’m not saying that get/set should be avoided when possible. No. I’m saying that you should never have them near your code.

object-thinking-by-david-westArrogant enough to catch your attention? You’ve been using that get/set pattern for 15 years and you’re a respected Java architect? And you don’t want to hear that nonsense from a stranger? Well, I understand your feelings. I felt almost the same when I stumbled upon Object Thinking by David West, the best book about object-oriented programming I’ve read so far. So please. Calm down and try to understand while I try to explain.

Existing Arguments

There are a few arguments against “accessors” (another name for getters and setters), in an object-oriented world. All of them, I think, are not strong enough. Let’s briefly go through them.

Ask, Don’t Tell: Allen Holub says, “Don’t ask for the information you need to do the work; ask the object that has the information to do the work for you”.

Violated Encapsulation Principle: An object can be teared apart by other objects, since they are able to inject any new data into it, through setters. The object simply can’t encapsulate its own state safely enough, since anyone can alter it.

Exposed Implementation Details: If we can get an object out of another object, we are relying too much on the first object’s implementation details. If tomorrow it will change, say, the type of that result, we have to change our code as well.

All these justifications are reasonable, but they are missing the main point.

Fundamental Misbelief

Most programmers believe that an object is a data structure with methods. I’m quoting Getters and Setters Are Not Evil, an article by Bozhidar Bozhanov:

But the majority of objects for which people generate getters and setters are simple data holders.

This misconception is the consequence of a huge misunderstanding! Objects are not “simple data holders”. Objects are not data structures with attached methods. This “data holder” concept came to object-oriented programming from procedural languages, especially C and COBOL. I’ll say it again: an object is not a set of data elements and functions that manipulate them. An object is not a data entity.

What is it then?

A Ball and A Dog

In true object-oriented programming, objects are living creatures, like you and me. They are living organisms, with their own behaviour, properties and a life cycle.

Can a living organism have a setter? Can you “set” a ball to a dog? Not really. But that is exactly what the following piece of software is doing:

Dog dog = new Dog();
dog.setBall(new Ball());

How does that sound?

Can you get a ball from a dog? Well, you probably can, if she ate it and you’re doing surgery. In that case, yes, we can “get” a ball from a dog. This is what I’m talking about:

Dog dog = new Dog();
Ball ball = dog.getBall();

Or an even more ridiculous example:

Dog dog = new Dog();
dog.setWeight("23kg");

Can you imagine this transaction in the real world?

Does it look similar to what you’re writing every day? If yes, then you’re a procedural programmer. Admit it. And this is what David West has to say about it, on page 30 of his book:

Step one in the transformation of a successful procedural developer into a successful object developer is a lobotomy.

Do you need a lobotomy? Well, I definitely needed one and received it, while reading West’s Object Thinking.

Object Thinking

Start thinking like an object and you will immediately rename those methods. This is what you will probably get:

Dog dog = new Dog();
dog.take(new Ball());
Ball ball = dog.give();

Now, we’re treating the dog as a real animal, who can take a ball from us and can give it back, when we ask. Worth mentioning is that the dog can’t give NULL back. Dogs simply don’t know what NULL is! Object thinking immediately eliminates NULL references from your code.

A Fish Called Wanda (1988) by Charles Crichton
A Fish Called Wanda (1988) by Charles Crichton

Besides that, object thinking will lead to object immutability, like in the “weight of the dog” example. You would re-write that like this instead:

Dog dog = new Dog("23kg");
int weight = dog.weight();

The dog is an immutable living organism, which doesn’t allow anyone from the outside to change her weight, or size, or name, etc. She can tell, on request, her weight or name. There is nothing wrong with public methods that demonstrate requests for certain “insides” of an object. But these methods are not “getters” and they should never have the “get” prefix. We’re not “getting” anything from the dog. We’re not getting her name. We’re asking her to tell us her name. See the difference?

We’re not talking semantics here, either. We are differentiating the procedural programming mindset from an object-oriented one. In procedural programming, we’re working with data, manipulating them, getting, setting, and deleting when necessary. We’re in charge, and the data is just a passive component. The dog is nothing to us — it’s just a “data holder”. It doesn’t have its own life. We are free to get whatever is necessary from it and set any data into it. This is how C, COBOL, Pascal and many other procedural languages work(ed).

On the contrary, in a true object-oriented world, we treat objects like living organisms, with their own date of birth and a moment of death — with their own identity and habits, if you wish. We can ask a dog to give us some piece of data (for example, her weight), and she may return us that information. But we always remember that the dog is an active component. She decides what will happen after our request.

That’s why, it is conceptually incorrect to have any methods starting with set or get in an object. And it’s not about breaking encapsulation, like many people argue. It is whether you’re thinking like an object or you’re still writing COBOL in Java syntax.

PS. Yes, you may ask, — what about JavaBeans, JPA, JAXB, and many other Java APIs that rely on the get/set notation? What about Ruby’s built-in feature that simplies the creation of accessors? Well, all of that is our misfortune. It is much easier to stay in a primitive world of procedural COBOL than to truly understand and appreciate the beautiful world of true objects.

PPS. Forgot to say, yes, dependency injection via setters is also a terrible anti-pattern. About it, in one of the next posts!

Related Posts

You may also find these posts interesting:

Reference: Getters/Setters. Evil. Period. from our JCG partner Yegor Bugayenko at the About Programming blog.

Yegor Bugayenko

Yegor Bugayenko is an Oracle certified Java architect, CEO of Zerocracy, author of Elegant Objects book series about object-oriented programing, lead architect and founder of Cactoos, Takes, Rultor and Jcabi, and a big fan of test automation.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

23 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Lorenzo
Lorenzo
9 years ago

This pattern or antipattern was estudied in some books of Robert C. Martin too, and this author think like David West, the problem are a lot of frameworks based on this pattern like hibernate, spring, etc., those frameworks needs get and set (and is). I think the use of this pattern even when developers think oriented in objects is inevitable, but the solution could be change the main frameworks. Whatever the solution, it will bring problems, What could be the replacement of pojos, beans and others?

Yegor Bugayenko
9 years ago
Reply to  Lorenzo
Zbyszek
Zbyszek
9 years ago

On the other hand, how to handle with immutable objects that dog get a gain of weight? Return a new immutable object? It doesn’t sound completely sane …

Yegor Bugayenko
9 years ago
Reply to  Zbyszek

Weight is NOT an attribute of a dog! That’t a misconception. Weight is a result of dog’s behavior, which is called “please, weigh yourself and tell us how much in pounds are you now”:

double weight = dog.weigh();

Zbyszek
Zbyszek
9 years ago

but how would you store result? and what are attribute of dog?

Zbyszek
Zbyszek
9 years ago

you are self denying: in your code:

Dog dog = new Dog(“23kg”);
2 int weight = dog.weight();

you set attribute of dog, although it’s immutable so, like in case of String. If I need a dog 50kG I need another immutable instance of dog. Ok I can change simple getter to return value with same logic, like after self weight I would weight x kG. Just encapsulation. Or even more I can have to methods getInitialWeight = 23 kG and getCurrentWeight and object still is immutable, and still is a object. Attributes don’t spoil it

Yannick Majoros
Yannick Majoros
9 years ago

There is one thing missing here: dumb data structures. You make some points on easy examples (Ball ball = dog.give() etc.). More complex examples don’t work. Whenever some function needs to work with multiple arguments of same importance, you can’t decide on which object it should be defined. And you either end-up with what I call a fat domain model, or create services or handlers that work on dumb data structures. I don’t think there is even a debate on getters/setters. There are multiple camps with some arguments, no dialogues and a lot of monologues, calling each other “anemic” or… Read more »

Yegor Bugayenko
9 years ago

The key point in this article is that there are no dumb data structures in OOP. I understand that you’re used to them, but maybe it’s time to start changing :)

Yannick Majoros
Yannick Majoros
9 years ago

My key point is that there is no academic background for that. This is a pure opinion, even if my impression while reading your article is that it is presented as fact.

Some OO languages seems to have dumb structures like this, e.g. ‘struct’ in C# if I’m not wrong. Some make the frontier somewhat blurry (via properties etc.).

Yegor Bugayenko
9 years ago

I agree, there is no academic background. This is an opinion mostly, but not only mine. Read the book I mentioned in the article, by David West. He gives a much better explanation.

Dan Halverson
Dan Halverson
9 years ago

Ask, Don’t Tell: Allen Holub says, “Don’t ask for the information you need to do the work; ask the object that has the information to do the work for you”.

I believe you mean “Tell, Don’t Ask” instead. The quote even has ‘Don’t ask’ in it. Although the ‘ask’ after the semi-colon doesn’t help.

This may help. https://pragprog.com/articles/tell-dont-ask

Yegor Bugayenko
9 years ago
Reply to  Dan Halverson

Definitely a typo, thanks for correcting!

Stephen McConnell
Stephen McConnell
9 years ago

If you are doing small, immutable objects, one does not need getters. However, often in enterprise level development, all the properties of the object are not known when it is created. Also, a HUGE constructor with ALL the properties you think are needed (when the object contains lots of properties) is very clunky and difficult to use, much less keep track of all the parameters of the Constructor. One could use aggregation of many small Objects in a constructor. There are many other ways of eliminating setters…. but they often are not practical. The article raises some interesting conjectures that… Read more »

Yegor Bugayenko
9 years ago

Another rule of thumb in OOP, which is not covered in the article, is that a proper object doesn’t have more than 5 public methods (approximately). If there are more, it is not a proper object any more and needs refactoring. The same is true for encapsulated properties, their number should be very limited. So, instead of “often in enterprise level development” we should say “often in a messy procedural development” :)

Frank Berger
Frank Berger
9 years ago

are you kidding? Naturally an Object with 1000 Methods is a nightmare. But are 500 classes with 2 methods each more comprehensible? On toy examples nearly everything works but in real world you have to make decisions and you have complexities beyond 5 method classes. This might require OO, functional or procedural or whatever paradigm fits. In RL you have constraints you have to handle. It’s RL and not dog.bark() After all SW is a tool to solve a real world problems not something worth in itself. Being a developer for quite some time I meet younger developers more and… Read more »

CrashCodes
CrashCodes
9 years ago

In the example, I was following along until the bits about no more nulls; but what is expected to happen if dog.take() is called before dog.give()?

CrashCodes
CrashCodes
9 years ago
Reply to  CrashCodes

err: dog.give() before dog.take().

Yegor Bugayenko
9 years ago
Reply to  CrashCodes

The dog will scream and run away :) Something similar should our application do. Throwing an exception is a logical behavior. Check this article also: http://www.yegor256.com/2014/05/13/why-null-is-bad.html

Roger Lincoln
Roger Lincoln
9 years ago

So the dog can never drop the ball?

Yegor Bugayenko
9 years ago
Reply to  Roger Lincoln

She can, of course. When the ball is out of her hands you can’t ask her to give it to you. You should first check, whether she still has it:

if (dog.hasBall()) {
Ball ball = dog.give();
}

jose
jose
9 years ago

I think that it is ok to abide by the JavaBean model, which dictates getters and setters that are name getXxx and setXxx. The author, through his example, seems like his beef is with the JavaBean naming convention; his example had a setter and getter it was just named something tht you can not easily guess or assume?

I would stick with convention when coding and JavaBean has proven to be a good convention.

jose
jose
9 years ago
Reply to  jose

Its funny because just now I was able to solve a problem because the Object from the API I am working with is a JavaBean hence I can take advantage of tools like BeanUtils from Apache. http://commons.apache.org/proper/commons-beanutils/

Sporniket
9 years ago

I disagree on one point :
The getter/setter IS an encapsulation of the implementation detail, even if in most cases, it is underused (I suspect that it is for convenience and performance : a fully implemented encapsulation for a mutable object could require some thought and work -shallow or deep copy ?- and a performance hit).
By the ways, remember that a Javabean might notify registered listener when the write accessor is called : in this case the write accessor is not a mere proxy to an internal field but implement a behaviour as well.

Back to top button