What's a Fluent Interface

What is the difference between a fluent interface and the Builder pattern?

The idea behind a Fluent interface is that one can apply multiple properties to an object by connecting them with dots, without having to respecify the object each time. The idea behind the builder pattern is that unshared mutable objects are often easier to work with than unshared immutable ones, but it's much easier to reason about shared immutable objects than shared mutable ones. Thus, code can use an an easy-to-work-with mutable object to produce a "model" of a desired instance, and then use that to make an easy-to-share immutable object that holds the same data.

The two ideas can work well together, but are somewhat orthogonal.

Note that there are at least three ways a fluent interface can work:

  • By having each member of an instance return a new instance with the appropriate change applied.
  • By having each member mutate the instance upon which it is invoked and return that.
  • By having each member return an instance of a lightweight patch object which holds a link to either the thing being modified or the previous patch.

The last style requires that some action be taken to apply all the patches, but if the object being modified is large and many changes are necessary, it can minimize the amount of copying that's required.

What's a fluent interface?

It benefits the coder by reducing the amount he has to type (and read).

To use the C++ example on Wikipedia:

Before:

int main(int argc, char **argv) {
GlutApp app(argc, argv);
app.setDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_ALPHA|GLUT_DEPTH); // Set framebuffer params
app.setWindowSize(500, 500); // Set window params
app.setWindowPosition(200, 200);
app.setTitle("My OpenGL/GLUT App");
app.create();
}

After:

 int main(int argc, char **argv) {
FluentGlutApp app(argc, argv);
app.withDoubleBuffer().withRGBA().withAlpha().withDepth()
.at(200, 200).across(500, 500)
.named("My OpenGL/GLUT App");
app.create();
}

Fluent Interface vs Builder Pattern: Advantages and Disadvantages

Builders basically always use a fluent interface. It isn't a case where you'd choose one or the other. The builder pattern is a type of object that typically uses a fluent interface. A fluent interface doesn't do anything by itself. It's just a popular way to write certain kinds of objects.

