subscribe via RSS
You May Not Need Builders Ever
One of the greatest advatages of using Builder pattern is giving names to methods in languages without named parameters support. Here’s builder example in Java.
Foo foo = new FooBuilder()
.withId("abc")
.withName("Some meaningful name")
.build();
Constructor can be used to build the same object, but parameter
meanings are disguised. In this case design also suffers from the
same types (well, all of them are String
s), which makes it easy
to accidentally put arguments in wrong order.
Foo foo = new Foo("abc", "Some meaningful name");
Some languages (eg. Scala) let us specify parameters by name. Using named parameters is a great way to obsolete usage of verbose Builder pattern and retain the same level of readability.
val foo = Foo(id = "abc", name = "Some meaningful name")
But what if only some of the parameters need to be specified while others can stay as is? Scala supports default parameter values.
class Foo(id: String, name: String = "Some meaningful name")
val foo = new Foo(id = "abc")
So if you work with modern language, consider ditching verbose Builder pattern in favour of your language features.
Scala has a copy
method on case classes which can be used as replacement
for Builder, but I find its name to be very low level and communicating
wrong message to the reader most of the time.
// BAD: I need a foo with specific name, but what I do is
// communicate copying
val foo = foo.copy(name = "New Name")
// GOOD: method name communicates intention - reader does not know
// how object is constructed
val foo = aFooWith(name = "New Name")