@since Tuesday, February 1, 2011

Builder Pattern for Persistence Objects


Usually, when dealing with persistent entities we would like to keep records at the same state they are stored in the database and keep the newly created entities unmodified until we are persisting them to a database. The first requirement is quite easy to accomplish when using interfaces. For instance, our data access layermight export the following as its domain objects:


Notice that our domain object interface doesn't expose any mutators (setters). Client retrieving these records is unable to change their state. If your services are read only - we're basically done. We hide our concrete implementation by declaring those classes as private package visible (I would also add final to be even stricter) and initialize them anyway preferable (constructor, setters). Easy, right?

Now, let's say our service enables CRUDoperations. We present our clients with the option to persist entities by passing a DTO/ VOimplementing the same interfaces as shown above. First ( Lazy) option: the client can have its own domain hierarchy implementation based on our published interfaces. Hmmm, nice option, but we don't want to force our clients to have unnecessary code when we can provide it with some assistance. Second option, publish our DTO and force the client to create the object by passing alldata values to the constructor (no mutators) - better, but what if our constructor has 5-6 (or more) fields? [ code smell] Third option: expose a default constructor and mutators and have the client initialize the object with multiple invocation lines, one-per-setter (we can have a mix mode of the 2 ndand 3 rdoptions but it's still the same). But, leaving mutators exposed might damage our requirement of keeping our entities unmodified until we reach the actual persist part. So, what should be a better option (I don't think it's the best, since any solution should fit the desired requirements)?

Here comes the builder pattern - we offer the client easy initialization of DTOs but prevent it from changing it once it's done. We add an inner  private static class called Builder which will allow easy initialization of our domain objects. Why inner class and not FooBuilder ? That's simply a flavor, I prefer having a class called Builder for each of my domain objects. Both options (inner or external) will give us the same result and have the same structure. Let's say we have the following DTO as our Foo implementation:


I won't go into details describing the DTO itself, simply say that I'm using Hibernateas an ORMand added some Hibernate Validatorsto give it a more realistic look and feel. Notice the default constructor is not available to client interaction (Hibernate can easily interact with it) and so does our mutators (private package scope). Another thing to notice is the special care we give collections: we never return the actual field or use the parameter given to us (collections are mutable [ 1, 2]). So, how can our clients initialize the above DTO? By using a Builder!


This example is what the general design should be like. For each mutator method we expose on our builder we can add validation logic or validate the entire object in the build() method. Notice we added 3 static factory methods to our original DTO to support 3 operation types: creatinga new instance, updatingan existing one or mergingvalues from existing one to a new instance. Another point to notice is that our builder returns itself from each mutator and that the build()method returns the interface (blocking any future changes to the instance). For ease of use we can add helper mutators to create complex objects by passing parameters to our builder to create (e.g. class holding IP and port - add  setIpAndPort(IP ip, int port)  and  setIpAndPort(IpAndPort ipAndPort)  to our builder)

With this approach we get the requirements we asked for when offering our clients CRUD operations. This design guideline might look as an overkill but the maintenance benefits and ease of client usage is what we're really looking for. With modern IDEs (like Eclipse, IntelliJor NetBeans) we can simply create a coding template to auto-generate builder implementation for our persistence objects. This design is not limited to persistence layer. Every time you need to create an object with too many constructor arguments (and you prefer not to refactor that class) - use a builder. Builder pattern - another tool in your clean code toolbox. 

No comments: