Skip to main content

C# - Creating a Fluent API [Beginner]



Introduction
Fluent interfaces are a fun and discoverable way to allow fellow developers to access functionality. If you've every used Linq's dot(.) notation, then you've used a fluent interface. Not only are fluent interfaces easy to use, but with the right knowledge they are also easy to create.

If you don't know what a fluent interface is, then let me show you through a simple example. This example allows you to calculate the miles per gallon for a vehicle given a few required values:
var mpg = new Car(make : "audi", model: "a4")
             .WithHorsePower(250)
             .WithFuel(gallons:10)
             .WithWeight(tons:3)
             .Mpg();
 
Compare the fluent approach with the traditional C# get/set pattern.
var car = new Car(make: "audi", model: "a4") {
    HorsePower = 250,
    Fuel = 10,
    Weight = 3
}

var mpg = car.Mpg();
 
Both approaches to this particular problem are perfectly fine. So why would you use a fluent interface over the traditional method?

In my humble opinion, I find that (good) fluent interfaces help dictate direction, and keep you from missing a crucial step in your setup. In the traditional approach what would stop us from calling the Mpg method before setting any of the other properties? The answer is nothing, and that can leave your developer in a state of confusion as to why their result is incorrect or throwing exceptions. 

I also believe that fluent interfaces do a better job of encapsulation. It would be very difficult for another developer or part of your application to modify values accidentally. This would be possible in the traditional approach, and not possible with the fluent interface.
if (car.Fuel = 30) // doh!
 
So let's break down our example and see what parts are important to a fluent interface.

Entry Point
 new Car(make : "audi", model:"a4") // entry point
 
Every fluent interface needs an entry point. A place where the developer must start in order to begin the chaining process. In our example, the entry point is just a simple constructor, but does not have to be: It could be a static method, a method, or property.

Chaining Methods
.WithHorsePower(250)
.WithFuel(gallons:10)
.WithWeight(tons:3)
 
Once you get passed the entry point, you are left with all the chaining methods. Chaining methods are capable of many things, but they are usually allow you to set properties. Nothing mind blowing here, but these methods are critical to setting the state you need for the executor.

Executor(s)
.Mpg(); // the executor
 
The executor is arguably the most important part of the fluent interface. It allows you to escape the chaining methods and finally return a result. Think of the executor method as the period on the end of a sentence. You are also not limited to one executor, you may have as many as makes sense to your API.

Now that I've broken down the different parts of the fluent interface, let's build it!

Show Me The Code!
How do we get to the interface we have above? let's start by knowing we need a Car class.
public class Car
{
    private readonly string _make;
    private readonly string _model;

    public Car(string make, string model)
    {
        _make = make;
        _model = model;
    }
}
 
So this helps us define the entry point. Our entry point in this case is the Car constructor. The next step is to build the chaining methods.
public class Car
{
    private readonly string _make;
    private readonly string _model;
    private int _bhp;
    private int _gallons;
    private int _tons;

    public Car(string make, string model)
    {
        _make = make;
        _model = model;
    }

    public Car WithHorsePower(int bhp)
    {
        _bhp = bhp;
        return this;
    }

    public Car WithFuel(int gallons)
    {
        _gallons = gallons;
        return this;
    }

    public Car WithWeight(int tons)
    {
        _tons = tons;
        return this;
    }
}
 
Here is the real magic. I am returning the Car itself after every method call. This allows you to chain to the next method. In this example, I am not constraining what methods you might want to call next, or the fact that you have to call any of them. If you want to constrain what the next call is, you can return another class / interface with one method (the next method). Note, calling the same method multiple times will just override the old value.

Finally, let's implement the executor. I've also taken the liberty to allow developers access to the values through readonly properties.
public class Car
{
    public int Gallons { get; private set; }
    public int Tons { get; private set; }
    public int Bhp { get; private set; }
    public string Make { get; private set; }
    public string Model { get; private set; }

    public Car(string make, string model)
    {
        Make = make;
        Model = model;
    }

    public Car WithHorsePower(int bhp)
    {
        Bhp = bhp;
        return this;
    }

    public Car WithFuel(int gallons)
    {
        Gallons = gallons;
        return this;
    }

    public Car WithWeight(int tons)
    {
        Tons = tons;
        return this;
    }

    public int Mpg()
    {
        // please don't use this for real mpg
        return Gallons/Math.Max(Tons, 1);
    }
}
 
It is important that the executor return something other than Car or else you will still be stuck in the chaining methods. Also note that readonly properties are also executors; calling any of them will not allow you to chain any more methods. This class is now fluent and ready to be used with the example from the introduction.

Conclusion
This pattern is very powerful and can be expanded once you realize what you need to do to facilitate it. It doesn't work in every situation but in those times where you would like to give guidance to other developers this approach gives you a great way to bake that guidance directly into your API.

Hope this helps you in better understanding the fluent interface approach and if you have any questions or if I could make anything clearer please don't hesistate to ask.

Links & Resources (Extra Credit)
Some fluent interface libraries that I use frequently. Looking at the code their can help you see advanced Fluent Interfaces.

Comments

Popular posts from this blog

C# Snippet - Shuffling a Dictionary [Beginner]

Randomizing something can be a daunting task, especially with all the algorithms out there. However, sometimes you just need to shuffle things up, in a simple, yet effective manner. Today we are going to take a quick look at an easy and simple way to randomize a dictionary, which is most likely something that you may be using in a complex application. The tricky thing about ordering dictionaries is that...well they are not ordered to begin with. Typically they are a chaotic collection of key/value pairs. There is no first element or last element, just elements. This is why it is a little tricky to randomize them. Before we get started, we need to build a quick dictionary. For this tutorial, we will be doing an extremely simple string/int dictionary, but rest assured the steps we take can be used for any kind of dictionary you can come up with, no matter what object types you use. Dictionary < String , int > origin = new Dictionary < string , int >();

C# Snippet - The Many Uses Of The Using Keyword [Beginner]

What is the first thing that pops into your mind when you think of the using keyword for C#? Probably those lines that always appear at the top of C# code files - the lines that import types from other namespaces into your code. But while that is the most common use of the using keyword, it is not the only one. Today we are going to take a look at the different uses of the using keyword and what they are useful for. The Using Directive There are two main categories of use for the using keyword - as a "Using Directive" and as a "Using Statement". The lines at the top of a C# file are directives, but that is not the only place they can go. They can also go inside of a namespace block, but they have to be before any other elements declared in the namespace (i.e., you can't add a using statement after a class declaration). Namespace Importing This is by far the most common use of the keyword - it is rare that you see a C# file that does not h

C# WPF Printing Part 2 - Pagination [Intermediate]

About two weeks ago, we had a tutorial here at SOTC on the basics of printing in WPF . It covered the standard stuff, like popping the print dialog, and what you needed to do to print visuals (both created in XAML and on the fly). But really, that's barely scratching the surface - any decent printing system in pretty much any application needs to be able to do a lot more than that. So today, we are going to take one more baby step forward into the world of printing - we are going to take a look at pagination. The main class that we will need to do pagination is the DocumentPaginator . I mentioned this class very briefly in the previous tutorial, but only in the context of the printing methods on PrintDialog , PrintVisual (which we focused on last time) and PrintDocument (which we will be focusing on today). This PrintDocument function takes a DocumentPaginator to print - and this is why we need to create one. Unfortunately, making a DocumentPaginator is not as easy as