Who Builds the Builder?
This is a short note on the builder pattern, or, rather, on the builder method pattern.
TL;DR: if you have Foo
and FooBuilder
,
consider adding a builder
method to Foo
:
struct Foo { ... }
struct FooBuilder { ... }
impl Foo {
fn builder() -> FooBuilder {
FooBuilder::default()
}
}
impl FooBuilder {
fn build(self) -> Foo { ... }
}
A more minimal solution is to rely just on FooBuilder::default
or FooBuilder::new
. There are
two problems with that:
First, it is hard to discover. Nothing in the docs/signature
of Foo
mentions FooBuilder
, you need to look
elsewhere to learn how to create a Foo
. I remember being
puzzled at how to create a GlobSet
for exactly this reason. In contrast, the
builder
method is right there on Foo
,
probably the first one.
Second, it is more annoying to use, as you need to import both
Foo
and FooBuilder
. With Foo::builder
method often only one import suffices, as you
don’t need to name the builder type.
Case studies:
-
TextEdit::build
from rust-analyzer. -
File::with_options
from std. -
Request
andResponse
from http.
Discussion on /r/rust.