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://richarddingwall.name"), "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://richarddingwall.name"))
	.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!

June 1, 2009

5 Comments

John Varga on June 1, 2009 at 4:25 pm.

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.

Richard on June 1, 2009 at 4:32 pm.

@John whoops! Good spotting… fixed.

John Varga on June 1, 2009 at 5:08 pm.

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.

Ed Blackburn on June 3, 2009 at 11:15 pm.

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?

Richard on June 4, 2009 at 7:45 am.

@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.

Leave Your Comment

Your email will not be published or shared. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>