Monthly Archives: March 2015

The Magic Setter Antipattern

Setters and getter are evil. When the JavaBean definition was created it seemed to be a good idea. But they do a lot of harm to the Java community. Not as many as the null pointer generally, but enough.

The very first thing is that many juniors believe that implementing setters and getter (hey, it is just a few click in Eclispe!) does encapsulation properly. Should I detail why it does not?

The other things is that using setters and getters are against YAGNI. YAGNI stands for You aren’t gonna need it. It means that you should not develop a code that the project does not need now. The emphasis is on the word now. Many programmers tend to develop code that extends the actual functionality and does something more general than actually needed. Even though in principle it could be valuable: in most of the practical cases it is not. The code becomes more complex and on the other hand project never develops to the stage where the generalization the programmer created is needed.

Setters and getter are a clean, simple and very broadly used example of YAGNI. If the setter does nothing else but sets the value of a field and if the getter does nothing else than returns the value of the field then why do we need them at all? Why do not alter the access modifier of the field to the value that the setter and the getter has (probably public)?

The answer usually is that you may need to implement some more complex functionality either in the getter or in the setter and then you need not change the “interface” the bean provides. The words “you may need to implement” suggests that this is YAGNI. What is more: it is dangerous. Implementing the setters and the getters you implicitly expose the implementation of the class. What does a setter do? Sets the value of a field. For example setBirthDate() by definition sets the field birthDate. And this is the way your users, who write the code calling the setter will think about it. You may document in your JavaDoc that setBirthDate() actually “specifies” a birth date but that is too late. You named the method to be a setter and that is it. Nobody reads JavaDoc. API rulez.

Later, when you change your code and setBirthDate() does not only sets birth date or does not even do that the users will not be notified. The change is silent and you just changed the interface you implicitely provided for your users. There will be bugs, debug session, new releases and this is good, because this creates workplace (feel the irony, please). If the users were provided direct access to the fields moving the fields from public to behind the barricades of private access modifier would cause compile time errors. Perhaps it is only a weird personal taste, but I prefer compile time errors more than bugs. They are easier (read: cheaper) to fix.

Do not worry: you still can modify your API. You can still remove your setters and getters from the set of methods and force fellow programmers to fix their code that implicitly assumed that setters really set and getters get. Please do.

What the actual story was making me write this?

Once upon a time there was an object that could do something. To perform its task you could set either field aaa or the field bbb, but never both. The application was developed this way and all was good for more than six years. Some day a young programmer princess came riding on white horse wanting to make the world to be a better place. He wanted to make the before mentioned class safer and modified the setter setAaa() to null the field bbb and the other way around. Unit tests shined. Coverage was 100%. (I should learn not to lie.) He submitted a new release of the library and a few weeks later he finished his internship and went back to school. That time the applications started to use the new version of the library. And they failed miserably because of this small change and rolled back to the old version. We all had hard time and summing up, well, the corporate spent approximately one person year of work caused by the simple change not to mention the amount of hair that programmers tore off from their head.

Why did the programs failed? There was some code that cloned an object containing the fields aaa and bbb in a way like this:

    BadBean newBadBean = new BadBean();
    newBadBean.setAaa(oldBadBean.getAaa());
    newBadBean.setBbb(oldBadBean.getBbb());

You see the point. In the new bean the field aaa was always null.

Now that you have read this article you will never try to create a clever setter. I know you won’t! You know the saying: Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live. Behold!