Ayende @ Rahien

Hi!
My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:

ayende@ayende.com

+972 52-548-6969

, @ Q c

Posts: 5,953 | Comments: 44,410

filter by tags archive

Design patterns in the test of timeBuilder


The intent of the Builder design pattern is to separate the construction of a complex object from its representation. By doing so, the same construction process can create different representations.

More about this pattern.

The sample code that usually comes with this pattern is something like this:

   1: PizzaBuilder hawaiianPizzaBuilder = new HawaiianPizzaBuilder();
   2: Cook cook = new Cook();
   3: cook.SetPizzaBuilder(hawaiianPizzaBuilder);
   4: cook.ConstructPizza();
   5: // create the product
   6: Pizza hawaiian = cook.GetPizza();

I find this sort of code to be extremely verbose and hard to read. Especially when we have a lot of options and things to do. Fluent Interfaces, however, are just an instance of the Builder pattern, and they are basically adding a modern API look & feel to the way we are actually constructing objects. Another thing to remember is that we are dealing with C#, and we have things like object initializers to do a lot of the heavy lifting for building objects. You should use that, for most cases.

NHibernate, for example, has the notion of a Builder, using the NHibernate.Cfg.Configuration object. It allows us to put all of the construction / validation code in one spot, and then the actual runtime code in a different place (and can assume a lot about its invariants). It also allows to do a lot of interesting things, like serializing the builder object (to save building time), which is something that you usually can’t / hard to do with real objects.

That said, you should be careful of code like the one listed above .What you have there is an overly abstract system. Requiring multiple steps to just get somewhere. If you find yourself feeding builders into builders, please stop and think about what you are doing. If you got there, you have not simplified the construction process.

Recommendation: This is still a very useful pattern. It should absolutely not be used if all you need to do is just setting some values. Reserve the Builder patterns where you actually have logic and behavior associated with the building process.

More posts in "Design patterns in the test of time" series:

  1. (21 Jan 2013) Mediator
  2. (18 Jan 2013) Iterator
  3. (17 Jan 2013) Interpreter
  4. (21 Nov 2012) Command, Redux
  5. (19 Nov 2012) Command
  6. (16 Nov 2012) Chain of responsibility
  7. (15 Nov 2012) Proxy
  8. (14 Nov 2012) Flyweight
  9. (09 Nov 2012) Façade
  10. (07 Nov 2012) Decorator
  11. (05 Nov 2012) Composite
  12. (02 Nov 2012) Bridge
  13. (01 Nov 2012) Adapter
  14. (31 Oct 2012) Singleton
  15. (29 Oct 2012) Prototype
  16. (26 Oct 2012) Factory Method
  17. (25 Oct 2012) Builder
  18. (24 Oct 2012) A modern alternative to Abstract Factory–filtered dependencies
  19. (23 Oct 2012) Abstract Factory

Comments

Moti

I find this pattern priceless when working with legacy code.

Yves Reynhout

I've been using message builders for a long time now and found they bring this to the table: - better semantics/intent (more verb-y than noun-y), - making a construct that is immutable, mutable for the duration of its construction, - allow different parts of the code to contribute to the building process

Mark

I agree with Ayende. In the real world what use a cook in a pizza parlour if he doesn't know how to make an Hawaiian pizza.

Euphoric

Yes, the example is too simplified and doesn't show real power of Builder pattern. It only shines when used in more complex scenarios or in conjunction with other patterns, like strategy. It is logical to use Builder when code specifying the construction details is actually different than the code that fetches the final result.

Frisian

I like the Builder pattern as it is popular in the Java world: http://www.informit.com/articles/article.aspx?p=1216151&seqNum=2

It allows you to create immutable objects without endlessly writing constructors for all cases. All checks can be conveniently put into the build() method.

If you don't mind creating a new builder every time you want to create a new object, there is a simpler way with almost no overhead compared to getters/setters: http://egalluzzo.blogspot.de/2010/06/using-inheritance-with-fluent.html

João P. Bragança

Or the fact that he's constructing it. Probably tastes like cardboard.

sw
sw

You can embed defaults in the builders instead of putting them in the objects you construct. That keeps your actual objects clean. Builders are priceless for building configuration too. Some examples are AutoFac's ContainerBuilder or the fluent config builders for EntLib. In these scenarios it makes a lot of sense to "feed builders into builders". Think of building a configuration for logging where you build the sub-config for formatting log entries and the like.

Comment preview

Comments have been closed on this topic.

FUTURE POSTS

No future posts left, oh my!

RECENT SERIES

  1. The RavenDB Comic Strip (3):
    28 May 2015 - Part III – High availability & sleeping soundly
  2. Special Offer (2):
    27 May 2015 - 29% discount for all our products
  3. RavenDB Sharding (3):
    22 May 2015 - Adding a new shard to an existing cluster, splitting the shard
  4. Challenge (45):
    28 Apr 2015 - What is the meaning of this change?
  5. Interview question (2):
    30 Mar 2015 - fix the index
View all series

Syndication

Main feed Feed Stats
Comments feed   Comments Feed Stats