The RapidPM Blog

We are coding Java, because it is a great pleasure for us.

Nested Builder

Nested Builder
While working with the Builder Pattern you will come to the point, when you have to build up complex objects. Suppose we would like to create Car. It consists of such attributes like engine, machine and a number of wheels. For this purpose we use the following class model.
public class Car {
    private Engine engine;
    private List<Wheel> wheelList;
}

public class Engine {
    private int power;
    private int type;
}

public class Wheel {
    private int size;
    private int type;
    private int colour;
}
Now it is possible to generate a corresponding Builder for each class. If you adhere to the basic pattern it will look like this for the class Wheel:
   public static final class Builder {
        private int size;
        private int type;
        private int colour;

        private Builder() {}

        public Builder withSize(int size) {
            this.size = size;
            return this;
        }

        public Builder withType(int type) {
            this.type = type;
            return this;
        }

        public Builder withColour(int colour) {
            this.colour = colour;
            return this;
        }

        public Wheel build() {
            return new Wheel(this);
        }
    }
The Builder is implemented as inner static class and thus it makes modifications in the class Wheel, which allows one to use only the Builder to create an instance. Of course, here I have omitted the option via reflection.
public class Wheel {

    private int size;
    private int type;
    private int colour;

    private Wheel(Builder builder) {
        setSize(builder.size);
        setType(builder.type);
        setColour(builder.colour);
    }

    public static Builder newBuilder() {
        return new Builder();
    }

    public static Builder newBuilder(Wheel copy) {
        Builder builder = new Builder();
        builder.size = copy.size;
        builder.type = copy.type;
        builder.colour = copy.colour;
        return builder;
    }
...}
But how does it look like, if we want to create an instance of the class Car? Here we come to the point, when we have to add the instance of the class Wheel to the instance of the class Car.
public class Main {
  public static void main(String[] args) {

    Engine engine = Engine.newBuilder().withPower(100).withType(5).build();

    Wheel wheel1 = Wheel.newBuilder().withType(2).withColour(3).withSize(4).build();
    Wheel wheel2 = Wheel.newBuilder().withType(2).withColour(3).withSize(4).build();
    Wheel wheel3 = Wheel.newBuilder().withType(2).withColour(3).withSize(4).build();

    List<Wheel> wheels = new ArrayList<>();
    wheels.add(wheel1);
    wheels.add(wheel2);
    wheels.add(wheel3);

    Car car = Car.newBuilder()
                 .withEngine(engine)
                 .withWheelList(wheels)
                 .build();

    System.out.println("car = " + car);
  }
}
This source code is not particularly well-done and in no way compact. So how can one adjust the Builder Pattern, in order to write manually as little of the Builder source code as possible, on the one hand, and, on the other hand, to have more convenience in using? WheelListBuilder Let's take a small detour. For example, to ensure, that only four wheels can be added to Car, you can create a WheelListBuilder. Here you can check in the method build(), if four instances of the class Wheel are available.
public class WheelListBuilder {

    public static WheelListBuilder newBuilder(){
      return new WheelListBuilder();
    }

    private WheelListBuilder() {}

    private List<Wheel> wheelList;

    public WheelListBuilder withNewList(){
        this.wheelList = new ArrayList<>();
        return this;
    }
    public WheelListBuilder withList(List wheelList){
        this.wheelList = wheelList;
        return this;
    }

    public WheelListBuilder addWheel(Wheel wheel){
        this.wheelList.add(wheel);
        return this;
    }

    public List<Wheel> build(){
        //test if there are 4 instances....
        return this.wheelList;
    }

}
Now our example is as follows:
public class Main {
  public static void main(String[] args) {

    Engine engine = Engine.newBuilder().withPower(100).withType(5).build();

    Wheel wheel1 = Wheel.newBuilder().withType(2).withColour(3).withSize(4).build();
    Wheel wheel2 = Wheel.newBuilder().withType(2).withColour(3).withSize(4).build();
    Wheel wheel3 = Wheel.newBuilder().withType(2).withColour(3).withSize(4).build();

//        List<Wheel> wheels = new ArrayList<>();
//        wheels.add(wheel1);
//        wheels.add(wheel2);
//        wheels.add(wheel3);

    List<Wheel> wheelList = WheelListBuilder.newBuilder()
        .withNewList()
        .addWheel(wheel1)
        .addWheel(wheel2)
        .addWheel(wheel3)
        .build();//more robust if you add tests at build()

    Car car = Car.newBuilder()
        .withEngine(engine)
        .withWheelList(wheelList)
        .build();

    System.out.println("car = " + car);
  }
}
Next step is to connect the Builder of the class Wheel to the class WheelListBuilder. The aim of it is to get a Fluent API, in order to avoid individual creation of each instance of the class Wheel and its connection via the method addWheel(Wheel w) to the WheelListBuilder. For programmer it should look like this in using:
List<Wheel> wheels = wheelListBuilder
    .addWheel().withType(1).withSize(2).withColour(2).addWheelToList()
    .addWheel().withType(1).withSize(2).withColour(2).addWheelToList()
    .addWheel().withType(1).withSize(2).withColour(2).addWheelToList()
    .addWheel().withType(1).withSize(2).withColour(2).addWheelToList()
    .build();
