Method Chaining – Reuse Object or Create New One

coding-stylemethod-chainingreadability

When using method chaining like:

var car = new Car().OfBrand(Brand.Ford).OfModel(12345).PaintedIn(Color.Silver).Create();

there may be two approaches:

  • Reuse the same object, like this:

    public Car PaintedIn(Color color)
    {
        this.Color = color;
        return this;
    }
    
  • Create a new object of type Car at every step, like this:

    public Car PaintedIn(Color color)
    {
        var car = new Car(this); // Clone the current object.
        car.Color = color; // Assign the values to the clone, not the original object.
        return car;
    }
    

Is the first one wrong or it's rather a personal choice of the developer?


I believe that he first approach may quickly cause the intuitive/misleading code. Example:

// Create a car with neither color, nor model.
var mercedes = new Car().OfBrand(Brand.MercedesBenz).PaintedIn(NeutralColor);

// Create several cars based on the neutral car.
var yellowCar = mercedes.PaintedIn(Color.Yellow).Create();
var specificModel = mercedes.OfModel(99).Create();

// Would `specificModel` car be yellow or of neutral color? How would you guess that if
// `yellowCar` were in a separate method called somewhere else in code?

Any thoughts?

Best Answer

I'd put the fluent api to it's own "builder" class seperate from the object it is creating. That way, if the client doesn't want to use the fluent api you can still use it manually and it doesn't pollute the domain object (adhering to single responsibility principle). In this case the following would be created:

  • Car which is the domain object
  • CarBuilder which holds the fluent API

The usage would be like this:

var car = CarBuilder.BuildCar()
    .OfBrand(Brand.Ford)
    .OfModel(12345)
    .PaintedIn(Color.Silver)
    .Build();

The CarBuilder class would look like this (I'm using C# naming convention here):

public class CarBuilder {

    private Car _car;

    /// Constructor
    public CarBuilder() {
        _car = new Car();
        SetDefaults();
    }

    private void SetDefaults() {
        this.OfBrand(Brand.Ford);
          // you can continue the chaining for 
          // other default values
    }

    /// Starts an instance of the car builder to 
    /// build a new car with default values.
    public static CarBuilder BuildCar() {
        return new CarBuilder();
    }

    /// Sets the brand
    public CarBuilder OfBrand(Brand brand) {
        _car.SetBrand(brand);
        return this;
    }

    // continue with OfModel(...), PaintedIn(...), and so on...
    // that returns "this" to allow method chaining

    /// Returns the built car
    public Car Build() {
        return _car;
    }

}

Note that this class will not be thread safe (each thread will need it's own CarBuilder instance). Also note that, even though fluent api is a really cool concept, it probably is overkill for the purpose of creating simple domain objects.

This deal is more useful if you're creating an API for something much more abstract and has more complex set up and execution, which is why it works great in unit testing and DI frameworks. You can see some other examples under the Java section of the wikipedia Fluent Interface article with persistance, date handling and mock objects.


EDIT:

As noted from the comments; you could make the Builder class a static inner class (inside Car) and Car could be made immutable. This example of letting Car be immutable seems a bit silly; but in a more complex system, where you absolutely don't want to change the contents of the object that is built, you might want to do it.

Below is one example of how to do both the static inner class and how to handle an immutable object creation that it builts:

// the class that represents the immutable object
public class ImmutableWriter {

    // immutable variables
    private int _times; private string _write;

    // the "complex" constructor
    public ImmutableWriter(int times, string write) {
        _times = times;
        _write = write;
    }

    public void Perform() {
        for (int i = 0; i < _times; i++) Console.Write(_write + " ");
    }

    // static inner builder of the immutable object
    protected static class ImmutableWriterBuilder {

        // the variables needed to construct the immutable object
        private int _ii = 0; private string _is = String.Empty;

        public void Times(int i) { _ii = i; }

        public void Write(string s) { _is = s; }

        // The stuff is all built here
        public ImmutableWriter Build() {
            return new ImmutableWriter(_ii, _is);
        }

    }

    // factory method to get the builder
    public static ImmutableWriterBuilder GetBuilder() {
        return new ImmutableWriterBuilder();
    }
}

The usage would be the following:

var writer = ImmutableWriter
                .GetBuilder()
                .Write("peanut butter jelly time")
                .Times(2)
                .Build();

writer.Perform();
// console writes: peanut butter jelly time peanut butter jelly time 

Edit 2: Pete in the comments made a blog post about using builders with lambda functions in the context of writing unit tests with complex domain objects. It is an interesting alternative to make the builder a bit more expressive.

In the case of CarBuilder you need to have this method instead:

public static Car Build(Action<CarBuilder> buildAction = null) {
    var carBuilder = new CarBuilder();
    if (buildAction != null) buildAction(carBuilder);
    return carBuilder._car;
}

Which can be used as this:

Car c = CarBuilder
    .Build(car => 
        car.OfBrand(Brand.Ford)
           .OfModel(12345)
           .PaintedIn(Color.Silver);