6

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.

Noj
  • 63
  • 2
  • It would seem a useful concept would be to have a mutable and immutable class derive from a common abstract base (which advertises getters for all the properties). The constructor for the immutable class could accept an argument of the base class. Not sure how to allow the mutable class to shadow abstract read-only properties with read-write ones, though, without creating an intermediate class which implements the read-only properties. – supercat Sep 02 '10 at 23:30

4 Answers4

14

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
  • 84,978
  • 11
  • 107
  • 151
  • 1
    +1 Builders with chainable methods actually improve the readability over a mutable object with `void` set methods, in my opinion. – ColinD Sep 02 '10 at 22:26
  • Agreed. Bloch includes chainable setters in the example builder mentioned above. – Andy Thomas Sep 02 '10 at 22:36
  • Brilliant! I can't believe I missed that. I was mostly skimming the immutability section, completely forgot to check back to the constructors. – Noj Sep 02 '10 at 23:07
3

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
  • 39,912
  • 17
  • 102
  • 155
2

You can go with fluent interfaces: Building big, immutable objects without using constructors having long parameter lists

See also:

Community
  • 1
  • 1
Rodney Gitzel
  • 2,652
  • 16
  • 23
  • Very true, it seems that fluent interfaces are the same idea as builders. Very cool concept. Can't believe I missed it. – Noj Sep 02 '10 at 23:08
0

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
  • 77,689
  • 9
  • 166
  • 211