Fluent Builder Pattern for classes with long-ish constructors

Last week I discovered a rather wonderful construct for objects with long constructors, e.g. immutable value types:

public class UserProfile
{
	public string City { get; protected set; }
	public string Country { get; protected set; }
	public Uri Url { get; protected set; }
	public string Email { get; protected set; }
	public string Tagline { get; protected set; }
	
	public UserProfile(string city, string country, Uri url, string email, 
		string tagline)
	{
		...
	}
}

This constructor has bad Connascence of Position (CoP); to construct a UserProfile instance, users have to know the position of each parameter. Otherwise they might mix up the city with the country for example:

// Spot the bug!
var profile = new UserProfile("NZ", "Wellington", 
	new Uri("http://rdingwall.com"), "rdingwall@gmail.com", ".NET guy"); 

This won’t be a problem with named parameters in C# 4.0, but until then, a nice alternative is a fluent builder class as described here:

UserProfile profile = new UserProfileBuilder()
	.WithCity("Wellington")
	.WithCountry("NZ")
	.WithUrl(new Uri("http://rdingwall.com"))
	.WithEmail("rdingwall@gmail.com")
	.WithTagline(".NET guy");

Builders are very easy to implement. Each With method records its value and returns the current builder instance. Then we provide an implicit cast operator that finally constructs a UserProfile with all the parameters in the right places.

public class UserProfileBuilder
{
	internal string City { get; set; }
	internal string Country { get; set; } 
	// ... etc
	
	public UserProfileBuilder WithCity(string city)
	{
		this.City = city;
		return this;
	}
	
	// ... etc
	
	public static implicit operator UserProfile(UserProfileBuilder builder)
	{
		return new UserProfile(builder.City, builder.Country, builder.Url, 
			builder.Email, builder.Tagline);
	}
}

I really like this!

6 thoughts on “Fluent Builder Pattern for classes with long-ish constructors

  1. Be aware that in your “With” example, the var will get confused and you will have a UserProfileBuilder instead of a UserProfile. You need to use an explicit type declaration.

  2. I only know this because I saw someone else post this pattern and I thought it was amazingly badass so I happened to remember that pitfall.

  3. You could still use var, if you have a:

    public UserProfile Build() member.

    Your public static implicit operator UserProfile member could implement Build() to keep it nice and DRY?

  4. @Ed: after a couple of weeks using this I’m inclined to agree. We’ve discovered the static operators aren’t much good for subclassed builders (e.g. AdminUserBuilder) because they cannot be inherited/overriden.

  5. At the first view this coding style looks cool.

    But it has the problem, that it doesn’t meet the requirements for clean code!

    An implict operator implementation must not throw an exception (see the Microsoft documentation). When constructors implement a validation of parameter values, they probably throw exceptions. Or imagine what happens when an object is instantiated and you forget to call the ‘WithCountry’ method. The country property has the default value.

    The code is compilable and executable, but it doesn’t work correctly, because you forgot to call the ‘WithCountry’ method. Finding this mistake could be a hard work.

    So this fluent object instantiation will result in very readable code, but it’s extremly prone to error.

Comments are closed.