Friday, 10 February 2012

C# How To: Write a Fluent API

I've seen a number of API's now that utilise a "fluent" interface (e.g., Fluent NHibernate, Moq etc.). So far, I've had mixed feelings about it. If you're not familiar with what a fluent interface is, then Martin Fowler's post on this subject is a good starting point. By following a fluent design, you get some neat looking "client-side" code that is almost self-describing. The following example models a real-world person and exposes a fluent interface.

public class Person
{
    public string FirstName { get; private set; }
    public string Surname { get; private set; }

    private Person() { }

    public static Person New()
    {
        return new Person();
    }

    public Person SetFirstName(string firstName)
    {
        this.FirstName = firstName;
        return this;
    }

    public Person SetSurname(string surname)
    {
        this.Surname = surname;
        return this;
    }

    public override string ToString()
    {
        return string.Format(
            "I am {0} {1}",
                this.FirstName,
                    this.Surname);
    }
}
As the code snippet shows, each setter method in the Person class returns a reference to the "current" object (think context/state). This is important as it permits users of the class to chain method calls on the object, with each invocation returning an up-to-date state of the original object. For example, we can create an instance of Person and then set its state in one single C# statement:

var person = Person.New()
    .SetFirstName("Ravi")
        .SetSurname("Singh");
This looks neat and is very readable. Without a fluent interface, you may have code that looks somewhat like:

var person = new Person();
person.FirstName = "Ravi";
person.Surname = "Singh";
Of course, you could use the object initialiser syntax or pass the names through to an appropriate constructor, but that's not the point. The point is that you don't get the same readability or fluentness that you get using method chaining. If your methods are named properly, then using the fluent technique makes reading your code closer to reading a sentence in natural language.

I personally prefer the fluent version. Earlier in the post, I mentioned that I had a mixed feeling - this mainly stems from the fact that it becomes difficult to debug code that uses a fluent interface. For example, if you have a statement in which a number of method calls are chained on an object, it's difficult to see the intermediary values returned by each method unless you step into each method call. This can be a bit of a pain when debugging. Other than this one problem, I've enjoyed working with fluent-based API's and will strive to write classes in a more "fluent" way.