Summary: Public getters and setters should be considered as an antipattern.

Public getters and setters should be considered as antipattern. Or more precisely: 95%-100% of all members should be completely hidden.
I got 24 comments for my last entry about "evil" getters and setters. The conclusion is interesting. Everyone agreed, that getters and setters do violate the encapsulation and so could be a maintenance problem.

Of course accessors are useful in infrastructure frameworks like EMF, XMLBeans, java.beans.XMLEncoder/Decoder etc. The main purpose of such frameworks is to provide additional services (serialization, delta computation, XML-representation etc.) based on the internal state of an object. So Getter and Setters are the easiest way in this infrastructural area to access the data.

But in business/domain applications getters/setters are an antipattern. So considering the fact I extracted the following best practices to deal with JavaBeans:

  1. Do not use getters and setters in business objects.
  2. Infrastructural code like Value Objects (throw-away) should be separated from the realization of the business logic.
  3. Use object oriented style whenever possible, instead invoking series of accessors.
  4. ...do not expose private state of an object using public accessors.
Now it is time to contribute some PMD/FindBugs-rules to search for "evil" getters and setters :-).


Web Apps, SPA, PWA with vanilla Java Script (ES 6+), CSS 3 and WebStandards only. As simple as possible, but not simpler. See you at: (Progressive) Web apps, Single Page Apps and WebStandards airhacks workshops at MUC airport, Winter Edition

airhacks.fm the podcast:

Stay in touch: airhacks.news.

Comments:

Getters and setters provide an illusion of encapsulation, where often public fields provide equal encapsulation, e.g.:

class Complex
{
public double real,imag;
}

Public fields actually tell an API user more, in the case of Complex we can see that real and imag are mutable.

class Complex
{
public final double real,imag;

public Complex(double real,double imag)
{
this.real=real;
this.imag=imag;
}
}

In this case the API user can actually see that the values are immutable, they don't have to trust the implementation.

One reason, in the Complex case, to use getters and (optionally) setters is so that you can change the implementation without the API user having to change their code.

So if you start with private fields and public getters and (optionally) setters, then you will not annoy the users of your API so much.

Of course, if the users of your API are in the same codebase as you, then this does not matter, and then you probably should not use this illusion.

IDEs can help you to make a public field into a private with accessors.

Mutable data is slightly dubious, I personally prefer to keep my types as 'value types', aka immutable types, aka referentially transparent types, so that I can share objects around without worrying. Of course, in certain situations, this is not so practical.

So I agree if you talk about setters, but if you talk about getters I am not so sure.

Here is a little rule that I try to follow:

** If a method can be implemented solely in terms of the other methods in an object, then it is a function ON the object, not a function OF the object. **

That is, it can profitably go into a utility class.

If you expose an object's data via an accessor (or a public, preferably final, field) then you can move your methods to a separate utility class.

This works pretty well if you are working directly with a known implementation, but let's now suppose that we are working with a general Number type.

interface Number
{
Number add(Number number);
}

We cannot sensibly move this to a static utility method, because each implementation will differ. There isn't enough information in the Number interface to do that. Of course, we can move each implementation's utility method to a static utility method and delegate, but that doesn't gain us a lot, except possibly removing code duplication for similar types.

In conclusion, getters and setters are fine when working at a low level of abstraction, like the Complex type, but when working at a higher level, like the Number type, they would be impossible anyway. What useful getter or setter could you define on a Number?

So if you are feeling like you want to move away from getters and setters, perhaps what you are saying is that you want to move away from poor/low abstractions.

Posted by Ricky Clarkson on August 16, 2006 at 03:51 PM CEST #

Old debate, and the evilness of accessors has been debunked many, many times (such as here: http://beust.com/weblog/archives/000022.html).

Posted by x@y.org on August 16, 2006 at 06:58 PM CEST #

x@y.org,

and http://www.adam-bien.com/roller/page/abien?entry=encapsulation_violation_with_getters_and
:-).
I didn't knew about the beust's entry, but I will read it :-). Regards! Adam

Posted by Adam Bien on August 16, 2006 at 11:53 PM CEST #

Post a Comment:
  • HTML Syntax: NOT allowed
Online Workshops
realworldpatterns.com
...the last 150 posts
...the last 10 comments
License