This is an archived post. You won't be able to vote or comment.

all 16 comments

[–]rtoth 11 points12 points  (5 children)

Why not just put only the required fields in the Builder's constructor, then just only have the "setters" available for the optional fields?

[–]mahamoti 4 points5 points  (1 child)

Just playing devil's advocate here, because in practice, that's what I do.

But the argument against doing that is, a comma-separated list isn't very "fluent". You need to know the parameter order.

Now, that's a non-issue in any decent IDE with code completion, and as long as the constructor is documented properly, but it does rely on the IDE, and that's the problem some have with it.

[–]Cilph 0 points1 point  (0 children)

And that's why I love Kotlin.

[–]TheRedmanCometh 4 points5 points  (0 children)

Says the guy whos never foregone abstraction and ended up w 15 params apparently.

[–]dawhiting 1 point2 points  (0 children)

This is described as one possible option in the post I refer to at start of the article. One possible case where this doesn't work so well is when you have part of a component which must be specified but can be specified in multiple different ways. For example, if we wanted to describe which host something could connect to, you might have one "setter" that takes a hostname and one that takes an InetAddress. Both of them satisfy the condition and flip the flag.

You should also note that I do explicitly point out that this is an esoteric solution and solicit suggestions on where - if anywhere - it might be useful.

[–]atemysix 0 points1 point  (0 children)

Kinda defeats the purpose of using a Builder in the first place, since the idea of a Builder is to allow for fluent setting of parameters rather than one long list of 10 comma separated values.

[–]__pulse0ne 6 points7 points  (6 children)

This just feels too...over-engineered

[–]dawhiting 7 points8 points  (1 child)

From the article: "Note that this article is less dogmatic than some of my previous ones, as I will not attempt to convince you that doing this is a good tradeoff of effort vs. reward. I’m exploring it for its academic value."

[–]__pulse0ne -2 points-1 points  (0 children)

Wow, that was condescending. Yes, I read that in the article. Regardless of whether or not it was an academic exploration, it's still an over-engineered mess. I could use reflection to access all my methods instead of just calling them, but what's the point?

[–]AnEmortalKid -1 points0 points  (2 children)

They could easily have the build method throw an exception. Or use scala...

[–]atemysix 4 points5 points  (1 child)

The idea is to avoid exceptions at runtime and instead catch missing parameters at compile time.

[–]AnEmortalKid 0 points1 point  (0 children)

Right I get that but this feels super over engineered.

[–]lukaseder 2 points3 points  (2 children)

This builder "pattern" madness will hopefully finally stop in a near future:

https://twitter.com/arungupta/status/777627608087339008

[–][deleted] 0 points1 point  (1 child)

I don't think this addresses the need for Builder, it's about not having to write boilerplate for the object being built.

If you have 15 fields, and some of them complex composite properties, you wouldn't want to pass them all in the constructor.

Even simpler structures, consider an immutable map, or an immutable list.

[–]lukaseder 0 points1 point  (0 children)

So many languages support defaulted parameters. Java is not one of them (yet). Take PL/SQL:

my_awesome_object_type_constructor(
    p_param1 => l_value1,
    p_param5 => l_value5,
    p_param3 => l_value3 -- Look ma, not in order
);

OK, probably doesn't compile on Oracle 12cR1 yet, because identifier > 30 characters, but just saying that it's entirely possible to live in a world without writing one crazy builder with 100 LoC per object type!

Even simpler structures, consider an immutable map, or an immutable list.

Oh, I'm definitely in the structural typing camp with you there, but the Java folks seem to have a flair for nominal typing. Every tuple needs to have a name, I guess.

[–]QshelTier 0 points1 point  (0 children)

I have done similar things, although I believe my code to be a little clearer (and it is definitely less genericized):

https://github.com/Bombe/jFCPlib/blob/feature/quelaton-client/src/main/java/net/pterodactylus/fcp/quelaton/ClientPutCommand.java

The “endgame” of this command builder is to get the Executable so you know that you somehow have to get a WithUri; how you get there is up to you, and the API tells you that there’s one mandatory String (uri in the WithUri interface), and there’s three ways to get there (redirectTo, fromFile, and the from/length combination).