A simple example of a fluent interface - Jon Galloway

A simple example of a fluent interface

 Roiy recently released a really nice c# image enhancement filters library on CodeProject. It includes a nice collection of easy to use image transformation filters - ResizeFilter, RotateFilter, ImageWatermarkFilter, etc. They follow a simple pattern:

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);

I recommended he implement a fluent interface to allow chaining filter operations together, like this:

static void Main(string[] args) { ZRLabs.Yael.Pipeline pipeline = new ZRLabs.Yael.Pipeline("cat.jpg"); pipeline.Rotate(90) .Watermark("Monkey") .RoundCorners(100, Color.Bisque) .Save("test.png"); }

That's easier than it might sound:

  1. I created a Pipeline class which holds a System.Drawing.Image object to maintiain the current image state
  2. I added a bunch of methods which accept parameters for filter properties a user would be likely to want to change (I could have added overrides to allow setting all filter properties if desired).
  3. Each method returns "this", meaning it returns a reference to itself. That's the magic that allows for the chained calls.

Here's a snip of the code:

public class Pipeline { private Image image; public Image CurrentImage { get { return image; } set { image = value; } } public Pipeline(string inputFilename) { image = Bitmap.FromFile(inputFilename); } public Pipeline Rotate(float Degrees) { RotateFilter filter = new RotateFilter(); filter.RotateDegrees = Degrees; image = filter.ExecuteFilter(image); return this; } public Pipeline BlackAndWhite() { BlackAndWhiteFilter filter = new BlackAndWhiteFilter(); image = filter.ExecuteFilter(image); return this; } public Pipeline Watermark(string caption) { TextWatermarkFilter filter = new TextWatermarkFilter(); filter.Caption = caption; filter.AutomaticTextSize = true; image = filter.ExecuteFilter(image); return this; } /* more filters here */ public void Save(string filename) { image.Save(filename); } }

Since each method returns a Pipeline object and the Pipeline exposes all the basic methods we'll need, we're all set to just keep calling methods until we're done.

What else could you do with a fluent interface?

Joshua Flanagan wrote a very nice regular expression wrapper which allows you to define a regex using a readable syntax, exposed via a very elegent fluent interface:

Pattern findGamesPattern = Pattern.With.Literal(@"<div") .WhiteSpace.Repeat.ZeroOrMore .Literal(@"class=""game""").WhiteSpace.Repeat.ZeroOrMore.Literal(@"id=""") .NamedGroup("gameId", Pattern.With.Digit.Repeat.OneOrMore) .Literal(@"-game""") .NamedGroup("content", Pattern.With.Anything.Repeat.Lazy.ZeroOrMore) .Literal(@"<!--gameStatus") .WhiteSpace.Repeat.ZeroOrMore.Literal("=").WhiteSpace.Repeat.ZeroOrMore .NamedGroup("gameState", Pattern.With.Digit.Repeat.OneOrMore) .Literal("-->");

As Joshua notes, Ayende's Rhino Mocks uses a fluent interface as well. Milan Negovan applied this approach to his Fluent Control Container, which simplifies the task of creating properly instantiating ASP.NET controls.

When would you apply a fluent interface? I think it makes sense when the routine use of your API requires multiple sequential method calls or property settings. I think a fluent interface makes a lot of sense on top of a richer API; simple use cases can use the fluent interface and stay simple, while complex use cases can call into the base API.

The whole definition of a fluent interface is a little vague, but as Martin Fowler says, "The more the use of the API has that language like flow, the more fluent it is."

Published Wednesday, December 6, 2006 1:17 AM by Jon Galloway

Comments

# re: A simple example of a fluent interface

If I am following correctly, Tom Crane also used a fluent interface in his WebImageMaker control, the IImageProvider interface, and implements it in the ImageProviderImpl class. This allows the control to process images seamlessly with minimal code in the actual Control itself with a simple method call passing a few critical pieces of information as parameters. I am very fond of Crane's control and have learned much from his code. I am on the same page with you on fluent interfaces and have used this type of pattern in a couple of controls that I have recently built with much success.

