Fluent Object Creation

When we are tasked with creating a POJO we will often fire up our favorite editor, add the attributes, and generate the accessor methods.

Here is an example of an Invoice class. For simplicity sake only a few of its many attributes will be shown.

public class Invoice {

	private InvoiceActor invoiceSupplier;
	private InvoiceActor invoiceDestination;
	private String supplierDocumentId;
	private Date documentDate;
	private String trailerNumber;
	private List<InvoiceItem> items;
	...

Given this code we would then create an instance of our Invoice and use our setters to populate the values of the attributes.

InvoiceActor supplier = new InvoiceActor();
supplier.setActorName("101");
supplier.setActorType(InvoiceActorType.DC);
...

List<InvoiceItem> list = new ArrayList<InvoiceItem>();
InvoiceItem itemOne = new InvoiceItem("TK421", 10, 8);
list.add(itemOne);
...

Invoice inv = new Invoice();
inv.setSupplierDocumentId("5150");
inv.setTrailerNumber("2112");
inv.setInvoiceSupplier(supplier);
inv.setInvoiceDestination(reciever);
inv.setItems(list);

When creating our POJO, we could add a constructor to our class that accepts the values for the various attributes so that they are initialized when the object is created. It allows us to create the object with less code than what we see above. It can also allow us to insure that our object was in a valid state at the point it is created (see Constructor Initialization for more details). And if we were going to make our Invoice class an immutable object we would need to get rid of the setters so we would typically turn to a constructor with parameters as an alternative to populate the attributes.


	public Invoice(InvoiceActor supplier, InvoiceActor dest, String docId, Date docDate, String trailer,
			List<InvoiceItem> list) {
		this.invoiceSupplier = supplier;
		this.invoiceDestination = dest;
		this.supplierDocumentId = docId;
		this.documentDate = docDate;
		this.trailerNumber = trailer;
		this.items = list;
	}

Which allows something like this:

InvoiceActor supplier = new InvoiceActor("101", InvoiceActorType.DC);
...
List<InvoiceItem> list = new ArrayList<InvoiceItem>();
InvoiceItem itemOne = new InvoiceItem("TK421", 10, 8);
list.add(itemOne);
...
Invoice inv = new Invoice(supplier, reciever, "5150", new Date(), "2112", list);

But if we had a lot more attributes, as a real Invoice class might, this would lead to a Code Smell (if it isn’t one already). Specifically, the Long Parameter List, a smell in the Bloater category of things to be avoided.

_agilewars_codesmells_

A long list of parameters makes the calling of the constructor difficult when trying to make sure the correct values are in the correct order. This is particularly true when there are a number of parameters with the same type. In this example we may wonder, was that the supplier or the receiver that came first in the list?

One way to solve this problem is through a fluent interface. Martin Fowler describes the fluent interface as an API “designed to be readable and to flow.”

Here is the code we would use to create an Invoice with a fluent API.

Invoice inv = Invoice.createdOn(new Date())
		.withDocumentNumber("5150")
		.shippingOnTrailer("2112")
		.suppliedBy(InvoiceActor.create()
		    .named("101")
		    .as(InvoiceActorType.DC))
		.beingSentTo(InvoiceActor.create()
		    .named("42")
		    .as(InvoiceActorType.STORE))
		.with(InvoiceItem.create()
		    .as("TK421")
		    .orderedQuantity(10)
		    .shippedQuantity(8))
		.with(InvoiceItem.create()
		    .as("FN2187")
		    .orderedQuantity(5)
		    .shippedQuantity(5));

This code is much more readable than either the setter initialization or the constructor initialization.

To create a fluent API, our setter methods must return an instance of the Invoice we are creating. Typically the methods are renamed so that the code for our object creation reads like a sentence.  Here is the code making our Invoice POJO fluent:

public class Invoice {

	... attributes ...

	/**
	 * fluent static factory method
	 */
	public static Invoice createdOn(Date date) {
		Invoice inv = new Invoice();
		inv.setDocumentDate(date);
		return inv;
	}

	/**
	 * fluent setter for trailer
	 * @param trailerNum
	 * @return Invoice
	 */
	public Invoice shippingOnTrailer(String trailerNum) {
		this.trailerNumber = trailerNum;
		return this;
	}

	/**
	 * fluent setter for document number
	 * @param docNumber
	 * @return
	 */
	public Invoice withDocumentNumber(String docNumber) {
		this.supplierDocumentId = docNumber;
		return this;
	}

	/**
	 * fluent setter for Supplier
	 * @param docNumber
	 * @return
	 */
	public Invoice suppliedBy(InvoiceActor actor) {
		this.invoiceSupplier = actor;
		return this;
	}

	/**
	 * fluent setter for Destination
	 * @param docNumber
	 * @return
	 */
	public Invoice beingSentTo(InvoiceActor actor) {
		this.invoiceDestination = actor;
		return this;
	}

	/**
	 * fluent setter for items in the list
	 * @param docNumber
	 * @return
	 */
	public Invoice with(InvoiceItem item) {
		if (items == null) {
			items = new ArrayList<InvoiceItem>();
		}
		items.add(item);
		return this;
	}

Not everyone is a fan of adding the fluent API directly to the POJO class as we have done here. This is because  it breaks the principle of Command Query Separation.  The common solution to the setters, constructors with long parameter lists, and adding a fluent API directly to our POJO is the Builder pattern, which is described in this post.

In the next post we will add a nested fluent builder to our Invoice object.

 

Advertisements

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