July 21, 2009

Builder Pattern - The Swiss Army Knife of Object Creation, Part 2

Are you still eager to learn how we use the Builder Pattern in Java to build hierarchical structures? Like the Groovy People, but without the dynamic Groovyness? In my last article I prepared everything we need for today. Hence take your pen and paper and follow me into the auditorium. The others are already waiting for us...

July 16, 2009

Builder Pattern - The Swiss Army Knife of Object Creation

It comes out that one of my new hobbys is feeding and taking care of unpopular design patterns. Up to just recently the Builder Pattern was one of this unloved creatures, but the enormous success of Groovy's awesome transformation of a single Design Pattern to a complete new world of DSLs converted the Builder to everybody's new Darling. This is the first article in a series of some, which discusses the Builder Pattern in static typed Languages like Java. This article gives a brief introduction to the Builder Pattern in general. With Groovy's dynamic typed nature, we are able to declaratively construct structures like this
def swing = new SwingBuilder()

def sharedPanel = {
     swing.panel() {
        label("Shared Panel")
    }
}

count = 0
def textlabel
def frame = swing.frame(
    title:'Frame', 
    defaultCloseOperation:JFrame.EXIT_ON_CLOSE, 
    pack:true, show:true) {
    vbox {
        textlabel = label("Click the button!")
        button(
            text:'Click Me',
            actionPerformed: {
                count++
                textlabel.text = "Clicked ${count} time(s)."
                println "Clicked!"
            }
        )
        widget(sharedPanel())
        widget(sharedPanel())
    }
}
In Groovy's ecosystem this concept nearly became a new religion. Domain models are declared, rather than manually plugged together. Grails and Griffon showcase a mutltiverse of applications. Beginning from configuring Database connections, Spring Beans even good ol' Log4j up to whole GUIs via SwingBuilder in Griffon. Today we declare software. And that's ok. Because it eases reading, writing and understanding.

The point is, is this only possible, if you utilize those new, fancy dynamic typed languages? Couldn't we build structures the declarative way even in our old, poor static languages? It would be sad, if the answer is no. The world is full of legacy application, Joe the Plumber Coder has to work with. Even poor Joe should have the oppertunity to write cool code. Hence gladly the answer is yes. But guys, to be honest, it is not that straight 'Just implement BuilderSupport' road. The path I show you gets dirty, filled with stacks and temporary structures, but is definitely worth the effort. (And since I'm always honest to you: We don't even get there today, but just the next time...)

But first things first: Let's talk about the basics of the Builder Pattern. We should have the same understanding, at least. The Builder Pattern is one of the so called Creational Patterns. It has one single purpose, and that's creating structures. But it does it with some super awesome fancyness. To see how it does it, we need to make one step back and have to reconsider why we actually need help in constructing objects. Surely, instantiating a plain new foo.Bar() is for beginners. But we are talking here about complex structures. Let's make up some real example. Have you ever handcrafted java.awt.GridBagLayout? The last time I did, I was pretty annoyed about building the GridBagConstraints:

JComponent content = getContent();
GridBagConstraints c11 = new GridBagConstraints();
c11.gridx = 1;
c11.gridy = 1;
c11.weighty = 1.0;
c11.weightx = 1.0;

c11.fill = GridBagConstraints.HORIZONTAL;
c11.anchor = GridBagConstraints.FIRST_LINE_START;

