Click here to Skip to main content
15,886,012 members
Articles / Desktop Programming / WTL

Guidelines to Fluent Interface design in C# - Part 1

Rate me:
Please Sign up or sign in to vote.
4.33/5 (2 votes)
5 Aug 2010CPOL3 min read 25.2K   16  
History, the basic concepts of Fluent Interfaces and a small glossary of terms that I will use in this series of posts

Shortcut: http://tiny.cc/rpj99

The term Fluent Interface was coined by Eric Evans and Martin Fowler in Fowler’s bliki as a proposal to build more readable code in an object oriented API. It can be used with any object oriented language but in this series of posts, I will use only C# samples.

It’s based on the method chaining technique where the return of a method is an object that allows the call of another method making the code look like this:

C#
//C# Sample
subject.DoSomething().DoSomethingElse().Finalize();

This post was motivated by the fact that I did not find any guide or help to build a coherent Fluent interface. It was just the opposite I found several different approaches. After some thought, I've decided to write this one. This is not a definitive guide nor a set of rules but just a proposal to a set of best practices that would help to write a good fluent interface.

Let’s start defining some terms and concepts that I will use in this series:

  • Sentence: is the statement or sequence of methods that defines a operation. The above C# sample is a simple sentence.
  • Subject: is the object being manipulated by the sentence.
  • Sentence Starter: is the first element of a sentence. In C#, it can be:
    1. An object
    2. A method that returns a object or property, or
    3. A type with static methods that returns an instance object

      The choice of using one of the above depends on the scope you are.

  • Term: is a method or property that can be called from the subject at some point in the sentence. Terms can be:
    1. A Verb: A term that does something to the subject (sets a property, changes a value or even changes the current subject of the sentence.
    2. A Constraint: A term that limits the list of terms available next by changing the subject of the sentence.
    3. A Constraint Verb: A verb that also works as a constraint.
  • Sentence Finalizer: An element that does not allow the sentence to continue. Generally it is a method that returns a void.
    In a very strict approach, every sentence should end with a finalizer, but in practice that not true and the sentence can end in any point that we are satisfied with the state of the subject.

Readable Code X Natural Language Utopia

The initial objective of Fluent Interface was to create a more readable code. But some developers raise the flag of making it to make the code as close as possible to natural language. I consider that overcoding. Take the sentence:

Make a car that is yellow and uses gasoline.

We can write is as:

C#
MakeACar().That.Is("Yellow").And.Uses("Gasoline");

Or as:

C#
CreateCar().WithColor("Yellow").WithFuel("Gasoline");

Both approaches are valid. Both are easy to read, but I think the first one is harder to code. And this is a very simple sentence.
I think we always need to analyze the problem and the context extensively before coding a fluent interface identifying the possible subjects and verbs to avoid making it too complicated to code or too raw.

Chaining X Nesting

Since we are talking about methods, there is always the question about chaining or nesting then. Consider this:

Make a car that has an engine that consumes gasoline, 
has electronic ignition and max RPM of 4500 and paint it as yellow.

We can write is as:

C#
CreateCar().SetEngine()
           .WithFuel("Gasoline")
           .WithMaxRPM(4500)
           .WithEletronicIgnition
           .SetCar()
           .WithColor("Yellow");

Or as:

C#
CreateCar().SetEngineTo(CreateEngine().WithFuel("Gasoline")
                                    .WithEletronicIgnition
                                    .WithMaxRPM(4500))
           .WithColor("Yellow");

Again both approaches are valid and easy to read, but instead of only using the method chain, we use the nesting to clarify that at some point, we are talking about the Engine instead of the Car. By using this alternative, we avoid using two Verbs that change the subject (SetEngine and SetCar) and even define a clear scope for the internal subject (the Engine).

These are the initial considerations I'd like to mention. In the next post, I will talk about some techniques to code each part of the sentence with some samples. I will talk about the use of static methods, generics, delegates, builders, etc. I hope it helps.

License

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


Written By
Software Developer (Senior) Pronto Solutions
Brazil Brazil
André Vianna is a Software Engineer in Rio de Janeiro, Brasil.
He is PMP, MCP and have worked as Development Project Manager, Senior Software Developer and Consultant for more than 15 years.
He worked with several major companies in Brasil, EUA, Canada and Mexico.
He has been working with the cut edge .NET platform since 2001 and is a C# specialist.

Comments and Discussions

 
-- There are no messages in this forum --