We were unable to load Disqus. If you are a moderator please see our troubleshooting guide.
I think you could still use the object initializer syntax for the builder. Just have the builder constructor do the value defaulting. Couple this with an implicit conversion operator and you get:
Foo foo = new FooBuilder { Bar = "bar" };
One more advantage is, it allows user to plugin their own custom implementation into framework. Please refer the following blog.
The second item in 'Effective Java (2nd edition)' is 'Consider a builder when faced with many constructor parameters'.
And this advice is aimed at all code, not just test code. One of the points Joshua Bloch makes is that rather than using the following
NutritionFacts cocaCola = new NutritionFacts(240,8,100,0,35,27)
which is hard to write, and harder still to read, we can us the builder pattern
NutritionFacts cocaCola = NutritionFacts.Builder(240,8).calories(100).sodium(35).carbohydrate(27).build()
which simulates named optional parameters (required parameters, e.g. 240 and 8, are passed in to the Builder's constructor).
The Builder is an inner class, so it is easy to locate.
@joe I thought the implicit operator needs to go on the target class although just trying out what you suggested does seem to work which is really cool!
I'm sure I tried that a few times before I posted and couldn't get it to work but it certainly seems to work now - thanks for the tip
oops C&P error:
return new Foo {Bar = current.bar, Baz = current.baz, Bling = current.bling};
Why can't you apply the implicit operator to the builder class so that you end up with
public static implicit operator Foo(FooBuilder current)
{
return new Foo {Bar = bar, Baz = baz, Bling = bling};
}
Foo newFoo = new FooBuilder().Bar("A").Baz("B")
How does require a change to a non-test class?
A fluent interface has also technical uses, besides pleasing the eye:
http://web.sysart.fi/develo...
In short: passing a fluent "sentence" around allows effective streaming of events, and the resulting code is beautiful.
Here is a more complex example, a converter from a parsed Java AST to an ngrease element (tree). The fluent building sentence is IMHO piped nicely in and out from the AST visitor methods with absolutely no need for any state management:
I don't quite understand why you'd do this and not just get rid of the automatic get;set and just return a default instead.
Like:
private foo = "defaultFoo";
public string Foo {get { return foo; } set { foo = value; } }
This way you could use the object initializer and have the same build pattern you're talking about.
Building objects like this is a lot more transparent in languages that support keyword parameters:
#python
foo = Foo(bar="bar")
#ruby
foo = Foo.new(:bar => "bar")
It's very nice specify just what you care care about, and tell the reader what it is that you're specifying.
In my last couple of projects, I've enjoyed the use of the Machinist framework for building domain objects for integration tests.
You give Machinst blueprints for your objects (using a convenient internal DSL), and Machinist builds an object graph whenever you want one, allowing you to override just the parts you are interested in.
What you are really replacing here is the Setter pattern, not the Builder pattern. The big difference is that with a builder I can have private variables within the object that are initialized via the builder, but then are immutable. There is no set property and no chance of having the value changed down the road. This can allow me the avoid situations where the object might be in an inconsistent state.