Tuesday, 4 March 2008

Dynamically generating Builder implementations, part 1.

« "Overriding" a third-party method in javascript | Main | Just another day at the abandoned factory »

In my current project, we have a lot of immutable values (a side effect of the fact that we have a bitemporal domain12, but that is a story for another time). We decided to actually enforce that immutability, so those values have no methods that mutate its state (a.k.a. setters). So all properties must be set at creation time using the constructor.

Now, some of these value classes have 10+ properties, so instantiating everything using the constructor isn't an attractive or readable option. Ideally, you'd use some kind of Builder Pattern to set those properties and create the actual instance once you're done setting them.

The only part that sucks about using Builders is that you have to code, test and maintain them. This is the part where dynamic proxies and code generation can come to the rescue. In the way I implemented this, we have three components in the solution:

  • The immutable value class (OrganizationState is this example).
  • Builder, an interface that defines a Builder, which is a class that knows how to build instances. This one should be extended for each concrete type you want to build, containing setters for each of the properties you want to set.
  • BuilderFactory, a concrete class that can generate an implementation of the right Builder. This is done using JDK proxies.

Using those components looks like this:

The value class and its accompanying Builder interface:

public class OrganizationState implements Serializable, Reported {

	private Day foundedOn;
	private Day endedOn;
	private OrganizationEndReason endReason;
	private OrganizationType type;
	private EstablishmentType establishmentType;
	private KboStatus kboStatus;
	private Reporter authenticReporter;

	public OrganizationState(Day foundedOn, Day endedOn,
OrganizationEndReason endReason, OrganizationType type,
EstablishmentType establishmentType, KboStatus kboStatus, 
Reporter authenticReporter) {
		this.foundedOn = foundedOn;
...
public interface OrganizationStateBuilder extends
 Builder<OrganizationState> {
	void setFoundedOn(Day foundedOn);
	void setEndedOn(Day endedOn);
	void setEndReason(OrganizationEndReason endReason);
	void setType(OrganizationType type);
	void setEstablishmentType(EstablishmentType establishmentType);
	void setKboStatus(KboStatus kboStatus);
	void setAuthenticReporter(Reporter authenticReporter);
}

As you can see, we have 7 properties that need to be set. Using a constructor would lead to wieldy, unreadable code, especially when you have have lots of properties of the same type. The Builder interface itself looks like this:

public interface Builder<V> {

	/**
	 * Initialize the V instance being built by the builder
         * with given prototype instance.
	 * @param prototype
	 */
	void fromPrototype(V prototype);

	/**
	 * Build the product (a V instance) and return it.
	 */
	V build();
}

Now the client code for using a Builder looks like this:

 
//create an implementation of the OrganizationStateBuilder, using JDK proxies.
OrganizationStateBuilder builder = BuilderFactory.createBuilder(OrganizationStateBuilder.class);

//set the properties on the build, from is a TO that comes from the frontend.
builder.setAuthenticReporter(from.getOrganizationInfo().getAuthenticReporter());
builder.setFoundedOn(from.getOrganizationInfo().getStartDate());
builder.setEndedOn(from.getOrganizationInfo().getEndDate());
//set some more properties
...

//build the actual instance.
OrganizationState state = builder.build();
It is also possible to create an instance that takes its initial values from another instance. This is very especially useful if you only need to change a single property:
OrganizationState prototype = ....;
...
OrganizationStateBuilder builder = BuilderFactory.createBuilder(OrganizationStateBuilder.class);
builder.fromPrototype(prototype);

builder.setFoundedOn(Day.today());
//build the actual instance.
OrganizationState state = builder.build();

As you can see, this code look much easier on the eyes than the equivalent constructor based version would look. For the next part, we'll look at how the BuilderFactory is implemented, and I'll talk about the how this code is generated and tested.




  1. [1] My colleague Erwin Vervaet made an excellent presentation at the Spring experience about this subject.

  2. [2] Martin Fowler has also written on the subject at http://www.martinfowler.com/eaaDev/timeNarrative.html.

Posted by cvf at 11:14 PM in Java

 

[Trackback URL for this entry]

Your comment:

(not displayed)
 
 
 

Live Comment Preview:

 
« March »
SunMonTueWedThuFriSat
      1
2345678
9101112131415
16171819202122
23242526272829
3031