Fluent interfaces – Builder Pattern, Intro (1/2)

The idea of fluent interfaces has been introduced by Martin Fowler (goo.gl/j4rdu) and Eric Evans – in short words you call one method after another. This way of implementation improves readibility, significantly – makes your code more human-readable than the usual method calls.

.NET framework uses this technique in many places – many of you think now about extension methods which can be chained one with another (about what I will post another time). Currently this seems to be the path for programming world.

The real-life applications enforces on programmers models which creation is very often quite awkward and difficult. Of course in day-to-day scenarios it is common to use builder pattern to help the new object creation process – the place where the object is needed does not have to care about the creation and (more importantly) about dependencies between other objects in the environment. Using builder pattern also helps with testing – there is possibility to change implementation of the builder to make just mock object instead of creation a real one.

The idea of builder pattern is quite easy to understand. What I would like to discuss is the fluent version of the builder – this will be covered in the next post.

Let’s start with a dummy version of the object the application is working on:

class BusinessObject
 {
   public Int32 Id { get; set; }
   public string Name { get; set; }
   public IEnumerable<BusinessObject> Children { get; set; }
 }

The first idea of a builder for such object is for example the BusinessObjectBuilder class.

class BusinessObjectBuilder
 {
    public BusinessObject Build(Int32 id, string name, IEnumerable<BusinessObject> children)
    {
       return new BusinessObject() {Id = id, Name = name, Children = children};
    }
 }

The disadvantages of such solution is trivial. Such scenario could be improved by the default parameters (introduced in the C# 4) – but it still would be not easily readable for a programmer. This would also be hard to refactor the code when the project of the process would change.

The second solution has less cons but it still is far from the ideal situation – where the code will speak for itself rather than the comment (which in plenty of times become outdated!).

class BusinessObjectBuilderSecond
 {
    private int _id;
    private string _name;
    private IEnumerable<BusinessObject> _children;
   public void SetName(string name)
    {
       this._name = name;
    }
// .....
   public BusinessObject Build()
    {
       return new BusinessObject() { Id = _id, Name = _name, Children = _children };
    }
 }

As seen in the code above – the situation is strictly different. In second version the program we could skip some parameters – for example the optional ones. But there is still one con- the one should use it in such way:

var builder = new BusinessObjectBuilderSecond();
 builder.SetName("name");
 // ...
 var obj = builder.Build();

It is clearer and nicer to use than the first version but it is still quite messy. But it makes the code of building an object easier to maintain – when the object will be updated, it is easier to add one method into builder without changing the usage of the builder in every place in the code. In the first scenario the programmer would have two paths – extend the method signature or add another Build method with some additional parameters so the builder class would have plenty of Build methods which is quite frustrating to get on your intelisense.

None of the presented solutions can resolve two main problems in business environment – domain model changes and easy readabilityof the code (which of course result in easier refactoring after changes in the business object). In the next post I will propose two solutions which can help to solve these issues.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s