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 06, 2006 1:17 AM by Jon Galloway

Comments

# re: A simple example of a fluent interface

I have a client looking for a full-time permanent employee with at least 1 year of C# development experience, they also use asp.net, vb, vb scripts, etc. The critical need is the C#. The company is near Oak Brook, IL. They are a Billion $ company.

Any suggestions on where/how to find these developers

I can be reached at jim@trisrecruiters.com

Wednesday, December 06, 2006 10:53 AM by Jim Shemroske

# 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 06, 2006 12:13 PM by Ryan Anderson

# re: A simple example of a fluent interface

> Pattern findGamesPattern

You gotta be kidding me.

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

# re: A simple example of a fluent interface

@Jeff - No, I am not kidding you. Read the whole post - he shows a simple example of a social security number validator, then a more complex regex which allows you to scrape game information from ESPN.

Wednesday, December 06, 2006 12:47 PM by Jon Galloway

# 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 06, 2006 4:00 PM by Jon Galloway

# re: A simple example of a fluent interface

I could have incorporated this pattern into the helper class I put together for some recent PDF generation work.  Here, objects such as images and text were being "applied" to my main object which was the document.  I think this pattern could have worked great. If only you posted this last week.  It's good stuff. Thanks.

Wednesday, December 06, 2006 7:17 PM by Ben Griswold

# 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 06, 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 07, 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 07, 2006 11:13 AM by Haacked

# re: A simple example of a fluent interface

I don't like these incredibly long or "fluent" lines of code much, for one reason: debugging. If I get a NullReferenceException in the line with the Regex syntax, well good luck debugging that...

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...

Thursday, December 07, 2006 3:43 PM by chris

# 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 08, 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

# the &#8216;bee log / Ordered Fluency

Pingback from  the &#8216;bee log  / Ordered Fluency

Thursday, July 12, 2007 4:09 PM by the ‘bee log / Ordered Fluency

# re: A simple example of a fluent interface

I wrote a article showing some "quick example" code illustrating how to build a Fluent Interface in C#:

blog.troyd.net/PermaLink,guid,5cdd4862-857a-488d-a577-c6d21b548f19.aspx

Thanks,

Troy

Wednesday, August 22, 2007 3:43 PM by Troy DeMonbreun

# Interfaces fluidas en NHibernate at Espacio de Dario Quintana

Pingback from  Interfaces fluidas en NHibernate at Espacio de Dario Quintana

# Fluent Interfaces on NHibernate at Dario Quintana

Pingback from  Fluent Interfaces on NHibernate at Dario Quintana

Monday, November 12, 2007 12:04 AM by Fluent Interfaces on NHibernate at Dario Quintana

# 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 05, 2007 1:55 AM by portrait artist

# re: A simple example of a fluent interface

nice peice i linked it in my peice on fluid interfaces

neildmartin.spaces.live.com/.../cns!7E48D388265D63E1!468.entry

Wednesday, December 05, 2007 5:29 AM by Neil Martin

# Java - Return Instance from Set Method | twit88.com

Pingback from  Java - Return Instance from Set Method | twit88.com

Wednesday, December 19, 2007 11:35 PM by Java - Return Instance from Set Method | twit88.com

# Misusing fluent interfaces

Fluent interfaces are a way of making your code more readable. The NUnit 2.4+ assertion syntax is a good

Friday, February 01, 2008 5:24 AM by dave^2=-1

# re: A simple example of a fluent interface

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

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

Leave a Comment

(required) 
(required) 
(optional)
(required)