Freitag, 3. Mai 2013

A word on setters

I like the concepts of Clean Code and Domain Driven Design and thus like my domain model to express itself.

And - I hate setters! For those of you, who don't know, what I am talking about, please read the JavaBeans spec, especially chapter 7.1. Setters are almost always wrong! At least the one that where created automatically by the IDE. Developers that generate setters almost always don't care about business logic.

An example? Think of an domain model entity that represents a person. A simple person entity may have two attributes: firstName and lastName. I can't think of a use case where it makes sense to create such simple person without any of that attributes set. And further more, this attributes are not likely to change any time soon. So why should this person have a constructor that does not enforce to set this attributes? And why should it have setters for this attributes?

"Wait" does the attentive reader shout here: "What, if the person marries?" OK - thats a use case. Do we have to take this use case into account? If yes, let's implement that business logic. Is this a reason to implement setLastName(...)? No! setLastName(...) in no way expresses the fact that it belongs to the use case of marriage. And, if we have to take marriage into account, we surely need to know, if a person is married. So we at least need a third attribute boolean married within the person entity and, of course, we have to set it on marriage. So implement setMarried(boolean)?

That's what I sayed when I wrote "Developers that generate setters almost always don't care about business logic". We have this use case marriage and we need to change two attributes. There is no reason to set this attributes independently. So let's just implement one method that exactly does the job and expresses that it does the job:

public void marry(String newLastName) {
  lastName = notBlank(newLastName);
  married = true;

Now a reader of that code directly knows the intent of that method. This is not be true for a method named setLastName. So again, no need for a setter!

OK, normally at this point the technical argument comes in: When I want to create that person in JSF, I need to have a default constructor to create an empty person and I need to have setters to fill that person. My answer to this (referencing Matthew 22 21) is: Give to JSF, what belongs to JSF and give to your domain model, what belongs to your domain model. And setters almost always don't belong to your domain model! I don't want to pollute my domain model, just because a spec like JSF sticks on a sixteen year old standard (Take a look at the release date of JavaBeans).

So be happy and create a JavaBean with getters and setters for JSF with an action method that creates the the person entity using a constructor that ensures that both first name and last name are correctly filled.

This is not nice and an overhead that seems to be just a workaround for the incompetence of the framework. In one of my next blog posts I will show a way to get rid of the usage of setters for object creation in JSF. Stay tuned.

A german version of this blog entry can be found here.

1 Kommentar:

  1. Luckily, I had at least two masters which made this stuff to one of my fundamental principles of life. ;) Looking forward to your next post!