Adam Bien's Weblog

Tuesday Aug 08, 2006

Getters and setters: an antipattern. JavaBeans and OO

As I saw the first time getters and setters in C++, I was a little bit confused and also disappointed. The encapsulated state, was indirectly exposed via the property accessors. Everyone told me: you have to design your classes this way, because you can then intercept the call and provide some additional value or protect the variables. In 99% of all getters/setters cases nothing happened, so it is a kind of overengineering. It becomes even worse. Using getters and setters it is hard to ensure the consistency of an object. Actually you have to wait until alls setters are invoked, before the object is usable. So it requires an insider knowledge what an object needs. Sample:
JavaBean style:

connection.setUser("dukie");
connection.setPwd("duke");
connection.initialize();

OO-style:

connection.connect("dukie","duke");

So in the OO-style you do not even know, whether the object has a private state, or not. It simple connects as expected - no magic here. Either an exception is thrown or not. So the consistency can be better assured. It is also more expressive: the "parameters" are bound to the activity.

JavaBeans were invented to support better IDE integration and be machine-readible. But it is not a great idea to use the default getter/setter approach to create business applications or domain models. From my point of view, using getters and setters is only a work around. In J2EE 1.4 world this conventions were needed to create transfer objects (or Value Objects). The design of many applications today becomes more and more procedural. It is nothing wrong with it - but with "real" objects more maintainable applications can be build...

Conclusion: The getter and setter convention increases the reflection capabilities so it is especially useful for machines (IDEs, framework). In standard OO-design property accessors are more an antipattern than a best practice. So you should be careful with the "Generate getters and setters" wizzards in modern IDEs...


Special Events: Java 8 with Java EE 7: "More Power with Less Code", 13th October, 2014 and Java EE 7: "Testing and Code Quality", 14th October, 2014

A book about rethinking Java EE Patterns

Comments:

I think you have have overlooked a view things here like polymorphise for one.

I agree that the state of an object is not know when you use setters to set everything but that does not mean you have to do it like that.

In your example you say:
connection.connect("dukie","duke");
is better and I agree that this is a convient method but it should still be implemented like this.

public void connect(String user, String pwd)
{
this.setUser("dukie");
this.setPwd("duke");
this.initialize();
}

This is because you may choose to override the setPwd method in a custom implementation. e.g. to encrypt the password.

If you are writting a final class i agree the setters are useless as their implementation can never be changed.

Posted by Owen Fellows on August 08, 2006 at 04:23 PM CEST #

Missing a point a bit IMO.

Getters/setters have some important usages, eg.:
- they NAME parameters - Java is a language that does not allow having named params, only ordered ones. Naming params helps to read/write the code
- getters/setters allow easy implementing of stuff like dependency injection or XML serialization - think a bit. You not always want to "hide your state", if you write some infrastructural code (persistence framework, serialization) you want your state to be easily exposed. There is the natural conflict.

I somehow share your hatred for exposing state, but simple mottos like "Getters/setters are bad" usually do not deal with reality too well. ;)

Posted by Michal on August 08, 2006 at 05:17 PM CEST #

Owen,

absolutely, but then getters and setters should be private at least protected, but not public. In this case I would agree with you.
I would also delete the getters in this case and provide on demand a method like: getConnectionInfo().
BUT: do we still need private/protected getters and setters?

thank you for your comment,

adam

Posted by Adam Bien on August 08, 2006 at 07:29 PM CEST #

Michal,

your are also right.

1.Parameter-naming:
why not: connect(String user,String password)?
You have then names.

2. In Java EE references can be directly injected.
Using getters and setters for DI is nothing else then a workaround.
In case you are writing infrastructural code, you can use of course getters and setters, but in my opinion it is not a best practice...

Again:
1. Getters and setters are not bad, but overused.
2. They should be not used as general solution, but maybe helpful in special cases.

I think my conclusion:

"Conclusion: The getter and setter convention increases the reflection capabilities so it is especially useful for machines (IDEs, framework). In standard OO-design property accessors are more an antipattern than a best practice. So you should be careful with the "Generate getters and setters" wizzards in modern IDEs..."

is still valid. Getters/Setters are great for infrastructure, but not very useful for domain-objects...

Posted by Adam Bien on August 08, 2006 at 07:40 PM CEST #

In your reply you mention removing gets and setters with and using a getConnectionInfo() instead which would presumable retrieve an object containing username and password e.g. a IConnectionConfig object.

So know you have a method connect(String user, String pwd) which should be connect(IConnectionConfig connectionConfig). So know you effectivly have setConectionConfig and getConnectionConfig so we are back to getters and setters again just with object instead of primiative types (including strings).

