Martin Fowler has written a very interesting blog post called "FluentInterface". I really must give this a real try in my own designs! All of a sudden my APIs feel very old-fashioned and stiff...

Just to keep the pot boiling, I'd like to check some variations on Martin's example with you.

Martin wrote the code for creating a new order like this:

private void makeFluent(Customer customer) {
    customer.newOrder()
        .with(6, "TAL")
        .with(5, "HPK").skippable()
        .with(3, "LGV")
        .priorityRush();
}

One thing about the snippet that I'm not sure I really like is how skippable() is dealt with. with() is returning the order so skippable() will be set not for the order line, but for the order. Of course the solution is simple; skippable() is affecting the last added order line. Nevertheless, I'm not 100% happy with this solution, although that's not important for the rest of the discussion. So, with that out of the way, let's continue.

OK, let's put this in a certain context. How would you write this if you want to build the order dynamically because of user actions? I mean, adding one order line at a time? Let's try out some proposals and see what you think. First the order itself is created, like this:

Order newOrder = customer.newOrder()
    .PriorityRush();

or maybe like this:

Order newOrder = new Order(customer)
    .PriorityRush();

Then the user picks a product so we add a line like this:

newOrder.AddLine(6, "TAL");

Well, I think AddProduct() feels better:

newOrder.AddProduct(6, "TAL");

Then another product is picked, and this one can be skippable:

newOrder.AddProduct(5, "HPK").Skippable();

If AddProduct() returns the orderLine instead of the order, then the Skippable() thing feels good again.

Instead of letting numberOfItems be a parameter to AddProduct (), it could be a property like this:

newOrder.AddProduct("TAL").NumberOfItems = 6;

But then we get a problem with Skippable()... NumberOfItems() also can be a function instead like this:

newOrder.AddProduct("HPK").NumberOfItems(5).Skippable();

Nah, I think numberOfItems was better as a parameter, but you get the idea for other purposes. No matter what, the whole thing is no longer as fluent I'm afraid...

Any better ideas? (You can contact me here.)

BTW, here's another thought. Do you think it's wise to add a fluent interface on top of the primitive one? For the consumer to use the one he prefers for a certain situation he would do something like this:

FluentOrder order;

or

PrimitiveOrder order;

Or should there only be a fluent interface exposed, if there is one at all?