Tuesday, April 25, 2006

Why I hate the default constructor


Hmm, I think I should provide a more detailed (boring) explanation on the reasons why the default constructor is in the list of my most hated anti-patterns.

Back to basics
OO theory provided us with the gift of encapsulation: the ability to hide details of the internal structure of an object by providing access control to attribute and methods thus allowing to split the exposed behaviour of an object (its interface) from the internal structure (the implementation).

The rule of thumb says that you should define all of your attributes private, and then provide public methods for the interactions with other classes. It’s a common practice (a short way to say that I quite disagree with that, but this will drive me out of scope) to provide also public methods to access the properties of the object, in a JavaBeans like fashion.

JavaBeans specification
JavaBeans specification defined that a special category of java objects, the Beans, was identified by the following properties
  • presence of a public parameterless constructor

  • presence of public methods to access properties of the object, such as getters and setters in the form of getPropertyName() and setPropertyName(…)
Plenty of discussions arose on the subject “is JavaBeans specification breaking encapsulation?” arguing that making attributes public would have had the same effect.

Unfortunately, what most of the developers forgot was that java beans specification were meant to be used by tools like IDEs (one of the first implementation of the spec was used to add user defined graphics object in a graphical environment, so that you could create your components and add them to the JBuilder palette) or frameworks like Castor or Hibernate. Java Server Pages also use Java Beans as the underlying object for the pages. Java Beans specification allowed tools to dynamically access properties of given (and unknown) objects by relying on introspection, driven by the coding conventions mentioned above.

Having a commonly accepted syntax for accessor methods, was a good result indeed, but was largely abused. But this gave new popularity to the empty constructor anti-pattern.

Why is the empty constructor evil?
Ok, I need a basic example to start from. Suppose we have a simple class like this:
public class Person {

private String name;
private String surname;

public Person() {}

public String getName() { return this.name; }
public String getSurname() {return this.surname; }

public void setName(String name) { this.name = name; }
public void setSurname(String surname) { this.surname = surname; }
}

By creating an empty object, and
then setting its property in a
Person p = new Person();
p.setName(“John”);
p.setSurname(“Smith);
fashion, we make a series of mistakes. At the end of the execution the result is just like
Person p = new Person(“John”,”Smith”);
assuming that we defined in Person.java a constructor like
Public Person (String name, String surname) {
this.name = name;
this.surname = surname;
}
But unfortunately the result it’s not the same during the execution. In other words object initialization is not atomic in the former case, while it is atomic in the latter. Moreover, the second constructor encapsulates creation logic, knowing that you need both name and surname to have a fully functional Person object. Using the default constructor, anybody trying to initialize the class should be aware of the internal details of the Person class to initialize the class.

Suppose then that you need instances of your class in different areas of your software. Every time, you should create your objects in the correct fashion. To do so, you normally would use the best replacement for OOP: cut & paste (which is a form of reuse after all…). Suppose then that you need to add an extra attribute to the Person class, namely birthDate, and that this attribute is required. Guess what? Changing the robust constructor to
public Person (String name, String surname, Date birthDate) {
this.name = name;
this.surname = surname;
this.birthDate = birthDate;
}
raises compilation problem on every invocation of the constructor. Is this a bad thing? Not at all! It allows you to correct every single invocation. It can be a simple job, or a tricky one (if the newly needed parameter is not so easy to get), but it ensures that the object is in the correct state. The other way round raises no compilation error, you know that you have to correct the code anyway, so you have the following options:
  • search every instance of new Person() throughout the code base and check that all the three setters are called (do you think that it’s fastest than fixing the compile errors?)

  • search some known instance of new Person(), add the new setter, and have a coffee

  • add the setter where we need it and let somebody else deal with the nullPointerException they are 99% likely to get.
Conclusion (where I explain my bitter mood)
What really puzzles me is that, every in the simplest situation, invoking the default constructor is almost always wrong! If your class has attributes, then you should favour a robust constructor instead, and makes you write less code. If it doesn’t have one, then maybe you don’t need a constructor at all but you could access static methods or use a factory to create your object. The only reason why we abuse so much this anti-pattern is just because we are damn lazy.

Tags: , ,

Monday, April 24, 2006

I hate the empty constructor


I was looking for inspiration for a short post about the abuse of the parameterless constructor. Then I found this and thought that there’s not so much else to say. If there is still somebody still convinced that

Person p = new Person();
p.setName(“John”);
p.setSurname(“Smith”);

is still as good as

Person p = new Person(“John”,”Smith”);

…please leave a comment.

Ok, then I thought this was a little bit too short, and wrote down some more explanation in the following post.

Tags: ,

Monday, April 17, 2006

Coding, the IKEA way


Today I spent some time mounting handles in an IKEA wardrobe I bought some weeks ago. Mounting handles is somehow a precision job, cause you don’t want your house to look like a cartoon room. So, I took measurements of the drawers, and of the handles, asked my wife in which position the handles looked better, tried to fit the preferred position with some basic proportion (so that the spaces above and below the handle are respectively ¼ and ¾ of the total drawer height), then calculated on paper the exact coordinates for the needed hole. The next step was to apply the measurement on the drawers. I didn’t have a professional measurement tape at home so I double checked all the measurements before marking with the pencil the final target for the drill. When I was satisfied wit the position I made a small hole with a nail in the exact position. Then I took the drill. Everything was in place so the result was pretty close to perfection.

It’s surprising how far we can go from this metaphor if we just turn back to our beloved coding activity. When asked to perform a simple, yet nontrivial, task, the average developer would switch on the IDE (I am optimistic, the IDE is obviously already on by default, and the mail client is now probably an Eclipse plugin) and start coding. A couple of lines there, a TODO marker when an ugly shortcut is taken, another couple of lines there, and the job looks almost complete. Then a failure during test sets the need for another quick fix just before the deadline. Ooops! Time for removing TODOs has gone, the code seem to work and there are more urgent things to do. In other words, the TODOs just made it to production. Cheers!

Let’s get back to my IKEA drawers. Really I should have started from the drill (which is my favourite tool anyway)! Making a couple of holes in the wardrobe (just to check if the drill worked) then refining the hole positioning by successive attempts. This way the handle probably wouldn’t be that aligned, or perfectly fixed, so I would probably have had to put some stuff to have the handles blocked some way. Of course there is only one probability over a million that all the handles are vertically aligned and centered in all the drawers, and I should have used some tape to close the unnecessary holes I did at the beginning, but as long as the whole wardrobe doesn’t fall apart I should have been pretty satisfied.

Ok, I probably went too far. Code can just be erased, while drill holes are irreversible. Well, code can be cleaned if you have time and we all know that you’ll never have…

Tags: ,