Fluent interfaces are a way of making your code more readable. The NUnit 2.4+ assertion syntax is a good example of this, as is this example from Jon Galloway. For a really comprehensive example see Anders’ post*.
It is also very easy to get carried away with this (ok, maybe that’s just me) and misuse the technique by reducing it to simple method chaining and applying it everywhere. Ayende has a good post on the difference. To borrow Ayende’s example (I’ll give it back), this:
string user = new StringBuilder() .Append("Name: ") .Append(user.Name) .AppendLine() .Append("Email: ") .Append(user.Email) .AppendLine() .ToString();is not a fluent interface, and is does not offer much over the standard approach:
string user = new StringBuilder(); user.Append("Name: "); user.Append(user.Name); user.AppendLine(); user.Append("Email: "); user.Append(user.Email); user.AppendLine(); user.ToString();
The second example is hardly significantly more difficult to read than the first (a bit more noise), and has the added advantage of making debugging easier by giving you a specific line number if an exception is thrown. The first example is not a fluent interface, it is just method chaining.
The main feature of a fluent interface is not the use of method chaining (in fact this is completely optional), but mainly providing an easy to use, easy to understand interface to your class or library. A fluent interface over Ayende’s StringBuilder example might look more like this:
String user = new UserDisplayer() .AddName(user.Name) .AddEmail(user.Email) .ToString();
Image myImg = Bitmap.FromFile("cat.jpg"); Image transformedImage; ZRLabs.Yael.BasicFilters.TextWatermarkFilter watermark = new TextWatermarkFilter(); watermark.Caption = "Test"; watermark.AutomaticTextSize = true; transformedImage = watermark.ExecuteFilter(myImg); transformedImage.Save("cat_watermark.png", System.Drawing.Imaging.ImageFormat.Png);
ZRLabs.Yael.Pipeline pipeline = new ZRLabs.Yael.Pipeline("cat.jpg"); pipeline.Rotate(90) .Watermark("Monkey") .RoundCorners(100, Color.Bisque) .Save("test.png");
He used method chaining here, but the code is still an improvement without it:
ZRLabs.Yael.Pipeline pipeline = new ZRLabs.Yael.Pipeline("cat.jpg"); pipeline.Rotate(90); pipeline.Watermark("Monkey") pipeline.RoundCorners(100, Color.Bisque) pipeline.Save("test.png");
I recently wrote a fluent interface around sending commands to a database via a custom database controller class. To make it easier I added a number of methods for adding parameters to the command (yes, there are libraries to do this already, but this was to interface with existing code). I admittedly got a bit carried away with this and chained all the calls to have commands created in pseudo-natural language, at the cost of making debugging harder if an exception was thrown. The interface was pretty neat, but the method chaining was definitely overkill.
So the morale of the story is that fluent interfaces can be great, but method chaining is probably best left alone unless it makes a drastic improvement to code readability.
* I frequently link to my own posts that link to another post, rather than straight to the original source. The reason is Blogger gives me backlinks (which is Blogger’s substitute for trackbacks) that help me to navigate through my related posts.