I agree if you don't want to give access to internal variables then getters and setters should just be added out of habit but if you want to be able to return e.g. connection information then they should be there.

The point that i'm trying to make is if you have some member variables that can be set and viewed then you should have getter/setters (obviously) but these should be used internally to the class to allow for polymorphism.

Posted by Owen Fellows on August 08, 2006 at 08:26 PM CEST #

In last post
"getters and setters should just"
should be
"getters and setters should NOT just"
:-)

Posted by Owen Fellows on August 08, 2006 at 08:27 PM CEST #

Owen,

a weblogger is actually a cool chat-tool :-).
I hope you know what I mean. My intension here is:
to provide clean, understandible OO-method.
Having private or protected getters and setters is fine for me - but it is perhaps in some case a little overengineering :-).
So you agree with me, that getters and setters violate the encapsulation? :-)

Posted by Adam Bien on August 08, 2006 at 09:04 PM CEST #

I'm just trying to understand your point of view using examples :-).

I agree that creating public getters and setters for everything breaks encapsulation.

And I do agree that having private/protected getters and setters could be seen as overengineering as the may never be used.

BUT. I believe private/protected getters and setters are easy to implement and can be very helpful when updating code later and therefore the overengineering is worth it.

e.g. have a member variable "emailAddress"

If you access this directly in your class that is fine. But then say you want to ensure that is is always lowercase. You have to find all usages and ensure you have a toLowerCase.

If from the beginning you used the getters and setters you have to add one toLowerCase instead of search for multiple occurences to ensure it is always true.

This is a bit of a simple example but I hope you see my point. This has happened to me numerious times and everytime I say "That was good I used getters and setters otherwise I'd have go through every usage of it."

Hope I'm not causing offence but do want to fully understand your point :-)

Posted by Owen Fellows on August 08, 2006 at 10:07 PM CEST #

I suppose we just disagree on this point as I have with many other people :-)

Posted by Owen Fellows on August 08, 2006 at 10:09 PM CEST #

Hi,

Beside that fact that public getters/setters are often autogenerated and never used, I think they are often implementet in a bad way. People tend to put program logic into them where it is realy not needed.
Setters should set something and Getters should return something - and nothing more. It is realy no problem if you do something like that:

void setCamera(Camera c) {
if(camera != null)
camera.removeMotionListener(this);
camera = c;
camera.addMotionListener(this);
}

but not:

void setCamera(Camera c) {
initCamStream(c);
}

initCamStream(..) should be called from outside or from methods like startRecording() but not inside a setter!

Methods like getPeerCount() should not iterate through all reachable peers ping through the net and count them, they should return the current peercount. If the object cant provide a peercount immediately you should name the method countPeers() [and dont forget the doc]!

Developers who dont know the exact implementation of getPeerCount() could do things like:
for(int i = 0; i<getPeerCount(); i++) {
//...
}

but a (real java hacker/) developer would never write:
for(int i = 0; i <countPeers(); i++) {
//...
}
because (s)he knows that countPeers() will be invoked every iteration ;-).

and my last sample of bad implemented setters (yes it is swt/jface):

// exchange content/label provider, sorter...
tableviewer.setContentProvider(provider); // invokes refresh()
tableviewer.setLabelProvider(labelProvider); // refresh again
tableviewer.setSorter(sorter); // table is not fresh enough => refresh

//... and filter
for(ViewerFilter oldone : oldFilters) {
tableviewer.removeFilter(oldone); // isnt it a nice rendering loop?
}
for(ViewerFilter newone : newFilters) {
tableviewer.addFilter(newone); // and give him the rest
}

System.out.println("table now fresh");

the first time as i ran it (we took the content of the table directly from database) i waited around 5min until the table was eh.. fresh ;-) Now we cache the data - dont ask why.

removeBlogLisener(this);
kaum schreib ich was hast du >1000 hits auf deiner Seite ;-)
schöne Grüße aus Trier
addBlogListener(this);

Posted by Michael Bien on August 08, 2006 at 11:02 PM CEST #

Owen,

no you are right. Getters and Setters gives you more power - the access to the members can be easier "decorated" with additional functionality. Now the next idea - wouldn't be a good use case for AOP?
It should be also possible to inject the functionality...

But you are right - on average it is better to use protected getters and setters. Public getters and setters should be considered as antipattern. Or more precisely: only 95%-100% of all members should be hidden...

Posted by Adam Bien on August 09, 2006 at 12:23 AM CEST #

Mike,

