Fluent Interfaces Require Fluent Situations

My friend and coworker Mike Naberezny wrote recently of fluent interfaces (a.k.a. object chaining). You should read more about it there, but in the mean time, here's an example usage provided by Mike for a new customer order with multiple lines and a shipping priority:

$customer->newOrder()
         ->with(6, "˜TAL')
         ->with(5, "˜HPK')->skippable()
         ->with(3, "˜LGV')
         ->priorityRush();

The idea is that the fluent interface makes it very easy to read the resulting code in a way that flows naturally. This is cool, but I want to add a caveat to his examples.

I think, for a fluent interface to be effective, you need situations where you actually have all that information at one time so that you can chain the methods in a fluid way. In the above case, we actually know what the whole order is, what the shipping priority is, etc. But very often (I would say "almost always") you *don't* know what the whole customer order is. Instead, you are more likely to iterate through the order lines as the customer adds them, or as you retrieve them from some data source. You might need something more like Mike's initial contra-example:

$order = $customer->newOrder();
foreach ($line as $item) {
    $order->with($item['number'], $item['type']);
}

That's not to say that a fluent interface cannot perform in such a way (it can if written to allow for it). My point is that writing class methods in a fluent interface style may not be worth the effort when you don't often expect to have all the necessary information at once; however, if you *do* expect to have that information, it can be very nice. For example, I could see where a fluent interface could be quite effective in something like Solar_Sql_Select. Currently, you need to do this:

$select = Solar::object('Solar_Sql_Select');
$select->cols('*');
$select->from('table_name');
$select->where('colname = ?', $value);
$select->order('colname DESC');
$result = $select->fetch('all');

But with a fluent interface, one could do it this way (which seems very clean to me at this point):

$select = Solar::object('Solar_Sql_Select');
$select->cols('*')
       ->from('table_name')
       ->where('colname = ?', $value)
       ->order('colname DESC');
$result = $select->fetch('all');

Anybody have thoughts on this particular style of expression?

Are you stuck with a legacy PHP application? You should buy my book because it gives you a step-by-step guide to improving you codebase, all while keeping it running the whole time.