backgroundPanel.add(content,c11);
Do you see what happens? Maybe not on the first look (yes, you do, you are a pro, but please do so as if you didn't), because it is very noisy. What we actually wanted to do is adding our content component to the backgroundPanel. Therefore we have to have to create the GridBagConstraints instance, and assign those constraints we want to apply to our content component. But since GridBagConstraints is a dull Pojo, we need to set each value by hand. This means, for each constraint we want to set, we need to write c11.someConstraint = someContraintValue . Yes of course, it could be worse, like we could have to implement it with punch cards, but that's what I just called noisy. When I want to construct something, I want to have it so obvious and redundant free as possible. Constantly repeating c11. = does not kill anyone, but it's also not the best idea we can come up with.

Ok, this is just one of the problems we have here. The next one jumps in our face where we set fill and anchor. and here the annoyance factor is already huger. GridBagLayout is as the rest of Swing from Java's Pre Enum Era (As a matter of fact even before Josh Bloch discovered the Type Safe Enum Pattern): Enumeration Values are encoded as Int Constants. This is bad but it gets worth: GridBagConstraints hosts several different Enumerations in the same scope. On one hand there are those values related to fill, like HORIZONTAL and there are enum values considering anchor like FIRST_LINE_START. Since they are intermixed in the same Naming scope, namely GridBagConstraints, auto complete is no help at all, when it comes to guessing what to assign to fill. You have to look up in the API Docs to see your options. Nothing flaws coding more then breaking your flow of coding if you really have to step into Documentation. And finally you can argue: What's that nonsense with setters? That's why POJOs have Constructors, just use them, and your whole argumenation vanishes. Maybe, but actually i don't like these types of Constructors

GridBagConstraints(
int gridx, int gridy, int gridwidth, int gridheight, 
double weightx, double weighty, int anchor, int fill, 
Insets insets, int ipadx, int ipady) 
Just imagine an instantiation and then your desire to maintain it. Which one was gridwidth? The first or the second? Mh, let's look into Javadocs, and then count the parameters... No, sorry Sir. I waste my time differently. But up to now I've promised much, and proofed nothing. So be so kind and have a look:
backgroundPanel.add(
    getContent(),
    new GbcBuilder()
        .grid(1,1)
        .weight(1.0,1.0)
        .fillHorizontal()
        .anchorLastLineEnd()
        .build() );
Do you see now what I meant with noise? Nothing of it left. When we get to building the constraints, GbcBuilder comes up to our expectations. We even did some helpful things here: Grid values are only assigned in pairs, why bother with two lines if we could have one? Do you see any arbitrary Int Constants anywhere around? No? Auto complete just offers us fillHorizontal(). 'Huh, fill & horizontal, i guess that's what i need, let's take it.' And how did we do this it? Let me show you:
public class GbcBuilder {

    private GridBagConstraints constraints;

    public GbcBuilder(){
        constraints = new GridBagConstraints();
    }

    public GridBagConstraints build(){
        return constraints;
    }

    public GbcBuilder grid(int gridX,int gridY){
        constraints.gridx = gridX;
        constraints.gridy = gridY;
        return this;
    }

    public GbcBuilder weight(double x, double y){
        constraints.weightx = x;
        constraints.weighty = y;
        return this;
    }

    public GbcBuilder fillHorizontal(){
        constraints.fill = GridBagConstraints.HORIZONTAL;
        return this;
    }

    public GbcBuilder anchorLastLineEnd(){
        constraints.anchor = GridBagConstraints.LAST_LINE_END;
        return this;
    }
}
This is actually a super short version of a GridBagConstraintsBuilder. A proper solution would be a little bit huger. Nevertheless, you already see the important aspects. The builder does what he promises: He builds what he should, holds the instance internally and finally spills it out. By constantly returning itself, the Builder gives us this fancy mechanism to repetitively call him. Quite useful feature. But I've already mentioned the drawback. Providing a builder is expensive in terms of implementation time. Is does not pay out if we talk about very specialized structures, which might be initialized only once in your code. But for your working horse model classes, which are used everywhere around the corner, maybe this is quite helpful. This should be enough for now. Today we've learned some interesting things, namely the Groovy People love the Builder, they have invented whole Domain Specific Languages with it. Furthermore the Builder helps us with the proper construction of those structures, which are complex to fill by encapsulating the knowledge how to fill them. Although I've promised, I have not explained how to build complex hierarchies of objects, like we've seen in Groovy and there are even some noteworthy words about Builders and Immutability to say. But we will keep this for the next time. I hope you come back.

Here you can find Part 2.