A fluent interface is when you have an object that returns itself, or something like itself. (I say like itself because it doesn't technically have to be itself, for example in the case of a step builder.) When you have someObject.doA().doB().doC() that's a fluent interface. Java Stream is also an example of using a fluent interface. (Although, technically the Stream object that you interact with is really a kind of builder. The stream only executes when you call a terminal operation like forEach. Everything before that was basically a builder and the terminal operation is analogous to a build() method.)

There are also lots of examples on Wikipedia. https://en.wikipedia.org/wiki/Fluent_interface

Understanding of How to Create a Fluent Interface

One alternative could be to invoke all operations on Mpg() which will allow the other operations to be conditional.

This is already answered in SO with a code sample. Please refer to Conditional Builder Method Chaining Fluent Interface

The post indicates, instead of Interfaces, the same might be achieved using constructors, with a calling method that makes all others operations conditional.

What fluent interfaces have you made or seen in C# that were very valuable? What was so great about them?

Kudos for the method parameter validation, you've given me a new idea for our fluent APIs. I've hated our precondition checks anyways...

I've built a extensibility system for a new product in development, where you can fluently describe the commands available, the user interface elements and more. This runs on top of StructureMap and FluentNHibernate, which are nice APIs too.

MenuBarController mb;
// ...
mb.Add(Resources.FileMenu, x =>
{
x.Executes(CommandNames.File);
x.Menu
.AddButton(Resources.FileNewCommandImage, Resources.FileNew, Resources.FileNewTip, y => y.Executes(CommandNames.FileNew))
.AddButton(null, Resources.FileOpen, Resources.FileOpenTip, y =>
{
y.Executes(CommandNames.FileOpen);
y.Menu
.AddButton(Resources.FileOpenFileCommandImage, Resources.OpenFromFile, Resources.OpenFromFileTop, z => z.Executes(CommandNames.FileOpenFile))
.AddButton(Resources.FileOpenRecordCommandImage, Resources.OpenRecord, Resources.OpenRecordTip, z => z.Executes(CommandNames.FileOpenRecord));
})
.AddSeperator()
.AddButton(null, Resources.FileClose, Resources.FileCloseTip, y => y.Executes(CommandNames.FileClose))
.AddSeperator();
// ...
});

And you can configure all commands available like this:

Command(CommandNames.File)
.Is<DummyCommand>()
.AlwaysEnabled();

Command(CommandNames.FileNew)
.Bind(Shortcut.CtrlN)
.Is<FileNewCommand>()
.Enable(WorkspaceStatusProviderNames.DocumentFactoryRegistered);

Command(CommandNames.FileSave)
.Bind(Shortcut.CtrlS)
.Enable(WorkspaceStatusProviderNames.DocumentOpen)
.Is<FileSaveCommand>();

Command(CommandNames.FileSaveAs)
.Bind(Shortcut.CtrlShiftS)
.Enable(WorkspaceStatusProviderNames.DocumentOpen)
.Is<FileSaveAsCommand>();

Command(CommandNames.FileOpen)
.Is<FileOpenCommand>()
.Enable(WorkspaceStatusProviderNames.DocumentFactoryRegistered);

Command(CommandNames.FileOpenFile)
.Bind(Shortcut.CtrlO)
.Is<FileOpenFileCommand>()
.Enable(WorkspaceStatusProviderNames.DocumentFactoryRegistered);

Command(CommandNames.FileOpenRecord)
.Bind(Shortcut.CtrlShiftO)
.Is<FileOpenRecordCommand>()
.Enable(WorkspaceStatusProviderNames.DocumentFactoryRegistered);

Our view configure their controls for the standard edit menu commands using a service given to them by the workspace, where they just tell it to observe them:

Workspace
.Observe(control1)
.Observe(control2)

If the user tabs to the controls, the workspace automatically gets an appropriate adapter for the control and provides undo/redo and clipboard operations.

It has helped us reduce the setup code dramatically and make it even more readable.


I forgot to tell about a library we're using in our WinForms MVP model presenters to validate the views: FluentValidation. Really easy, really testable, really nice!

Fluent Interfaces - Method Chaining

You can create a fluent interface in any version of .NET or any other language that is Object Oriented. All you need to do is create an object whose methods always return the object itself.

For example in C#:

public class JohnBuilder
{
public JohnBuilder AddSmartCode(string s)
{
// do something
return this;
}

public JohnBuilder WithfluentInterface(string s)
{
// do something
return this;
}

public JohnBuilder ButHow(string s)
{
// do something
return this;
}
}

Usage:

John = new JohnBuilder()
.AddSmartCode("c#")
.WithfluentInterface("Please")
.ButHow("Dunno");

Tips for writing fluent interfaces in C# 3

On your 4th point;

Yes I think that a complex fluent interface can still be fluent.

I think fluent interfaces are somewhat of a compromise. (although a good one!) There has been much research into using natural language for programming and generally natural language isn't precise enough to express programs.

Fluent interfaces are constructed so that they write like a programming language, only a small subset of what you can express in a natural language is allowed, but they read like a natural language.

If you look at rhino mocks for example the writing part has been complicated compared to a normal library. I took me longer to learn mostly due to the fluent interface but it makes code a lot easier to read. Because programs are usually written once and read a lot more than once this is a good tradeoff.

So to qualify my point a bit. A fluent interface that's complex to write but easy to read can still be fluent.

What's the point of DSLs / fluent interfaces

2 - Is this fluent interface approach
just a replacement for the non
existing named method parameters in
C#? Would named parameters make fluent
interfaces obsolete, e.g. something
similar objective-C offers:

Well yes and no. The fluent interface gives you a larger amount of flexibility. Something that could not be achieved with named params is:

sizer.FromImage(i)
.ReduceByPercent(x)
.Pixalize()
.ReduceByPercent(x)
.OutputImageFormat(ImageFormat.Jpeg)
.ToLocation(o)
.Save();

The FromImage, ToLocation and OutputImageFormat in the fluid interface, smell a bit to me. Instead I would have done something along these lines, which I think is much clearer.

 new Sizer("bob.jpeg") 
.ReduceByPercent(x)
.Pixalize()
.ReduceByPercent(x)
.Save("file.jpeg",ImageFormat.Jpeg);

Fluent interfaces have the same problems many programming techniques have, they can be misused, overused or underused. I think that when this technique is used effectively it can create a richer and more concise programming model. Even StringBuilder supports it.

var sb = new StringBuilder(); 
sb.AppendLine("Hello")
.AppendLine("World");


Related Topics



Leave a reply



Submit