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::buildfrom rust-analyzer. -
File::with_optionsfrom std. -
RequestandResponsefrom http.
Discussion on /r/rust.