Vagif Abilov's blog on .NET

Fluent object construction

I like an idea to replace constructor overloads that take optional parameters with more fluent approach, so there will be less (and easier for understanding) constructor overloads and more readable code. Perhaps also more writeable.

Let’s take an example, well-known StreamWriter. It has the following constructors:

public StreamWriter(Stream stream);
public StreamWriter(string path);
public StreamWriter(Stream stream, Encoding encoding);
public StreamWriter(string path, bool append);
public StreamWriter(Stream stream, Encoding encoding, int bufferSize);
public StreamWriter(string path, bool append, Encoding encoding);
public StreamWriter(string path, bool append, Encoding encoding, int bufferSize);

Stream and path parameters are mutually exclusive and one of them must be sent to a constructor, other parameters (encoding, append and bufferSize) are optional, and append flag can only be used together with the path. There are in total 8 constructor overloads, and they don’t cover all possible valid combination: there is no overload that only takes path, encoding and bufferSize (you will have to send append flag too).

What if this class had fewer constructors but provided additional methods to enrich stream writer setup? Like this:

public class FluentStreamWriter
{
    public Encoding Encoding { get; private set; }
    public int BufferSize { get; private set; }

    public FluentStreamWriter(Stream stream) { }
    public FluentStreamWriter(string path) { }
    public FluentStreamWriter(string path, bool append) { }

    public FluentStreamWriter With(Encoding encoding, int bufferSize) { this.Encoding = encoding; this.BufferSize = bufferSize; return this; }
    public FluentStreamWriter WithEncoding(Encoding encoding) { this.Encoding = encoding; return this; }
    public FluentStreamWriter WithBufferSize(int bufferSize) { this.BufferSize = bufferSize; return this; }
}

And the code using classic and fluently constructed stream writer would look like this:

var writer1 = new StreamWriter("temp.txt", false, Encoding.UTF8);
var writer2 = new StreamWriter("temp.txt", true, Encoding.UTF8, 1000);

var writer3 = new FluentStreamWriter("temp.txt").With(Encoding.UTF8, 1000);
var writer4 = new FluentStreamWriter("temp.txt").WithEncoding(Encoding.UTF8);
var writer5 = new FluentStreamWriter("temp.txt").WithEncoding(Encoding.UTF8).WithBufferSize(1000);

What I like in this approach is the separation between mandatory and optional set of constuctor arguments: what is sent to the constructor is mandatory (either individual parameters or set of mutually exclusive parameters). Everything that is optional may be added using methods prefixed with “With” that return the same class instance.

The drawback of this approach is that since it moves some object construction options to custom methods, they can be overlooked by developers that are not aware of API style and may conclude that object construction possibilities are limited by the list of constructor overloads. So perhaps this approach is not suitable for a small API where fluent construction will be the only deviation from traditional type design style. But in large frameworks with fluent API style it can feel natural and be easily accepted.

Comments

Pavel said:

Вот тут разбирают более сложный случай, достаточно интересно qedcode.com/.../socket

# February 17, 2010 7:04 PM

Vagif Abilov said:

Спасибо! Very interesting.

# February 17, 2010 7:35 PM

SamLazy said:

So, what is the advantage compare to initializing properties?

# February 18, 2010 3:42 AM

Vagif Abilov said:

SamLazy,

Object construction and setting properties are two different things, because they happen during two different phases. Construction (and fluent construction) is something that occurs on object creation. After that the object essentials are set and it can be used. Settable properties can be modified at any time, so it makes sense to declare as properties only those settings that should be changeable during object lifetime.

# February 18, 2010 8:14 AM

SamLazy said:

тфу, блин! Не подумал в эту сторону.

Спасибо.

# February 18, 2010 9:57 PM

whiplash compensation claim said:

Falls on a construction site can happen at three different levels – on the ground when involved in manual handling of building materials, when working on scaffolding or ladders and when working on a roof.

# March 3, 2011 10:50 AM

Underfloor Heating Installing said:

WOW. Lot of good info. Thanks for sharing your knowledge.

# May 18, 2011 7:12 AM

shopfitting brisbane said:

that's amazing man..

# November 3, 2011 5:10 AM

pisos barcelona said:

It took me time to read all the tips, but I clearly loved the post. It proved to be very helpful to me and I’m certain to all of the commenters here!  

# January 26, 2012 9:44 AM

bizflats said:

# September 5, 2012 10:44 AM
Leave a Comment

(required) 

(required) 

(optional)

(required) 


Please add 3 and 6 and type the answer here: