views:

147

answers:

4

So I've been reading Effective Java by Joshua Bloch and noticed two points which I actually have encountered in my work.

Point 1: Making setter methods to make code more readable. In his example, we have a class with a ridiculously huge constructor. When people instantiate the class, it's hard to tell what's going on with all the parameters. Thus, he suggested making a minimalistic constructor and have setter methods for all other options, so instead of...

MyClass clazz = new MyClass(a, b, c, d, e, f, g);

you would write....

MyClass clazz = new MyClass(a, b, c);
clazz.setDitto(d);
clazz.setEcho(e);
clazz.setFunzies(f);
clazz.setGumballs(g);

Which, as a huge supporter of readable code, I liked a lot.

Point 2: In general, he suggested having immutable classes. He goes into great depth on why having immutable classes is much better than having a class that could be in several different states. I can definitely say that he sold the idea to me, and I can't wait to make most classes I write from now on immutable, except....

What happens when you have an immutable class with a huge constructor? You can't make setter methods for it; that would break immutability. I tried skimming through the rest of the book, but I don't think he covers a solution for this.

There is the possibility of making one-time use setter methods, but just the fact that a setter method is available to a class that is supposedly immutability is disheartening, even if it does just throw an Exception if you try it subsequent times.

Does anyone have any good ideas on how to handle this problem? I'm currently facing this issue at work where I have an Immutable class with a huge constructor which I'd like to refactor to something that's more readable without breaking immutability.

+11  A: 

One option is to provide a separate builder class that provides the setters, which is responsible for constructing the actual object.

In the second edition of Bloch's "Effective Java", item 2 illustrates this for an immutable class. The key ideas are:

  • The builder has a mutable field for each option.
  • The builder passes itself as a single argument to the immutable class's constructor.
Andy Thomas-Cramer
+1 Builders with chainable methods actually improve the readability over a mutable object with `void` set methods, in my opinion.
ColinD
Agreed. Bloch includes chainable setters in the example builder mentioned above.
Andy Thomas-Cramer
Brilliant! I can't believe I missed that. I was mostly skimming the immutability section, completely forgot to check back to the constructors.
Noj
+3  A: 

Introduce Parameter Object, maybe? It kind of moves the problem around, but maybe in useful ways. Your parameter object needs no methods; it just holds the data, and you set it up, instead of your real class. Then your real class initializes itself in the constructor via the parameter object.

Carl Manaster
A: 

How about having an abstract base class which supports getters but no setters for all the attributes of the class, a derived sealed "immutable" class whose constructor accepts a base-class object, and a derived mutable class which includes setters for all the properties?

supercat