Home > API and Patterns, Fluent interfaces > Dealing with immutability and long constructors in a fluent way.

Dealing with immutability and long constructors in a fluent way.

I use to state that the best thing to do is to keep your code simple and clean. But if your task is to design an easy-to-understand and easy-to-change API, this may be a bad advice. There simply is no silver bullet in programming and simplicity ain’t one either.

There is a common case you may have encountered more than once, which is long constructors with repeating types. You’re likely to see them in immutable classes. I’m not going to discuss why immutable classes are desirable, I’m going to talk about easing the pain to construct them. Take this for example, I must admit that I tended to write code like this quite often.:

@Immutable
public Address(String street, String zipcode, String town, String country){
 //...
}

True, the IDE may help you with displaying the parameter names in a pop up, but no one will warn you if you get the order wrong and if Murphy loves your company, you’ll end up with a pile of unusable data in a productive database. It gets worse if you decide to re-factor the class. If you change the parameter order of example, it just needs a bad moment for a CVS-commit to cause major mayhem, which gets more likely the bigger the team and the higher the fan-in-complexity of the class is.

This can be avoided, unfortunately at the price of complexity. Let me introduce to you two approaches: The copy-mutator-method and the builder-class.

Copy-Mutator

This pattern is quite nice to enforce immutability and at the same time avoid problems with ambiguous constructor arguments plus it is easy to write, but it has downsides. Let me first show the source code and discuss the rest later.

@Immutable
public final class Address{

  private String street;
  private String zipcode;
  private String town;
  private String country;

  public Address(){}

  private Address(final Address a){
   street=a.street;
   zipcode=a.zipcode;
   town=a.town;
   country=a.country;
  }

  public String getStreet(){
   return street;
  }
  //..

  public final Address withStreet(final String steet){
   final Address a=new Address(this);
   a.street=street;
   return a;
  }

  public final Address withZipcode(final String zipcode){
   final Address a=new Address(this);
   a.zipcode=zipcode;
   return a;
  }

   //..
}

Here we go. To initialize an object with this pattern is a nice and fluent expression:

Address home=new Address()
 .withStreet("Sesame St. 10")
 .withZipcode("12345")
 .withTown("Muppetcity")
 .withCountry("USA"); 

So why not simply use a bean and setters? Well, it may be just as readable, but objects made like this can be immutable and beans can not. So if you want to enforce immutability, here’s a solution.

But there are downsides to this pattern:
First, the fields are not final, which requires a little more care when you touch and change the internals of the class, so you don’t introduce mutable state to an immutable class by accident. I would consider that a low risk, but it’s there.

Secondly this pattern creates a lot of intermediate objects that get thrown away immediately. This may seem to be a problem if you want to create a lot of these objects in a tight loop, but it isn’t. It isn’t, because you will rarely find yourself in a situation, where such a constant cost is a real issue – and if you do you can still tune this hot spot and keep the rest of the code tidy. And it isn’t because a modern JVM can handle these kind of object allocations very well, as pointed out in this excellent article by Brian Goetz. So consider this a non-issue.

The last downside with this pattern I’d like to mention is the only real downside in my humble opinion: If your requirement is to disallow “null” for any fields, you have a problem.
You’d have to write a method to check the fields against null, but you are not forced to call it right after initialization. And if you install a check at field-access time, your object may cause an exception way after initialization, which makes it hard to impossible to find the cause, because you needed to check every initialization.
In short: If you need to check invariants on initialization, this pattern is not an option.

Luckily there is another pattern which allows to avoid this particular downside at the expense of some more lines of code:

The Builder

The builder is a mutable object which creates the immutable object after checking everything is set up as required. Because the builder is mutable it cannot be shared safely among threads (thanks for the hint, Theo!). It is therefore wise to prevent any other thread from accessing the builder than the one that created it. A simple barrier will do the job:

public class SingleThreadBarrier{
 private final Class<?> c;
 private final Thread thread;
 
 public SingleThreadBarrier(final Class<?> c){
  this.c=c;
  thread=Thread.currentThread();
 }

 void pass(){
  if(thread != Thread.currentThread()){
   throw new IllegalStateException("Multithreaded access to "+c+" forbidden.");
  }
 }
}

Now with our barrier ready to go, let me show you the sourcecode for the builder:

 @Immutable
 public final class Address{

  private final String street;
  private final String zipcode;
  private final String town;
  private final String country;

  private Address(final AddressBuilder b){
   street=b.street;
   zipcode=b.zipcode;
   town=b.town;
   country=b.country;
  }

  public String getStreet(){
   return street;
  }
  //..
  
  public static AddressBuilder build(){
   return new AddressBuilder();
  }
  //..

  public static class AddressBuilder{
   private final SingleThreadBarrier barrier
    = new SingleThreadBarrier(getClass());
   private String street;
   private String zipcode
   //..
   public AddressBuilder withStreet(final String street){
    barrier.pass();
    this.street=street;
    return this;
   }

   public AddressBuilder withZipcode(final String zipcode){
    barrier.pass();
    this.zipcode=zipcode;
    return this;
   }

   //..
 
   public Address noNullPropertyAllowed(){
    barrier.pass();
    if(Arrays.asList(street, zipcode, town, country).contains(null)){
      throw new NullPointerException();
    }
    return new Address(this);
   }

  }
 }

As you can see building an address with this pattern is just a tiny bit longer, but still a very fluent expression which almost reads like a book:

