4 ms·
What's the advantage of: t = TemplateBuilder() .withFoo(foo) .withBar(bar) .excludeBaz() .build() over: t = Template(foo=foo, bar=bar, baz=none)
by javcasas 5y ago
What's the advantage of:
t = TemplateBuilder()
.withFoo(foo)
.withBar(bar)
.excludeBaz()
.build()
over:
t = Template(foo=foo, bar=bar, baz=none)
- culturedsystems 5y agoI agree there's not much point using this kind of simple builder if you have named function parameters, but the GoF builder pattern has a couple of additional features which can still be useful. In the GoF examples the construction process is more complicated (maybe the order in which construction steps take place is significant, and maybe parts of the construction might be conditional), and the same construction algorithm can be used to produce different types of object. If I remember correctly, the main example in the GoF book is a builder for creating documents by adding a title, subtitle, paragraphs, etc, and the document being constructed might be a UI representation, an RTF file, HTML, etc.
- valenterry 5y ago> maybe the order in which construction steps take place is significant That is just horrible... > maybe parts of the construction might be conditional No builder pattern needed for that, just use optional arguments and/or an option/nullable type.
- hermitdev 5y agoI think the builder pattern is more useful when you have sets of parameters that make sense together, but may be mutually exclusive with others. A more compelling example would be an IP address builder that supported different versions. ipv4 = IPAddress().v4("127.0.0.1").build() ipv6 = IPAddress().v6("::1").build() Trying to perform something like this in Python with merely a constructor on an IPAddress type would lead to a not-so-obvious interface (such as use X set of named args to construct a v4 address or use Y set of named args to construct a v6 address, but using X & Y in the same constructor is a runtime error). This is my contrived example for where the builder pattern might make sense. With your example, I don't see any compelling advantage to use the builder pattern. In fact, I'd argue as-is, the builder is unnecessary, is more verbose, adds additional complexity, and you should just use the constructor with named args instead. The point behind the builder pattern is to perform nontrivial initialization that is hard/difficult/impossible to perform in a normal constructor a la C++, C#, Java, etc. If you're not performing nontrivial initialization, you've just introduced extra verbosity and complexity for no gain, so don't use the pattern then. This is, of course, just my opinion. For example, if you see code that has a lot of overloaded constructors followed by an `init` function that must be called after construction, or code with a lot of overloaded `init`-type functions, only one of which shall be called; the builder pattern might make sense there.
- xigoi 5y agoipv4 = IPAddress.v4("127.0.0.1") ipv6 = IPAddress.v6("::1") KISS.
- gpderetta 5y agoYou do not have to use the same class for V4 or V6.
- hermitdev 5y agoI'm well aware. I chose the example to somewhat mirror what happens at the native posix level with addresses. It's the same structure, but can only be built in specific ways. Probably should have actual stated something to take effect.
- happymellon 5y agoI was talking about complex configurations with repetitive, not extremely basic named parameters. Think about a loadbalancer or an API Gateway that is going to loop through and generate several lambdas and their security groups. I'll post an example in a bit of what I mean, but using a builder lets me use functions to break down the template into readable pieces. And I'm not saying that it is impossible, I'm talking about readability.