Click here to Skip to main content
15,867,488 members
Articles / Fluent

Fluent interfaces and Method Chaining in C#

Rate me:
Please Sign up or sign in to vote.
4.93/5 (22 votes)
21 Aug 2013CPOL4 min read 119.7K   21   11
Humans are lazy and programmers are humans J . We like things which are simplified and clean. So if you see the evolution of programming, we initially started with functional programming, and evolved towards object oriented programming.So as functional programmers where we used to remember methods a
 
 

Humans are lazy and programmers are humans J . We like things which are simplified and clean. So if you see the evolution of programming, we initially started with functional programming, and evolved towards object oriented programming

So as functional programmers where we used to remember methods and function names like “Add”, “Subtract”, “Multiply” and “Divide”, in OOP we just need to remember class “Maths” and all functions just pop out when we create the object of the class.

But as object oriented programmers we need to remember there are two worlds in OOP, one who creates the class and second who consumes it by creating the object.

So by following good OOP principles like abstraction, encapsulation etc developer writes the below “Customer” class so that other developers who consume this class should not feel it complicated.

public class Customer
    {
        private string _FullName;
        public string FullName
        {
            get { return _FullName; }
            set { _FullName = value; }
        }
        private DateTime _Dob;
        public DateTime Dob
        {
            get { return _Dob; }
            set { _Dob = value; }
        }
        private string _Address;
        public string Address
        {
            get { return _Address; }
            set { _Address = value; }
        }
  
    } 

Now the consumer who want to consume our “Customer” class will create the customer object , set properties and invoke methods. Below is the sample code for the same.

Customer customer = new Customer();
customer.FullName = "Shiv";
customer.Dob = Convert.ToDateTime("1/1/2008");
customer.Address = "Mumbai"

Now let’s zoom on the above consumer code. Is it complicated?, probably not if you are C# developer or a object oriented programmer

But what if your consumer is a tester who really does understand c# and would like to have more simplified interfaces to invoke your customer class for UNIT testing purpose.

What if you are component seller and you would like to surprise your component consumers with simplified interfaces. You would like to stand different from your competitors.

Welcome to the concept of “Fluent interfaces”.

“Fluent interfaces simplify your object consumption  code by making your code more simple, readable and discoverable.” 

So if our component consumers can write object invocation code in simple English sentence like below , that would “ROCK” right.

customer.NameOfCustomer("Shiv")
                .Bornon("12/3/1075")
                .StaysAt("Mumbai"); 

So now the next thing how to we implement “Fluent” interfaces. That’s done by using “Method chaining”.

“Method chaining” is a common technique where each method returns an object and all these methods can be chained together to form a single statement.

So the above customer class we can wrap in another class (“CustomerFluent”) which will implement method chaining and expose chained methods in a simplified format.

So you can see in the below code methods “NameofCustomer” , “BornOn” accept input s and return backs “CustomerFluent” class.

public  class CustomerFluent
    {
        private Customer obj = new Customer();
        public CustomerFluent NameOfCustomer(string Name)
        {
            obj.FullName = Name;
            return this;
        }
        public CustomerFluent Bornon(string Dob)
        {
            obj.Dob = Convert.ToDateTime(Dob);
            return this;
        }
        public void StaysAt(string Address)
        {
            obj.Address = Address;
           
        }
    } 

Now your client code is simple, nice and FLUENT as in the below code.

customer.NameOfCustomer("Shiv")
                .Bornon("12/3/1075")
                .StaysAt("Mumbai"); 

I have seen four visible uses of fluent interfaces:-

LINQ Queries

var x = context.Users.Select(u => new { u.Id, u.Name }); 

Unit testing

Assert.AreEqual(obj.Expected,obj1.Actual); 

Mock testing 

Container.GetMock()
                  .Setup(s => s.Save(new Person()))
                  .Returns(true)
                  .Verifiable(); 

DSL (Domain specific language) 

DSL is a language for simple users who do not understand programming. So they can type something in simple English as shown below. This will be parsed and checked for syntaxes. Later this sentence can be mapped to a internal fluent interface statement.

task "warn if website is not alive":
      every 1.Hour
      starting now
      when WebSite("http://www.questpond.com ").IsAlive is false
      then:notify "admin@example.org", "site down!" 

Below is the code of the Fluent interface statement to which the above DSL can map.

new FluentTask("alert if site is down")
      .Every( TimeSpan.FromMinutes(3) )
      .StartingFrom( DateTime.Now )
      .When(delegate
      {
            return WebSite("http://www.questpond.com").IsAlive == false;
      })
      .Execute(delegate
      {
            Notify("admin@example.org", "site down!");
      }); 

Are Fluent interfaces always good?

If you are creating fluent interfaces for developers then probably you are wasting time. Developers are consistent with creating objects with the new keyword and setting properties. Even if you create something simple for them they are consistent with certain consuming methodology and you will find you are adding more complexity than simplifying it.

Second thing we need to understand that we need to write more amount of code to create fluent interfaces. As you saw in the previous code I created a separate class for making interfaces simplified.

There are very few instances when you need fluent interfaces, below are few of them:-

 
  • During UNIT testing when the developers are not full fledged programmers.
  • You want your code to be readable by non-programmers so that they can understand if the code is satisfies their domain logic.
  • You are component seller and you want to stand out in the market as compared to the others by making your interfaces simpler.
  • You are creating a DSL language and this language is mapped with fluent interface statements.    

For Further reading do watch  the below interview preparation videos and step by step video series.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect https://www.questpond.com
India India

Comments and Discussions

 
PraiseThanks Pin
Erion Pici6-Sep-18 1:46
Erion Pici6-Sep-18 1:46 
SuggestionFluent guidelines Pin
zameb7-Jul-17 3:49
zameb7-Jul-17 3:49 
QuestionShould methods be called in a particular order? Pin
Jyotendra925-Oct-16 18:59
Jyotendra925-Oct-16 18:59 
GeneralMy vote of 1 Pin
mishrsud3-Nov-15 16:47
professionalmishrsud3-Nov-15 16:47 
BugHow is your FluentCustomer class instantiated? Pin
BloodBaz26-May-15 1:08
BloodBaz26-May-15 1:08 
SuggestionAddition to the Fluent class Pin
maxspan26-Sep-14 14:06
maxspan26-Sep-14 14:06 
QuestionFluent - Sounds a bit like With Pin
Member 86075914-Apr-14 6:21
Member 86075914-Apr-14 6:21 
AnswerRe: Fluent - Sounds a bit like With Pin
mishrsud3-Nov-15 16:45
professionalmishrsud3-Nov-15 16:45 
GeneralNice one Pin
Sau00230-Jan-14 2:19
Sau00230-Jan-14 2:19 
QuestionMy vote of 5 Pin
JohannQ12-Dec-13 2:11
JohannQ12-Dec-13 2:11 
GeneralMy vote of 5 Pin
Nikhil_S21-Aug-13 22:16
professionalNikhil_S21-Aug-13 22:16 
Good article as always.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.