The following thing happens here: As soon as the method addWheel() is called, a new instance of the class WheelBuilder should be returned. The method addWheelToList() creates the instance of the class Wheel and adds it to the list. To achieve it, one has to modify both Builders involved. On the side of the WheelBuilder the method addWheelToList() is added. This method adds the instance of the class Wheel to the WheelListBuilder and returns the instance of the class WheelListBuilder.
private WheelListBuilder wheelListBuilder;

public WheelListBuilder addWheelToList(){
  this.wheelListBuilder.addWheel(this.build());
  return this.wheelListBuilder;
}
On the side of the class WheelListBuilder only the method addWheel() is added.
  public Wheel.Builder addWheel() {
    Wheel.Builder builder = Wheel.newBuilder();
    builder.withWheelListBuilder(this);
    return builder;
  }
If we apply this to the other Builder, we will get a quite considerable result:
      Car car = Car.newBuilder()
          .addEngine().withPower(100).withType(5).done()
          .addWheels()
            .addWheel().withType(1).withSize(2).withColour(2).addWheelToList()
            .addWheel().withType(1).withSize(2).withColour(2).addWheelToList()
            .addWheel().withType(1).withSize(2).withColour(2).addWheelToList()
          .done()
          .build();

NestedBuilder

Up to now the Builders were modified manually. It can be easily implemented in a generic way i.e. in a form of Builder tree. Thus each Builder knows its Children and its Parent. The necessary implementation can be found in the class NestedBuilder. It is assumed here that the methods for setting attributes always begin with "with". Since it is true for the most Builder Generators, no manual adjustment is necessary.
public abstract class NestedBuilder<T, V> {
  /**
   * To get the parent builder
   *
   * @return T the instance of the parent builder
   */
  public T done() {
    Class<?> parentClass = parent.getClass();
    try {
      V build = this.build();
      String methodname = "with" + build.getClass().getSimpleName();
      Method method = parentClass.getDeclaredMethod(methodname, build.getClass());
      method.invoke(parent, build);
    } catch (NoSuchMethodException
            | IllegalAccessException
            | InvocationTargetException e) {
      e.printStackTrace();
    }
    return parent;
  }

  public abstract V build();

  protected T parent;

  /**
   * @param parent
   * @return
   */
  public <P extends NestedBuilder<T, V>> P withParentBuilder(T parent) {
    this.parent = parent;
    return (P) this;
  }
}
Now we can add to one Parent the specific methods for connection to the Children. A derivation from NestedBuilder is not needed.
public class Parent {

  private KidA kidA;
  private KidB kidB;

  //snipp.....

  public static final class Builder {
    private KidA kidA;
    private KidB kidB;

    private Builder() {
    }

    public Builder withKidA(KidA kidA) {
      this.kidA = kidA;
      return this;
    }

    public Builder withKidB(KidB kidB) {
      this.kidB = kidB;
      return this;
    }

    // to add manually
    private KidA.Builder builderKidA = KidA.newBuilder().withParentBuilder(this);
    private KidB.Builder builderKidB = KidB.newBuilder().withParentBuilder(this);

    public KidA.Builder addKidA() {
      return this.builderKidA;
    }

    public KidB.Builder addKidB() {
      return this.builderKidB;
    }
    //---------

    public Parent build() {
      return new Parent(this);
    }
  }
}
And on the Children side it is as follows: here it must be derivated only from NestedBuilder.
public class KidA {

  private String note;

  @Override
  public String toString() {
    return "KidA{" +
        "note='" + note + '\'' +
        '}';
  }

  private KidA(Builder builder) {
    note = builder.note;
  }

  public static Builder newBuilder() {
    return new Builder();
  }

  public static final class Builder extends NestedBuilder<Parent.Builder, KidA> {
    private String note;

    private Builder() {
    }

