Skip to content

Favour Constructors Over Setters

June 10, 2009

Sometimes we get so caught up in the latest tool, feature or technology that we forget about our most basic principles. Take Dependency Injection for example; we can get so caught up in the abilities of Spring, Guice, or PicoContainer, that we forget that there are other, better reasons to choose Constructor Injection over Setter Injection than whatever is used in the HelloWorld example. But first, a little recap…

How can we set the state of our objects?

As you’ll know from your first lesson in Object Oriented Design, objects have methods and fields; action and state; what they do, and what they have. (If you didn’t know that, then I suggest that you start with Head First Java, and come back later). Today, we’re only concerned with the state of an object; what it has in order to fulfil its (one and only) responsibility.

Let’s say that we’ve a pin that we can put in a map. Something like “Pin has-a LonLat position” (again, if you don’t know what that “blah has-a bleugh” means, then it’s back to Head First Java for you. Seriously, someday you’ll thank me for it). But when we want to use our Pin, how do we set its position?

Option 1: Public Fields

Back when we were at school, our first implementation of Pin might use public fields:

public class Pin {
// we need to put our pin somewhere
 public LonLat position;
}

Then the code that uses our Pin would look something like this:

...
myPin = new Pin();
myPin.position = new LonLat(5, -13);
...

Public fields are bad, and pretty much every programmer I know knows not to use them, so I shouldn’t have to say anything else, right? But, if I’m honest, I’m not sure that every programmer I know knows *why* not to use them.

It’s all about information hiding; if your fields are public, then you’re exposing your internal workings (aka “flashing your knickers”). Once other objects have started using your object’s interface and setting your fields, you’ll be unable to vary your implementation to meet any future requirements. For example, how can we perform an action when our position is set?

Not only that, but public fields go hand-in-hand with default constructors (you saw that I didn’t write a constructor for Pin but still managed to construct one, right?). Don’t forget, default constructors are evil.

Remember kids: public fields – just say no.

Option Two: Public Setters.

So it’s Day Two on our how to set an object’s state course, and you know that your public field won’t cut the mustard. How’s about a public method instead?

public class Pin {
 // we need to put our pin somewhere
 private LonLat position;
 public void setPosition (LonLat position) {
  this.position = position;
 }
}

This is much better. If someone comes up with an additional requirement for out Pin (say, no pins allowed in the sea) then we can just add that validation to our setPosition method. Just a small tweak to our client code…

...
myPin = new Pin();
myPin.setPosition(new LonLat(5, -13));
...

…and we’re done, right? I mean, we’ve still got that evil default constructor, but this is what most classes do, right? What could possibly go wrong?

Well, what if our Pin needs two pieces of state to make it complete; say a height to go along with its location? You could add a setHeight method to the Pin class, but how would you make sure that every time someone makes a Pin, they set both the location and the height? How is the IDE going to help you? How are you going to help the programmer who comes after you? (Don’t forget, we don’t write programmes for computers, we write programs for programmers.)

Don’t forget that we want to “fail fast”. The sooner we fail, the sooner we can fix. Favour compilation errors over runtime errors. If someone forgets to set the height on our location-and-height Pin, then that’s a runtime error (either in the software sense, or in the broader sense – just because it doesn’t throw an exception, doesn’t mean it’s not a failure). But I’m getting ahead of myself.

In the meantime, just remember kids; setters are dogs.

Option Three: Set State on Construction.

I’ve you bothered to read the title of this post, then you’ll already know who our winner’s going to be. Here’s what our Pin looks like when we set its state on construction:

public class Pin {
 // we need to put our pin somewhere
 private LonLat position;
 public Pin (LonLat position) {
  this.position = position;
 }
}

And here’s our snippet of client code…

...
myPin = new Pin(new LonLat(5, -13));
...

Just one line. Great! Fewer lines of code == fewer lines of errors, right?

What’s so great about setting state on construction? How about…

  • An object with its state set on construction is a ready-to-use object. Not some generic, default-value, best-guess object that you can then tweak with setters if you need to. Or, worse, a generic, default-value, best-guess object that you *don’t* tweak the setters on, and can’t work out why it doesn’t have the right attributes. Because you can’t construct the object without supplying its state, it’s impossible to construct an object and then forget to set its state (always aim to make the right thing to do the easiest thing to do).
  • If you need to add, remove or modify a parameter to your constructor then your IDE can do all the heavy lifting for you. Even if you’re one of those emacs-and-command-line types, you’ll get compilation errors for every line of client code you’ll need to change, so you can’t possibly miss one.
  • No change-of-state is possible during object lifecycle. It’s so much easier to reason about an object when you know that its state can’t change.

That’s three good reasons; I’m sure that there are more. For me, it’s just one of those no-brainer “Good OO” things that is definitely the right thing to do. Heck, if the Good Citizen says you should do it, just do it.

But what if I use dependency-injection? Is that a problem?

It doesn’t matter; set state on construction!

Seriously, all of the Dependency Injection (DI) frameworks mentioned at the start support DI-on-Construction (DIoC), so just use it. Setting state on construction isn’t a DI decision, it’s an OO decision. But don’t take my word for it, have a read of what the man in Google has to say about it. According to him, not only do you get all of the OO benefits above, but DIoC also gives you:

  • No circular dependencies
  • No ambiguous dependency-injection order

One final point; one criticism of levelled at DIoC when compared to setter-injection is that you’ll end up with some massive, ugly, multi-arg constructor as you pass in all your state. If you do end up with some multi-parameter constructor, then that’s not a problem with DIoC, that’s code-smell for an object that depends on too much. That’s not a DI problem; that’s an OO problem.

And what about JavaBeans and Reflection?

JavaBeans require a public default constructor and getters/setters for all of your state. How can you set state on construction when you have to provide a default constructor and getters/setters? Well, we had exactly this problem on a recent project, and I think that we came up with a really neat way of solving it. But I think that deserves a post all of its own.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: