The builder pattern in Dick's Devoxx presentation

134 views
Skip to first unread message

Jesper de Jong

unread,
Nov 20, 2009, 3:49:11 PM11/20/09
to The Java Posse
Hello Dick,

In your presentation at Devoxx this week (which was very interesting!)
you showed a slide that demonstrated a builder pattern in Java, with a
number of interfaces. It looked interesting, but I forgot the exact
details of how it looked. Can you please share it here?

regards
Jesper de Jong

Moandji Ezana

unread,
Nov 20, 2009, 6:58:44 PM11/20/09
to java...@googlegroups.com
IIRC, it was a series of single-method interfaces. Each method returned the Builder type, except the "last" method, which returned the target type. The builder implemented all the interfaces and returned this for every implemented method.

The point was to have the IDE's auto-complete guide you through the use of the builder. The FEST-Reflect library is a very good example of this kind of builder.

Moandji


--

You received this message because you are subscribed to the Google Groups "The Java Posse" group.
To post to this group, send email to java...@googlegroups.com.
To unsubscribe from this group, send email to javaposse+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/javaposse?hl=.



Reinier Zwitserloot

unread,
Nov 20, 2009, 8:11:53 PM11/20/09
to The Java Posse
I was listening to Michael Ernst's amazing pluggable type checker
framework talk which conflicted with Dick Wall's, but I'll grab a
parleys subscription so I can view it when Stefan Janssen and cohorts
finish polishing up the videos. This sounds like an interesting idea
I've never seen before, and it also sounds like a massive wall of
boilerplate. I foresee a lombok transformation.
> > javaposse+...@googlegroups.com<javaposse%2Bunsubscribe@googlegroups .com>
> > .

Moandji Ezana

unread,
Nov 21, 2009, 5:45:57 AM11/21/09
to java...@googlegroups.com
On Sat, Nov 21, 2009 at 2:11 AM, Reinier Zwitserloot <rein...@gmail.com> wrote:
This sounds like an interesting idea
I've never seen before, and it also sounds like a massive wall of
boilerplate.

Entirely true. Again, check out FEST-Reflect for an example of how practical it is to use, and how impractical it is to write.

Moandji

Jesper de Jong

unread,
Nov 21, 2009, 3:33:34 PM11/21/09
to The Java Posse
Thanks for the replies. Yes, Dick's builder pattern indeed had the
fluent interface style, like FEST has. I'll have a look at how it's
done in FEST.

Jesper

On 21 nov, 11:45, Moandji Ezana <mwa...@gmail.com> wrote:
> On Sat, Nov 21, 2009 at 2:11 AM, Reinier Zwitserloot <reini...@gmail.com>wrote:
>
> > This sounds like an interesting idea
> > I've never seen before, and it also sounds like a massive wall of
> > boilerplate.
>
> Entirely true. Again, check out
> FEST-Reflect<http://fest.easytesting.org/reflect/> for

Dick Wall

unread,
Nov 23, 2009, 10:03:13 AM11/23/09
to The Java Posse
Hi, thanks for the interest. Here is the example builder I used in its
entirety:

// The builder DSL
public interface SnpIdChromBothAllelesOnly {
public SnpDetail withOddsRatios(Map<Genotype, Double>
oddsRatios);
}

public interface SnpIdChromRiskOnly {
public SnpIdChromBothAllelesOnly withNonRiskAllele(char
nonRisk);
}

public interface SnpIdChromOnly {
public SnpIdChromRiskOnly withRiskAllele(char risk);
}

public interface SnpIdOnly {
public SnpIdChromOnly withChromosome(String chrom);
}

public static SnpIdOnly buildForId(String rsId) {
return (new Builder()).newFor(rsId);
}

public static class Builder implements SnpIdOnly, SnpIdChromOnly,
SnpIdChromRiskOnly, SnpIdChromBothAllelesOnly {

private String rsId;
private String chrom;
private char riskAllele;
private char nonRiskAllele;

public SnpIdOnly newFor(String rsId) {
this.rsId = rsId;
return this;
}

public SnpIdChromOnly withChromosome(String chrom) {
this.chrom = chrom;
return this;
}

public SnpIdChromRiskOnly withRiskAllele(char risk) {
this.riskAllele = risk;
return this;
}

public SnpIdChromBothAllelesOnly withNonRiskAllele(char
nonRisk) {
this.nonRiskAllele = nonRisk;
return this;
}

public SnpDetail withOddsRatios(Map<Genotype, Double>
oddsRatios) {
return new SnpDetail(rsId, chrom, riskAllele,
nonRiskAllele, oddsRatios);
}
}


It is, as mentioned previously, a wall of boilerplate (so much of Java
is), but this is still a neat pattern worth mentioning. In particular,
it uses different interfaces, each with a single method, returned from
each builder method, to lead you through the creation of the object.
This idea could be extended, for example if you needed either one
thing or another but not both, at some point you would return the
builder cast as an interface that offered only two methods, each of
which returning a different interface view of the builder, etc.

The technique is overkill in this case, but if you have a DSL that is
intended to be used in a very controlled way and also is heavily used,
it starts to make more sense, since you can enforce object creation in
a way that you can only get the real object back once you have
satisfied all of the dependencies.

The point of the talk was to mention that default and named parameters
largely eliminate the need for this kind of builder (although if you
really want to control everything about it, this same technique can be
used in Scala and other languages too).

Cheers

Dick

Reinier Zwitserloot

unread,
Nov 23, 2009, 3:38:26 PM11/23/09
to The Java Posse
I've redesigned the way I envision @Buider to work once I add it to
lombok based on this; it's an excellent idea as the boilerplate is
generated anyway. My biggest concern with this design is that you blow
up the ability to use a builder in the StringBuilder fashion - as an
object that you pass along, where each place contributes its own
little part of the full build of this object. Well, you still can, but
it all has to be in a very specific order and you have to use specific
type names. However, this style isn't as bad as the one we were
discussing before; as a 'workaround', you can cast your
SnpIdChromRiskOnly object back to the SnpDetail.Builder class to get
access to everything. It's not the prettiest form, but you can do it,
you can document that this will always work regardless of API
revision, and splitting up the building process across a multitude of
methods is generally rare.

It gets more complicated rather quickly when you start adding
optionals into the mix; where do you store the default values? You can
de-final your fields and just stick them on the field itself, but now
you've got fields that are supposed to be immutable that aren't final,
which feels a bit meh. Not to mention it could theoretically cause
issues in a multi-threaded environment. Perhaps a private field named
fieldName_DEFAULT is a better option, though it feels a bit hacky to
it that way. To handle the optional nature of this, you'll need a
specific 'build()' method so that the last required chain returns an
interface with build() as well as set options for each optional field.

Thanks for posting, Dick. Not something I've ever seen before, and
really takes 'documentation-by-auto-complete' to the next level.

--Reinier Zwitserloot

Moandji Ezana

unread,
Nov 23, 2009, 4:24:07 PM11/23/09
to java...@googlegroups.com
On Mon, Nov 23, 2009 at 9:38 PM, Reinier Zwitserloot <rein...@gmail.com> wrote:
It gets more complicated rather quickly when you start adding
optionals into the mix; where do you store the default values?

Wouldn't you store them in the builder? I don't think you can get very far without a build() method, though there are various ways of doing without one for a while.

For extra safety, you could make the builder itself immutable.

There are some nice blogs about builders for unit test data by Nat Pryce and Jay Fields. I think they could blend nicely with Dick's and FEST's auto-complete-driven approach.

Moandji

Casper Bang

unread,
Nov 23, 2009, 5:31:42 PM11/23/09
to The Java Posse
Have used the technique before as well, especially good when designing
an API for others to use - it effectively renders documentation
pointless. :) My usage was influenced by Wicket, which also goes far
in assisting the developer when it comes to chaining properties like
converters, validators etc. Knowing Dick is also using Wicket, I
wonder if he was influenced by it too?!

/Casper

On Nov 23, 4:03 pm, Dick Wall <dickw...@gmail.com> wrote:

Patrick Wright

unread,
Nov 24, 2009, 4:41:34 AM11/24/09
to The Java Posse
This article a great review of the various builder techniques, and the
trade-offs involved
http://www.infoq.com/articles/internal-dsls-java

I also found Martin Fowler's discussion helpful (see this page and
pages linked from it, e.g. NestedFunction and MethodChaining)
http://martinfowler.com/dslwip/ExpressionBuilder.html


Patrick
Reply all
Reply to author
Forward
0 new messages