var self = justin();

Software Developer Teammate

A place to remind my future self of what I've learned and experienced. That means both my successes and failures.


Simple Fluent API Example

The Goal - A Fluent API Example

Skip to the goods - here's the code on github.com

A few weeks ago, a buddy at work and I decided to try writing a fluent API to wrap an open source project. Since neither of us had written one before, we decided to quickly write a small example. Essentially, it was just a throw away library just to demonstrate one way of constructing a fluent API.

So, for our first stab at this, we decided to build a car object. The car class is very simple.

public class Car  
{
    public Car(Engine engine, int doors, string make, string model, int year)
    {
        Engine = engine;
        Doors = doors;
        Make = make;
        Model = model;
        Year = year;
    }

    public Engine Engine { get; private set; }
    public int Doors { get; private set; }
    public string Make { get; private set; }
    public string Model { get; private set; }
    public int Year { get; private set; }
}

A car has an engine that is configurable, so we needed an engine class.

public class Engine  
{
    public Engine(int cylinders, int horsePower, bool hasTurbo)
    {
        Cylinders = cylinders;
        HorsePower = horsePower;
        HasTurbo = hasTurbo;
    }

    public int Cylinders { get; private set; }
    public int HorsePower { get; private set; }
    public bool HasTurbo { get; private set; }
}

Since our goal was to focus on the fluent-y-ness (??) of the API, we stepped away from the keyboard and started writing things on the white board. About 10 minutes later, we came up with this syntax:

Car.HasDoors(4).IsMake("Subaru").IsModel("Impreza")

It's not the best fluent API we'd seen, but it seemed to be functional and was a good goal for us. Once we started coding, we focused first on the Car.

public class CarBuilder  
{
    private string Make;
    private string Model;
    private int Doors;
    private int Year;

    public CarBuilder WithDoors(int doors)
    {
        Doors = doors;
        return this;
    }

    public CarBuilder MakeIs(string make)
    {
        Make = make;
        return this;
    }

    public CarBuilder ModelIs(string model)
    {
        Model = model;
        return this;
    }

    public CarBuilder YearIs(int year)
    {
        Year = year;
        return this;
    }

    public Car Build()
    {
        return new Car(Doors, Make, Model, Year);
    }
}

So far this is just the Builder Pattern that returns a reference to itself after each method. Retuning 'this' is obviously the key piece in a fluent API.

This allow for this: var car = new CarBuilder().WithDoors(4).IsMake("Subaru").IsModel("WRX").Build();

That's not a bad stab at it. The only thing we didn't like was having the Build()  boilerplate method at the end.

Implicit Cast, The Slightly Less Known Sauce

So, to get around having to call Build()  when we were finished, we add an implicit conversion between CarBuilder and Car

public static implicit operator Car(CarBuilder builder)  
{
    return new Car(builder.Doors, builder.Make, builder.Model, builder.Year);
}

This fixes the Build method problem because now we implicitly cast to a car. The only thing here is that it forces you to explicitly declare your car type instead of using var otherwise the compiler wouldn't know you wanted a Car instead of a CarBuilder:

Car car = new CarBuilder().WithDoors(4).IsMake("Subaru").IsModel("WRX");

Not bad! I can live with that trade off if it means getting rid of a boiler plate method call at the end. And taking this approach to an engine builder, we got this:

public class EngineBuilder  
{
    private int Cylinders;
    private int HorsePower;
    private bool HasTurbo;

    public EngineBuilder WithCylinders(int cylinders)
    {
        Cylinders = cylinders;
        return this;
    }

    public EngineBuilder WithHorsePower(int hp)
    {
        HorsePower = hp;
        return this;
    }

    public EngineBuilder WithTurbo()
    {
        HasTurbo = true;
        return this;
    }

    public static implicit operator Engine(EngineBuilder builder)
    {
        return new Engine(builder.Cylinders, builder.HorsePower, builder.HasTurbo);
    }
}

Now all that's left is to add an EngineBuilder to the CarBuilder and add an Engine to the Car.