Nice post Galloway!

Wednesday, December 6, 2006 12:13 PM by Ryan Anderson

# re: A simple example of a fluent interface

> Pattern findGamesPattern

You gotta be kidding me.

Wednesday, December 6, 2006 12:40 PM by Jeff Atwood

# re: A simple example of a fluent interface

@Jim -

I highly recommend HiddenNetwork advertisements as a way to locate highly skilled, passionate developers. You can find out more from the link below, but here's a brief summary of why I recommend it:

* Top notch developers are using programming weblogs as a way to keep on top of the latest technologies and developments in their field

* HiddenNetwork places targeted advertisements on the weblogs your target developers read and trust (not just one weblog, but a selected list based on the skillset you're targeting).

* The HiddenNetwork system uses GeoLocation to show advertisements which are geographically relevant, so developers near Oak Brook, IL will see your ad.

* Candidates will reply directly to you, so you're not working through anyone who will want a referral bonus. You place a targeted ad and work directly with those who respond.

* Last and definitely least, I get a small referal payment if you place an ad with them using this link. I would absolutely recommend this service if I didn't get a penny, but I don't mind it. ;-)

Here's that link:

http://hiddennetwork.com/ref.ashx?1016

Wednesday, December 6, 2006 4:00 PM by Jon Galloway

# re: A simple example of a fluent interface

I've never heard this style called 'fluent' but it's nice to see the coverage here for .Net. The style is actually quite common in some (other language) libraries. I like the comparison to domain specific languages - in fact probably the best way to build a very clean fluent API is to think of it as production rules in a simple grammar.

Going one step further if you model your API using production rules then you could use the trusty GOF Design Pattern "Interpreter" to map out your object model. Combine that idea with operator overloading and you could truly have your own 'domain specific language'. For example:

((pipline.Rotate(90) + WaterMark("Monkey")) + RoundCorners & 100 & Color.Bisque) >> "test.png"

Once someone understands that some things are 'with'ed using + and parameterized with bitwise & it might be a very productive API, i.e. one that is easy to write and easy to read. One bonus to this approach would be that type checking for the operator overloading helps the programmer avoid incorrect syntax in the local 'grammar'. I guess you give up IntelliSense checking in this model but supporting IDE idioms has never been a primary design criteria for me :-)

Wednesday, December 6, 2006 9:23 PM by Micah Dylan

# re: A simple example of a fluent interface

It's interesting that Haskell monads support the kind of notation that Micah mentioned, kind of, but they also support (well, the language does), a 'do' notation, that looks a lot more like conventional imperative programming - and the tutorials quote the imperative look as being simpler.  The notation without do-notation is probably close to fluent code.

Have you tried mixing fluent interfaces with immutability, e.g., making pipeline.Rotate(90) return a new instance, rather than 'this'?

That way you can break at any stage of the chain of calls and pass the object returned to another method without worrying that it might be modified.

Good code reads like sentences - one statement should equate to one sentence describing its purpose.  Fluent interfaces seem interesting from that perspective, do they depend on mutability?

Thursday, December 7, 2006 6:58 AM by Ricky Clarkson

# re: A simple example of a fluent interface

Fluid interfaces do not depend on mutability, and I would argue that by making them immutable, the code is more clear in what it is doing.

Why should a method that changes the state of an object return that object?

Thursday, December 7, 2006 11:13 AM by Haacked

# re: A simple example of a fluent interface

"About the immutability: fine for some objects like strings, but you don't want to do that for images because you would allocate several images in this one line of code..."

Not necessarily true - you can just make a filter - e.g., if you rotate an image by 90 degrees you don't need to copy the image, just swap the x and y coordinates over whenever anyone asks for a pixel value.

Of course, copying it, or mutating it, will be faster in many cases.

Friday, December 8, 2006 9:28 AM by Ricky Clarkson

# re: A simple example of a fluent interface

well that's just groovy.

