An Intellij plugin to generate a nested static Builder for a Class.
Why another Builder plugin? --------------------------- There were several Builder plugins already out there, but none that generated a Builder that conformed to the pattern laid out in [Effective Java](http://www.informit.com/articles/article.aspx?p=1216151&seqNum=2), which we use extensively. In addition, the [Features](/README.md#features) outlines other goodies.- Download the latest release.
- From Intellij: Preferences -> Plugins -> Install plugin from disk...
- Restart Intellij
- From a Class, right click -> Generate... -> Builder...
- Remove any fields you don't want and select which fields are nullable
- Creates a static nested Builder that conforms to the pattern in Effective Java.
- Select what fields you want to include in the Builder.
- A Guava
Preconditions.checkNotNull
will be added to the constructor for non-null fields. - If
javax.persistence
annotations exist on fields, nullable will be inferred for the UI dialog box. - Can optionally generate getters, which will return an
Optional
if the field is nullable.
public void testBarThingIsDifferent() {
Bar bar1 = ... // complicated construction code with many fields
bar1.setThing("thing1");
Bar bar2 = ... // more construction code
bar2.setThing("thing2");
Zen zen = ... // still more setup code
Foo foo1 = new Foo(bar1, zen);
Foo foo2 = new Foo(bar2, zen);
assertSomethingAboutBar(foo1, foo2);
}
Now if we use a Builder and write a test fixture method once:
public class TestFixtures {
...
public Foo.Builder newFooBuilder() {
return new Foo.Builder()
.bar(newBar())
.zen(newZen());
}
...
}
Now we can reuse the fixture method everywhere and only override exactly what we care about.
public void testBarThingIsDifferent() {
Bar bar1 = testFixtures.newBarBuilder()
.thing1("thing1")
.build();
Bar bar2 = testFixtures.newBarBuilder()
.thing2("thing2")
.build();
Foo foo1 = testFixtures.newFooBuilder()
.bar(bar1)
.build();
Foo foo2 = testFixtures.newFooBuilder()
.bar(bar2)
.build();
assertSomethingAboutBar(foo1, foo2);
}
Some good things about the new Test:
- We've completely removed the construction of objects we don't care about, like
Zen
- It's very clear that
thing
is different and that's what we're testing.
The main drawback to using a Builder is the tedious overhead to write one. The fewer dependencies you have, the less inclined you are to write one. But we just argued for a Builder with only 2 depenencies? That's where the plugin comes in! Say you have the given class:
public class Foo {
private final Bar bar;
private final Zen zen; // This can be null.
}
With the click of a button you can generate the following code:
public class Foo {
private Bar bar;
private Zen zen;
private Foo(Builder builder) {
this.bar = Preconditions.checkNotNull(builder.bar);
this.zen = builder.zen;
}
public Bar getBar() {
return bar;
}
public Optional<Zen> getZen() {
return Optional.ofNullable(zen);
}
public static class Builder {
private Bar bar;
private Zen zen;
public Builder bar(Bar bar) {
this.bar = bar;
return this;
}
public Builder zen(Zen zen) {
this.zen = zen;
return this;
}
public Builder fromPrototype(Foo prototype) {
bar = prototype.bar;
zen = prototype.zen;
return this;
}
public Foo build() {
return new Foo(this);
}
}
}