thank you. Yes. Business Logic in setters/getters is evil, because, no one would expect it. But it could be o.k, in case it is well-documented in Javadoc.
I suppose your JXTA and SWT examples were not well documented :-).

Greetings from munich!,

adam

Posted by Adam Bien on August 09, 2006 at 12:27 AM CEST #

>But it could be o.k, in case it is well-documented in Javadoc.
yes perhaps, but additionally you should refactor getPeerCount() to countPeers() if it counts peers every time it is called...

>I suppose your JXTA and SWT examples were not well documented :-).
the doc was always in my brain ;-)

michael

Posted by Michael Bien on August 09, 2006 at 01:00 AM CEST #

I also agree that Business Logic in getters and setters is evil if something needs to be refreshed it should have two methods
- boolean isFresh()
- void refresh()

Then as Michael says about you can make lots of updates to the state and then refresh it (saving possible duplicated work).

But i think this is getting off the point of the post :-).

So my final comment is I agree with Adam when he says:
"Public getters and setters should be considered as antipattern. Or more precisely: only 95%-100% of all members should be hidden"

Which boils down to, Only create code that is needed :-)

Posted by Owen Fellows on August 09, 2006 at 12:12 PM CEST #

Owen,

I would only remove the "only", add "completely" and use the following
sentence as title for a new blog entry:

"Public getters and setters should be considered as antipattern. Or more precisely: 95%-100% of all members should be completely hidden"

Posted by Adam Bien on August 09, 2006 at 12:34 PM CEST #

Owen,

I fully agree with Adam.
Moreover, if you implement your class in the way you wrote it:

>>>
public void connect(String user, String pwd)
{
this.setUser("dukie");
this.setPwd("duke");
this.initialize();
}
>>>

You create a fragile base class: http://en.wikipedia.org/wiki/Fragile_base_class

My two cents.
Cheers,

Sergio B.

Posted by Sergio Bossa on August 09, 2006 at 05:10 PM CEST #

Sergio,

thanks, I saw you had also an interesting entry about exactly the same topic -> interesting.

So this:
>>>
public void connect(String user, String pwd)
{
this.user = format("dukie");
this.pwd = format("duke");
this.initialize();
}
>>>

would be better, than "hidden" formatting or validation in the setters. The format method could also belong to an external Utility-Class...

Posted by Adam Bien on August 09, 2006 at 06:50 PM CEST #

This topic is also discussed here:
http://www.peerbox.com:8668/comments/start/2006-03-23/1

Posted by Kevin Greer on August 09, 2006 at 10:44 PM CEST #

Kevin,

thanks -> I will write another post and summarize the results.
So what do YOU think. Are accessors good or evil?

thanks,

adam

Posted by Adam Bien on August 09, 2006 at 11:13 PM CEST #

Hi Adam,

thanks to you for the discussion.

I'd say your code is clearer than Owen's one, but the problem of the base fragile class is still there:

> format("dukie")

Doing so, you are calling a non-final public method that, if overridden by a subclass, could break the connect() behaviour and contract, and lead to unexpected results: this is because you are giving the subclass rights to change the connect() behaviour WITHOUT superclass knowing anything (because the change is in the subclass)!

Hope to have clarified.

Cheers,

Sergio B.

Posted by Sergio Bossa on August 10, 2006 at 11:51 AM CEST #

Sergio,

you are right. But this can only happen, in case you have more than 2 levels of inheritance. In most "business" projects, more than 3 levels is suspect.
The method format can be final, in case the implementation in the superclass is complete, or abstract in case you would like to have something like the Template pattern.

So: how evil are actually getters and setters? :-)

greetings && thanks,

adam

Posted by Adam Bien on August 10, 2006 at 12:03 PM CEST #

As per my experience with OO, C++ & Java, due to the advent of technologies like Java beans (extended to EJBs) the encapsulation concept is gone for toss. Java beans were more from the point of view of IDEs & similar tools and deployment ease.

From OO Domain modeling (Domain Driven Design) perspective getter/setter is surely an anti-pattern. I have seen domain classes with attributes & getter/setters and no other bevavior or operation which violates/avoids the GRASP (General Responsibility Assignment Software Patterns).

Getter/setters should be used judiciously or scarcely. Theie usage is very confusing and awkward for people who have done domain modeling using POJOs and get introduced to EJB based development environment.

Best regards,
Swapnil

Posted by Swapnil Jagtap on August 10, 2006 at 01:54 PM CEST #

Swapnil:

Absolutely. But with Java EE 5 Getters and Setters are no more required.
Entities are object oriented, so perhaps it is possible to have truly object-orientation...

