flow.
"Flow is a condition of deep, nearly meditative involvement." - Tom DeMarco

30 Seconds to a Fluent Interface

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.


Feedback

# re: 30 Seconds to a Fluent Interface

I'm not a fan of methods returning "this" - it just seems like a hack.

What we really need is a .. operator that performs another operation on the previous object, e.g.

var larry = new CustomerBuilder().WithName("Larry")..WithAge(30)..Build();

[)amien 8/5/2008 2:49 PM | Damien Guard

# re: 30 Seconds to a Fluent Interface

Hi Damien,

Thanks for the comment. I agree, the "return this;" can seem a bit awkward. I think an implied operator to do the same thing would be a cool addition to the language, or at least as a macro.

I mentioned Boo briefly in the post. The Boo language (I suppose, more correctly the Boo compiler) is extensible enough to recognize additional custom functionality, adding this ability as an operator could be a cool exercise. I suppose we could walk one level up the call stack using the StackTrace and StackFrame classes to get the calling functions, but I'm just thinking out loud. Regardless, it's definitely given me something cool to think about.

Thanks for the idea!
Jeremy 8/5/2008 9:25 PM | Jeremy

 re: 30 Seconds to a Fluent Interface

Is it worth the hideous code underneath to get this interface? Haskell's type constructors give you this syntax:

createCustomer (Name "Larry") (Age 30)

without the icky intermediate states and return(self) boilerplate.

C# has taken a lot of features from functional languages, I wonder if there's enough leverage to let you do things this way?
8/6/2008 4:48 AM | Greg M

# re: 30 Seconds to a Fluent Interface

I wrote about method chaining here: http://72miles.com/blog/posts/configuration-method-chaining/

But I don't think that fluent interfaces is the same as method chaining. Fluent interfaces are more about the language of the domain and generating readable code that is domain specific. The end result of fluent interfacing is much more than just a simple method chain.

8/6/2008 8:56 AM | Mike

 re: 30 Seconds to a Fluent Interface

Your Build() method is not necessary and you are not returning the parent class which in your example is Object. 8/6/2008 10:57 AM | ssahloe

 re: 30 Seconds to a Fluent Interface

What's wrong with this?

var person = new Customer() { Name = "Larry", Age = 30 }; 8/6/2008 11:56 AM | Andrew

# re: 30 Seconds to a Fluent Interface

I'd strongly advise against fluent builders for filling properties in. C# has object initializers for just this purpose:

new Customer()
{
Name = "Larry",
Age = 30
}

I've written about using fluent builders for setting up object graphs for testing purposes, and I do recommend doing that:

http://blog.eleutian.com/2007/09/29/FluentFixtures.aspx

Be sure to look at the use of operator implicit to do with the ugly Build() method.

And Damien, hack or not, returning this is the only way to do it in C# at the moment. .. would be great, but we don't have it yet.

8/6/2008 8:10 PM | Aaron Jensen

# re: 30 Seconds to a Fluent Interface

@Aaron and Andrew,

Thanks for the comments guys. You're completely correct, the object initializers are a much cleaner choice for this. I actually started doing this back in the 2.0 days so I hadn't even thought about what I could use in 3.0 to replace it. Taking advantage of the initializers is an excellent idea.

Also, Aaron, you're completely correct regarding the use of this for test data. I actually begin using this technique as a more flexible, and expressive, replacement for an object mother. For some reason I neglected to mention that in the post.

Thanks again for taking the time to leave comments!

Jeremy 8/6/2008 9:02 PM | Jeremy Jarrell

# re: 30 Seconds to a Fluent Interface

Aaron,

Thanks for the idea about the implicit operator, I've never even thought about doing that!

Jeremy 8/6/2008 9:06 PM | Jeremy

Post a comment





 

Please add 5 and 1 and type the answer here: