Hacker News new | ask | show | jobs
by noema 2033 days ago
The main intent of Builder isn't performance, but to avoid a combinatorial explosion of constructors for every possible set of parameters.
1 comments

So why have constructors for every possible set of parameters?

Why

    VerbalExpression.regex()
        .startOfLine().then("http").maybe("s")
        .then("://")
 .maybe("www.").anythingBut(" ")
 .endOfLine()
 .build();
Instead of

    new VerbalExpression()
        .startOfLine().then("http").maybe("s")
        .then("://")
 .maybe("www.").anythingBut(" ")
 .endOfLine();
Both are equally readable to me, but with the builder pattern you have an ability to fork a builder. Cloning objects in Java could be messy.
With immutable objects, every step in the fluent chain of calls is an independent fork of the full object state. There's no need to use java clone(); each method calls a private constructor that passes the object state (slightly altered, of course).

java.lang.String works exactly this way. You're already used to the pattern.

The builder allows you to have immutable objects. While I dislike builders and seldom use them, I dislike mutable objects even more.
In the parent's suggestion, you still have immutable objects. "VerbalExpression()" is a valid regex, namely the empty one. Every subsequently called method concatenates some new regex onto the receiver and thus builds a new regex (since regular expressions are closed under concatenation).

Builders are used in Java* when you have an object which is invalid without passing in a bunch of parameters, but you don't want to have to remember the order of the parameters. But this is not one of these cases.

There is one drawback, however: you do have to compile the regex into a FSA at some point and it wouldn't be good to do that for every intermediate regex. So I assume that the compilation happens in the "build" step. They could have just called it "compile", though.

* named parameters in constructors seem a better alternative in every language that supports them, e.g. Kotlin

Furthermore, with immutable objects there's no need to to have any public constructors at all.

`REGEX.startOfLine().then("http")...`

Since the start object is immutable, there's no reason to create new ones. Here's an example of this pattern applied to HTTP (my project):

https://github.com/stickfigure/hattery

Avoiding repeated Pattern.compile() is a good point though.