thank you for your comment

Posted by Adam Bien on August 10, 2006 at 02:04 PM CEST #

I realize this is a Java blog, but wanted to point out something really cool about visual basic 6. If you make a Public variable in a class, it's automatically compiled as get and set procedures (via COM). So you can later make Get and Set procedures that actually do stuff without breaking the interface.

Posted by Chase Saunders on August 10, 2006 at 07:30 PM CEST #

Hi Chase,

it's o.k. But why you need public attributes.
You are a candidate for Semplice -> the VB 6 on the Java-Platform :-).

Posted by Adam Bien on August 25, 2006 at 01:29 PM CEST #

domain objects should only have getters and setter
it is the responsibility of the domain objects to keep themselfs consistent, that's why your should place your business logic as much as possible in the getter , setters, adders, removers, and connect business objects using listeners (or forward chaining engine) to keep them consistent. think spreadsheet, think first order logic, think constraint solving, think dataflow ...
ideally domain objects allow modification in whatever order.

not controller (sessionfacade whatever) knowing everything especially when to call validate etc..

however getter and setters are bad for objects that represent algorithms or functions, technical objects...

Posted by 84.194.66.66 on February 01, 2007 at 09:50 PM CET #

getters/setters aren't evil, only programmers not able to separate:

// bean style
auth.setUser("dukie");
auth.setPwd("duke");
// procedural
connection.initialze(auth);

Posted by Michael Nischt on June 01, 2007 at 12:43 PM CEST #

Michael,

I cannot get your point (perhaps I'm one of these programmers) but:
Perhaps they aren't evil, but they violate the encapsulation and encourage
procedural programming. You encapsulate the attributes first and expose them via getters/setters - what's the difference?
The cool story is: in JavaFX script they aren't even required - it's an interesting idea.

Posted by Adam Bien on June 01, 2007 at 05:37 PM CEST #

I, myself is intrigued by fact, why we use getters/setters.
We need to encapsulate only process methods etc.
In case of value objects/java beans, all we do get an object & set an object.
So wht's wrong with using java beans just like C style structs.

On top of that, there are interfaces defined for those beans. Why? In case of internal project, why someone define interface. Again it's overkill.

Posted by ashish jain on June 13, 2007 at 09:13 AM CEST #

As I understand you - you share my opinion, or? :-)

regards,

adam

Posted by Adam Bien on June 13, 2007 at 12:25 PM CEST #

I realize I'm weighing in late on the discussion, but here's my take:
First off, getters and setters are not of the devil, in GRASP objects accessors should be public and final, and here's why:
Let's say you have a User object, and that you have a user edit screen, where you're asking users to change their password. Without setters and getters, it becomes extremely difficult to update domain objects without getters and setters, because in many cases you don't have all the information to call a constructor with all the arguments the object needs. In short for updating purposes, public setters and getters make the most sense.

Posted by Nate Corlet on February 27, 2008 at 05:30 PM CET #

In some cases I can follow the idea of seeing getters and setters evil. They just blow up the code.

But I also see cases where getters setters do make sense. Like in an application I am currently working on there are multiple legacy service interfaces to be used, each of them having their own - different - data structures for everything.

What's wrong about having an interface for general objects like an address or account which make it possible to use the same code (and JSPs/Facelets) no matter from whin legacy service the object is coming from. In this case, getters and setters are implementations of the interface to map to the fields in the legacy entities.

Or what's your suggestion for a solution to this? Copiing all entities? Then for each change in fields which my application does not even need to deal with, the application has to be changed just to copy data which is not even needed within the higher levels.

I am curiously looking forward to your opionon about this.

... Michael

Posted by Michael Hönnig on June 28, 2008 at 11:21 PM CEST #

I particulary think getters and setters are evil. We usually have our code files full of them. And they are generally dumb. They can server for something, but in rarely situations we really put more code inside them besides the get and the set operation. Python for example let´s you declare the variables and you just add kind of getters/setters if you need to override the get/set behaviour. Somebody knows if there is an initiative like that for future Java versions?
Thanks,
Marcelo

Posted by Marcelo Alcantara on January 30, 2009 at 06:41 PM CET #

Thank you for the post.

When exposing domain objects to the UI, getters and setters and lot more easier than using builder patterns.

Any solutions?

Posted by Arun Joy on December 06, 2011 at 03:58 PM CET #

Great subject, I was using your article while writing my own, on the same topic: http://www.yegor256.com/2014/09/16/getters-and-setters-are-evil.html

Posted by Yegor Bugayenko on September 16, 2014 at 12:58 PM CEST #

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