i bet we'll see more and more talk about this approach.

Sunday, December 10, 2006 7:17 AM by lb

# re: A simple example of a fluent interface

Doesnt it look similar to unix way of doing things (pipes) ?

OR

C++'s cout << "blah" << "blah blah" << endl;

Monday, December 11, 2006 5:13 AM by Kalpesh

# re: A simple example of a fluent interface

Another approach that has a bit of the same feel to it is chaining constructors. It is quite useful when you are building hierarchies instead of sequences. A good recent example is the XElement class in XLinq. Here you create an XML fragment by doing like new XElement("table", new XElement("tr", new XElement("td", new XAttribute("colspan", 2)))); The last parameter in the constructor is something like a "params object[] children" which get processed by type and added as childnodes. This beats setting properties and adding to the Controls collection by several meters.

Monday, December 11, 2006 2:31 PM by Bjørn Erik Haug

# re: A simple example of a fluent interface

@Kalpesh - It "looks" similar to pipes and standard output redirection, but it's a lot cleaner. Piping output is very fragile since there's no strong typing - everything is just handled by convention. A fluent interface allows this kind of simplicity by overlaying convenient access on a rich, strongly typed object model. Additionally, an object model with a piped interface can maintain state, whereas pipes generally pass simple information to compensate for their fragility.

Monday, December 11, 2006 5:01 PM by Jon Galloway

# re: A simple example of a fluent interface

       image.Rotate(90)

       image.Watermark("Monkey")

       image.RoundCorners(100, Color.Bisque)

       image.Save("test.png");

is much more readable than

       pipeline.Rotate(90)

           .Watermark("Monkey")

           .RoundCorners(100, Color.Bisque)

           .Save("test.png");

Wednesday, March 14, 2007 2:43 PM by James

# re: A simple example of a fluent interface

Smalltalk (the first (or second depending on how you count) real OO language (real OO, not like C#. Whatever, you probably will not (want to) understand. ;-))) had special syntax for this kind of thing for ages.

image rotate: 90;

     watermark: 'monkey';

     roundCorners: 100 colored: Color bisque;

     saveIn: 'test.png'.

A dot (.) ends a line in Smalltalk (it's like ; in C#). A semicolon tells you that this method should be called on the original object and not on the result of the previous method call.

So:

anObject xxx yyy zzz.

is:

anObject.xxx().yyy().zzz(); in C#

and:

anObject xxx; yyy; zzz.

is:

anObject.xxx();

anObject.yyy();

anObject.zzz();

in C#.

Wednesday, March 14, 2007 3:06 PM by Jules

# re: A simple example of a fluent interface

For that smalltalk solution to work you have to make the filters mutate the original image, which doesn't have a great deal to recommend it. Admittedly, that's what the original code does, but the interface doesn't require it.

My gut feeling is that, the interface is pretty decent, but it would probably be better to have each of those pipeline methods return a new FilterableImage (seems like a better name than Pipeline somehow). That way you can reuse an intermediate result multiple times. The current implementation means that once you've applied a transformation it's final.

Tuesday, March 20, 2007 5:07 PM by Piers Cawley

# re: A simple example of a fluent interface

I wanted to check the code but they look so small.  Of course, I can’t just copy and paste them.  Is there any way that I can view the codes in a more legible way?

Wednesday, December 5, 2007 1:55 AM by portrait artist

# re: A simple example of a fluent interface

i need some example fluent, please send me, thanks,  khosrowshirin@yahoo.com

Saturday, August 2, 2008 3:51 AM by ali khosrowshiri

# re: A simple example of a fluent interface

Is this method chaining or is this Fluent Interface...

Please explain

Thanks,

Yash

Saturday, October 31, 2009 3:44 PM by Yash

# re: A simple example of a fluent interface

jQuery is a good example of this in action.

$('.foo').hide().addClass('selected').show(250);

Each function returns the (possibly modified) collection, for use in the next part of the chain.

Monday, December 21, 2009 10:57 AM by bc