June 22, 2008

Setter methods make kittens cry

Do use setters if being edited is the central purpose of that class. Do not use setter methods to create an object. Setter methods intended for creation will still be accessible during the whole lifetime of the object. Someone might use them and break all your stuff. Basically everything involving caches or hashCode() will die in your arms. Like when changing an attribute will cause some remote piece of code have maps with broken mappings and suddenly sport sets with duplicate elements. Being paranoid makes for good code karma.

Furthermore, do not use setters to wire up required attributes. I often see code like this:

Foo foo = new Foo();
foo.setAttribute1(a1);
foo.setAttribute2(a2);
foo.setAttribute3(a3);

This is bad because until the last line has executed, foo lives in some sort of twilight zone, where it exists but may not be used yet. Your class should not allow to create an object with invalid state. Better use the constructor to wire up attributes:

Foo foo = new Foo(a1, a2, a3);

Some people will argue that this will become hard to read if you have a lot of attributes. In such cases you should use a Builder separate factory class that collects all attributes with setters and can create the object once all required attributes are present (otherwise throw an exception). This shifts the enforcement of valid object creation from compile time to runtime, but still fails fast if necessary.

A related point I would like to make is that immutable objects (objects that cannot change their state after instantiation) also make for good code karma. Mutable objects can be a pain to work with and force their clients to make defensive copies. Immutable objects are also thread-safe by default (you might still screw it up though).