Address home=Address.build() //get a builder object
 .withStreet("Sesame St. 10") //initialize the builder
 .withZipcode("12345")
 .withTown("Muppetcity")
 .withCountry("USA")
 .noNullPropertyAllowed(); //check builder's setup and construct the address

One nice thing about this pattern is, for a start, that the fields of the immutable object are final, so you can’t create a mutable state by accident. The more important goodie is the method which finally checks and constructs the immutable object. Because you can have more than one! In other words: it’s an extensible design. I just wrote a very basic implementation to keep it short, but you may add other validation methods without breaking anything and when you start thinking about it for a moment, things like “@NotNull”, annotations in general, “Reflection” and “Strategy Pattern” might spring to mind. Maybe I’ll revisit this topic in a later blog posting, but for now I’ll call it a day and leave you with your own thoughts or even the urge to comment, which is highly appreciated.

Advertisements
  1. theo
    March 21, 2010 at 00:28

    One usage for immutables is in multi threading. But there you want final fields. Neither the first solution nor the second one are safe in that I think.

    • March 21, 2010 at 14:46

      The first solution doesn’t allow any state change for the user of the API, so it’s effectively immutable and thread safe. I also can’t think of any way how two threads could see another version of a variable, can you? Let’s not think about reflection here, because you can even change final fields with reflection, as pointed out by Dr. Heinz Kabutz in this short acticle.
      The second solution has final fields for the immutable class, so it’s safe like any other immutable class. The builder itself is mutable, but I thought that would be okay, because the builder was not meant to be shared among threads. One could argue that it is still possible to do so, I agree, so I have installed a barrier to prevent such kind of misuse.

  2. javacoder42
    March 22, 2010 at 16:08

    I think the biggest shortcoming of the builder approach is not mentioned:
    In contrast to the c’tor approach you would not get a compile time error if u forget to call a “with” method.

    looks like there is no silver bullet for this kind of problem in Java.

    Another idea is to:
    public Address(Street street, Zipcode zipcode, Town town, Country country){

    }

    But this will lead into much more code. 🙂

    • March 22, 2010 at 18:38

      You’re absolutely right, this is what I miss too. You could enforce compile time errors by using a lot of intermediate classes, but then you had to create those classes using a template-engine to keep it convenient. Does anybody else hear an “over-engineering” warning signal coming closer?
      Your solution with own types instead of Strings would afford to check every parameter type for immutability.

  3. javafinanceguy
    April 10, 2010 at 22:25

    In my opinion, there are two different types of unchangeable objects, one is immutable and other is read only. what you’re describing seems like a read only object and not immutable object. immutable objects were designed for state machines, where usually thru a single property that would provide sufficient information on the state.
    Builder pattern [as in your post] or Factory patterns can be used for creating such immutable objects.
    but for ready only, the object needs to ensure that properties are safe guarded whenever its instructed to do so.
    AOP can be used to ensure setter methods are locked out [annotations can be also used to do this]

    • April 11, 2010 at 03:01

      Thanks for your feedback, it’s truly appreciated. Keep the food for my brain coming!
      As for the definition linked below, I would consider the object described in the second part (builder) truly “immutable” object. The first object may be a corner case though, as it gets changed after construction. However, since that change is a completely internal affair (of the factory method, which is inside the class itself) I would consider it immutable too. Well, it probably depends on how you define “construction” in this case: the successful call of the factory method or the (internal) call of the constructor. I’d vote for the factory method. In the java.lang.String class, the internal char[] cannot be completely safeguarded from internal modification, which is actually the same as with the class in the first example. But does that make a String “read only” instead of “immutable”? Oh, one thing I noticed: I should have made the classes “final”. I wouldn’t have noticed without your comment. Thanks a lot, I’ll correct that.

      http://java.sun.com/docs/books/tutorial/essential/concurrency/immutable.html

  4. August 3, 2010 at 15:49

    Looks like this topic is hot, as someone has just posted a quite similar article on DZone:

    http://java.dzone.com/articles/immutability-with-builder-design-pattern

  5. seb
    September 16, 2010 at 19:15

    I don’t know why everyone uses a static inner class for their builder implementation. It’s way better to move them to a separate class (why not give them their own interface, too?) and create a new builder each time you want to build a complex object. that way each thread can create have its own builder and you won’t have to check for concurrent access to that class.
    Finally checking the state of the object before returning it in the get()/build/whatever() method is essential IMHO. That way all returned objects are always fine, which is especially nice when you want to avoid NPEs or other common problems.

    • September 16, 2010 at 22:15

      The class is static so you don’t need an instance of “Address” to create a builder, which makes some sense if you think about it.
      The builder is an inner class to tie it to the built object and to get some control over its use (you could make the constructor private or the class final for example).

      A seperate top level class would make no difference in terms of synchronization. Take this simple example:

      //top  level
      final AddressBuilder builder=new AddressBuilder(); 
      Thread a = new Thread(){
       public void run(){
        builder.withStreet("Sesame street");
        //...
       }
      };
      Thread b = new Thread(){
       public void run(){
        builder.withStreet("Elm street");
        //...
       }
      };
      a.start();
      b.start();
      a.join();
      b.join();
      Address address = builder.build();
      

      Who comes first wins – not desirable.
      To avoid users from doing this, you’d need a barrier like sketched above, even if you don’t have static class.

  1. No trackbacks yet.

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: