Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fluent Interfaces - Method Chaining

Method chaining is the only way I know to build fluent interfaces.

Here's an example in C#:

John john = new JohnBuilder()     .AddSmartCode("c#")     .WithfluentInterface("Please")     .ButHow("Dunno");  Assert.IsNotNull(john);    [Test]     public void Should_Assign_Due_Date_With_7DayTermsVia_Invoice_Builder()     {         DateTime now = DateTime.Now;          IInvoice invoice = new InvoiceBuilder()             .IssuedOn(now)             .WithInvoiceNumber(40)             .WithPaymentTerms(PaymentTerms.SevenDays)             .Generate();          Assert.IsTrue(invoice.DateDue == now.AddDays(7));     } 

So how do others create fluent interfaces. How do you create it? What language/platform/technology is needed?

like image 913
solrevdev Avatar asked Nov 16 '08 02:11

solrevdev


People also ask

What is method chaining in C#?

Method chaining is a technique in which methods are called on a sequence to form a chain and each of these methods return an instance of a class. These methods can then be chained together so that they form a single statement. A fluent interface is an object-oriented API that depends largely on method chaining.

How does fluent user interface work?

The Fluent interface makes it easier to find powerful features by replacing menus and toolbars with a Ribbon that organizes and presents capabilities in a way that corresponds more directly to how people work.

Is fluent API good?

Fluent interface, first coined as a term by Martin Fowler, is a very convenient way of communicating with objects in OOP. It makes their facades easier to use and understand. However, it ruins their internal design, making them more difficult to maintain.

What is chaining in programming?

Method chaining, also known as named parameter idiom, is a common syntax for invoking multiple method calls in object-oriented programming languages. Each method returns an object, allowing the calls to be chained together in a single statement without requiring variables to store the intermediate results.


2 Answers

The core idea behind building a fluent interface is one of readability - someone reading the code should be able to understand what is being achieved without having to dig into the implementation to clarify details.

In modern OO languages such as C#, VB.NET and Java, method chaining is one way that this is achieved, but it's not the only technique - two others are factory classes and named parameters.

Note also that these techniques are not mutually exclusive - the goal is to maximize readabilty of the code, not purity of approach.

Method Chaining

The key insight behind method chaining is to never have a method that returns void, but to always return some object, or more often, some interface, that allows for further calls to be made.

You don't need to necessarily return the same object on which the method was called - that is, you don't always need to "return this;".

One useful design technique is to create an inner class - I always suffix these with "Expression" - that exposes the fluent API, allowing for configuration of another class.

This has two advantages - it keeps the fluent API in one place, isolated from the main functionality of the class, and (because it's an inner class) it can tinker with the innards of the main class in ways that other classes cannot.

You may want to use a series of interfaces, to control which methods are available to the developer at a given point in time.

Factory Classes

Sometimes you want to build up a series of related objects - examples include the NHibernate Criteria API, Rhino.Mocks expectation constraints and NUnit 2.4's new syntax.

In both of these cases, you have the actual objects you are storing, but to make them easier to create there are factory classes providing static methods to manufacture the instances you require.

For example, in NUnit 2.4 you can write:

Assert.That( result, Is.EqualTo(4)); 

The "Is" class is a static class full of factory methods that create constraints for evaluation by NUnit.

In fact, to allow for rounding errors and other imprecision of floating point numbers, you can specify a precision for the test:

Assert.That( result, Is.EqualTo(4.0).Within(0.01)); 

(Advance apologies - my syntax may be off.)

Named Parameters

In languages that support them (including Smalltalk, and C# 4.0) named parameters provide a way to include additional "syntax" in a method call, improving readability.

Consider a hypothetical Save() method that takes a file name, and permissions to apply to the file after saving:

myDocument.Save("sampleFile.txt", FilePermissions.ReadOnly); 

with named parameters, this method could look like this:

myDocument.Save(file:"SampleFile.txt", permissions:FilePermissions.ReadOnly); 

or, more fluently:

myDocument.Save(toFile:"SampleFile.txt", withPermissions:FilePermissions.ReadOnly); 
like image 83
Bevan Avatar answered Sep 20 '22 09:09

Bevan


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"); 
like image 41
Chris Pietschmann Avatar answered Sep 21 '22 09:09

Chris Pietschmann