public class CarBuilder  
{
//snip
    public EngineBuilder HasEngine()
    {
        this.engineBuilder = new EngineBuilder();
        return engineBuilder;
    }
//snip
}
public class Car  
{
    public Car(Engine engine, int doors, string make, string model, int year)
    {
        Engine = engine;
        Doors = doors;
        Make = make;
        Model = model;
        Year = year;
    }

    public Engine Engine { get; private set; }
    //snip
}

Lastly, we need to update the implicit operator to create a car with the updated constructor.

public static implicit operator Car(CarBuilder builder)  
{
    return new Car(builder.engineBuilder, builder.Doors, builder.Make, builder.Model, builder.Year);
}

Ok, so quick run down. The CarBuilder has a HasEngine()  method that returns an EngineBuilder and once you cast the CarBuilder to a Car, the EngineBuilder also gets casts to an Engine when it is used in the Car constructor. Make sense?

So let's look at what this fluent API now gives us.

Car car = new CarBuilder().WithDoors(4).IsMake("Subaru").IsModel("Impreze").HasEngine().WithCylinders(4).WithHorsepower(200)

That looks pretty fluent! But we noticed a problem. Once you call HasEngine() , you are now only working with an EngineBuilder which forces you to only be able to call HasEngine()  after you have finished constructing the Car. You see? You can't get back to the CarBuilder when you have the EngineBuilder from the HasEngine()  method.

Ok, so clearly we need a reference in the EngineBuilder back to the CarBuilder, but how would this look in a fluent API? We needed some word that would denote a context switch visually. So we tried out And. Our idea is that And would be a pointer back to the original CarBuilder, allowing you to construct the Car and Engine in any order you wanted.

Now we just add a field to the EngineBuilder, update the EngineBuilder constructor, add an And property, and then update the CarBuilder to pass in a reference to itself when it creates a new EngineBuilder.

public class EngineBuilder  
{
    //snip
    private readonly CarBuilder parent;

    public EngineBuilder(CarBuilder parent)
    {
        this.parent = parent;
    }

    //snip
    public CarBuilder And { get { return parent; } }
}

public class CarBuilder  
{
    //snip
    public EngineBuilder HasEngine()
    {
        this.engineBuilder = new EngineBuilder(this);
        return engineBuilder;
    }
    //snip
}

Putting all of that together gave us this:

Car car = new CarBuilder().HasEngine().WithCylinders(4).WithHorsePower(200).And.WithDoors(4).IsMake("Subaru").IsModel("Impreza")

I'm sure this could be better, but this was a good example of a fluent API.

Reusability?

Then we thought "what happens if we want to build a motorcycle?" In this case, we would need a different MotorCycleBuilder because motorcycles don't have doors... but we would also need a new type of EngineBuilder that could point back to a MotorcycleBuilder instead of a CarBuilder... So we decided to refactor the EngineBuilder and introduce generics.

public class EngineBuilder<T>  
{
    private int Cylinders;
    private int HorsePower;
    private bool HasTurbo;

    private readonly T parent;

    public EngineBuilder(T parent)
    {
        this.parent = parent;
    }

    public EngineBuilder<T> WithCylinders(int cylinders)
    {
        Cylinders = cylinders;
        return this;
    }

    public EngineBuilder<T> WithHorsePower(int hp)
    {
        HorsePower = hp;
        return this;
    }

    public EngineBuilder<T> WithTurbo()
    {
        HasTurbo = true;
        return this;
    }

    public T And { get { return parent; } }

    public static implicit operator Engine(EngineBuilder<T> builder)
    {
        return new Engine(builder.Cylinders, builder.HorsePower, builder.HasTurbo);
    }
}

Then modify the CarBuilder's HasEngine()  method and you get this:

public EngineBuilder<CarBuilder> HasEngine()  
{
    this.engineBuilder = new EngineBuilder<CarBuilder>(this);
    return engineBuilder;
}

Then once we wrote the MotorCycleBuilder, its HasEngine()  looked like this:

public EngineBuilder<MotorCycleBuilder> HasEngine()  
{
    this.engine = new EngineBuilder<MotorCycleBuilder>(this);
    return engine;
}

And voila! Now we have a simple fluent API with reuseable components!

comments powered by Disqus