    public Builder withNote(String note) {
      this.note = note;
      return this;
    }

    public KidA build() {
      return new KidA(this);
    }

  }
}
The usage is then very compact, as it is seen in the previous example.
public class Main {
  public static void main(String[] args) {
    Parent build = Parent.newBuilder()
        .addKidA().withNote("A").done()
        .addKidB().withNote("B").done()
        .build();
    System.out.println("build = " + build);
  }
}

Conclusion

Of course any combination is possible. It means that a Proxy can be Parent and Child at the same time. So there is nothing else to prevent the building of the complex structures.
public class Main {
  public static void main(String[] args) {
    Parent build = Parent.newBuilder()
        .addKidA().withNote("A")
                  .addKidB().withNote("B").done()
        .done()
        .build();
    System.out.println("build = " + build);
  }
}

Is your JUnit KnowHow up to date? - Part 3

This time i want to cover the topic of parameterizing JUnit tests with the Parameterized runner which is also part of my blog series Is your JUnit knowhow up to date? The last article can be found here. So let us get started.

For this article assume that we have a simple calculator which looks as follows:
public class Calculator {
    public static int add(int x, int y) {
        return x + y;
    }
}
and want to test the add method with several different combinations of parameters. A naive solution could look like this:
    import org.junit.Test;

    import static de.bischinger.junit.parameterized.Calculator.add;
    import static org.assertj.core.api.Assertions.assertThat;

    public class NaiveBadCalculatorAddTest {

        @Test
        public void should_pass() {

            //Test parameters 1
            int x = 1;
            int y = 2;
            assertThat(add(x, y)).isEqualTo(3);

            //Test parameters 2
            x = -1;
            y = -2;
            assertThat(add(x, y)).isEqualTo(-3);

            //Test parameters 3
            x = Integer.MAX_VALUE;
            y = Integer.MAX_VALUE;
            assertThat(add(x, y)).isEqualTo(-2);

            //Test parameters 4
            Integer boxedX = Integer.valueOf(1);
            Integer boxedY = Integer.valueOf(2);
            assertThat(add(boxedX, boxedY)).isEqualTo(3);
        }
    }

To be honest...it works. But it lacks in two aspects:
  • Test isolation - which means your test method tests several different assumptions which are not separated from each other (here for example positive and negative addition as simple corner cases). That way tests are harder to understand directly in the code and also in the reports if something went wrong.
  • Clean code - the code itself is very declarative and grows badly with every new assumption you want to test.

Maybe at one point you noticed that the code could be optimized if you extract your input parameters and expected results into an array. A possible solution could look like this:
    public class OptimizedNaivBadCalculatorAddTest {

        @Test
        public void should_pass() {

            int[][] parameters = new int[][] { { 1, 2, 3 }, { -1, -2, -3 }, { Integer.MAX_VALUE, Integer.MAX_VALUE, -2 },
                { Integer.valueOf(1), Integer.valueOf(2), 3 } };

            for (int[] parameter : parameters) {
                assertThat(Calculator.add(parameter[0], parameter[1])).isEqualTo(parameter[2]);
            }
        }
    }
Now the code is more compact and readable and everything should be fine. But wait...what if you want to do that in another test case? Do you copy that construct into every test case? And what do you do if you have to do some stuff in @Before or @After with the parameters?

This is the point where JUnit provides the concept of the Parameterized runner. In fact the transposition from the code above is not that far away if you look at the following code
@RunWith(Parameterized.class)
public class NaivParameterizedCalculatorAddTest {

    @Parameters
    public static Iterable data() {
        return Arrays.asList(new Object[][] { { 1, 2, 3 }, { -1, -2, -3 }, { Integer.MAX_VALUE, Integer.MAX_VALUE, -2 },
            { Integer.valueOf(1), Integer.valueOf(2), 3 } });
    }

    private int x;
    private int y;
    private int expected;

    public NaivParameterizedCalculatorAddTest(int x, int y, int expected) {
        this.x = x;
        this.y = y;
        this.expected = expected;
    }

    @Test
    public void should_pass() {
        assertThat(Calculator.add(x,y)).isEqualTo(expected);
    }
}
As you can see the following changes have to be done:
  • Annotate your test class with @RunWith(Parameterized.class). That way JUnit knows that it has to look out for the @Parameters-Annotation
  • Provide a public static method annotated with @Parameters, a random name and a return value of either Iterable or Object[]
  • Provide a constructor with corresponding count and datatypes in which you can map the parameters to member fields
