Monday, August 04, 2008 9:48 PM
Fluent interfaces are a great way to make your code more readable, and the express your intent in a clearer, often more concise, way.
A hallmark of a good fluent interface is the ability to seamlessly string together an arbitrary number of objects and still have your code resemble spoken language. For example, consider the following snippet of code from a builder object built with a fluent interface…
var larry = new CustomerBuilder().WithName("Larry").WithAge(30).Build();
The fluent interface applied to the code makes it incredibly simple for anyone to ascertain the intent of this code at a glance. The key to this ability to easily chain members together in nearly any order is that each member of the class returns a reference to itself. This reference can then be used to to add additional commands onto the chain. Let’s take a look at the CustomerBuilder class…
internal class CustomerBuilder
{
private string _name;
private int _age;
public Customer Build()
{
return new Customer(_name, _age);
}
public CustomerBuilder WithName(string name)
{
_name = name;
return this;
}
public CustomerBuilder WithAge(int age)
{
_age = age;
return this;
}
}
Notice that with the exception of the Build() method, each of these method signatures have a return type of their parent class, CustomerBuilder. Beyond that, notice that all of those methods satisfy that signature by returning a reference to the current object. This allows us to continue to alter the method under construction, either by setting the name or age, without losing context. The afore mentioned Build() method returns the newly constructed object once we’ve finished setting the properties. This trick of almost always returning the current object from a method is what allows us to easily chain objects together to create more naturally spoken code. If you think this looks great in C#, you should try it in a more terse language such as Boo.
Next time we’ll dive deeper and talk about some of the issues which come up when you try to mock a fluent interface.