Now you can use the member fields in your test methods, have a small readable test and can use the full power of the JUnit lifecycle. But the constructor part still looks like it could be optimized with Java reflections. Therefore JUnit provides the @Parameter-Annotation as follows:
@RunWith(Parameterized.class)
public class ImprovedParameterizedCalculatorAddTest {

    @Parameters
    public static Iterable data() {
        return Arrays.asList(new Object[][] { { 1, 2, 3 }, { -1, -2, -3 }, { Integer.MAX_VALUE, Integer.MAX_VALUE, -2 },
            { Integer.valueOf(1), Integer.valueOf(2), 3 } });
    }

    @Parameter public int x;
    @Parameter(1) public int y;
    @Parameter(2) public int expected;


    @Test
    public void should_pass() {
        assertThat(Calculator.add(x,y)).isEqualTo(expected);
    }
}
So the constructor can be removed if you change the visibility of your member fields to public (thanks to reflection) and add @Parameter to every member field. JUnit just needs to know which field of the parameter array should be mapped to which member field. As you can see it works with an index number which is defaulted to 0. And again the code is more compact then before considering clean code. But what happens if some parameter combination fails within the test?

configured @Parameters
unconfigured @Parameters




I have changed the fourth test result from 1 to 3 and my IntelliJ shows me the result of the left picture. I think that is not very meaningful. But with a small detail of the @Parameters- Annotation it can look like the right picture. In order to do that you can use the name field of the @Parameters-Annotation which is defaulted to the String {index} and shows the index of the parameter field. To improve the output the following code snippet could be used to create a more meaningful output:
@Parameters(name = "{index}: Calculator.add({0},{1})={2}")


As usual all code samples can be found on my github account https://github.com/AlexBischof/junit-parameters

4 Kids: Devoxx and JavaLand

The last month was amazing. We (that is Alexander Bischof and Oliver Milke) have been on tour for JavaLand 4 Kids and for Devoxx 4 Kids. These kids are awesome and every single event we prepare for the kids makes it even more of a pleasure for us.

JavaLand 4 Kids

As you can guess from the name, the JavaLand 4 Kids took place during to the famous JavaLand conference in Phantasialand in Cologne on 2015-03-24. It was inspired by the Devoxx 4 Kids and organized alongside the rest of the conference by DOAG. It was just by chance that this event came to our attention, but we immediately agreed it would be good idea take part and use another opportunity to teach and inspire the kids.

Alexander Bischof, Arun Gupta, Oliver Milke

During dinner we sat close to Arun Gupta, who is one of the initiators and driving forces behind the Devoxx 4 Kids.

Fried Saacke, chairman of the conference team, stated that he would like to introduce JavaLand 4 Kids as integral part of the JavaLand conference and we are looking forward to next year's JavaLand 4 Kids already.

Devoxx 4 Kids

Two and a half weeks later, another Devoxx 4 Kids took place in Karlsruhe on 2015-04-11. This was the second Devoxx 4 Kids in Karlsruhe and it was mainly a chance for all the kids who missed the first event as the workshops were the same like last year. My girlfriend Anne Doege also took place as support in working with kids. She studied Social Work, which makes her a perfect addition to our team and she even helps to display to the kids that technological affinity is also for women. synyx organized a great a event for the kids and a fantastic "after work party", as well ;-)

Impressions

Events like the Devoxx 4 Kids and JavaLand 4 Kids are invaluable for the kids. They are so grateful and clever. The kids literally cling to your lips awaiting to be taught more and more.

We truly enjoy taking place in these events, since the atmosphere with the other coaches and the kids is inspiring. More importantly however, there has been some buzz around the 4-Kids events recently. The media feedback for the JavaLand was enormous, which greatly helps in spreading the idea of the Devoxx 4 Kids. Moreover, we can be proud that we had a significant participation of girls in both events. We hope this continues.

What did we do with the kids?

We introduced the kids to the Internet of Things and showed them how to work with the electronic parts of Tinkerforge. Tinkerforge provided the materials the kids played with during JavaLand 4 Kids and Devoxx 4 Kids. You can find out more about our workshop in the official Devvox 4 Kids repository and read more about it in an article about the Devoxx 4 Kids of last fall..

This is a good place to say thank you. Thank you, Tinkerforge, for providing the materials for the kids!

What's next?

Fortunately there are more events already planned. There will be a Devoxx 4 Kids in Hamburg on 2015-06-06.

There will also be another Devoxx 4 Kids in Karlsruhe this fall and hopefully a new JavaLand 4 Kids during next JavaLand. We are already looking forward to participating :)

More to read