Monday, March 15, 2010

API Design & Closures

In a recent design discussion, I've noticed that the preferred java-ish approach is rather verbose.

Suppose we want to create an expression tree and evaluated-it:

solution1:
ExpressionTreeBuilder b = new ExpressionTreeBuilder();
b.newExprY(a,b);
b.newExprX(c,d);
....
ExpressionTree t = b.toTree();
interpreter.eval(t);

I find this solution rather difficult for 'beginners', the people who see the API for the 1st time. As a 1st time user of the API, I discover the interpreter as a service, and I start searching for the ExpressionTree to give it to the interpreter. I find the class, but it is immutable. I finally, redirect myself to the ExpressionTreeBuilder and I realize how can I use all the parts properly. IMO the above approach has a detective-trying-to-solve-a-puzzle feeling, exposing too much of the implementation mechanism.

A much cleaner solution would be:
interpreter.eval { |b|
b.newExprX()
b.newExprY()
}

This solution has a single point of entry and the user is directed to the correct API usage. The intermediate build/transform steps are hidden. It reminds me of scala loan pattern, or ruby html builder.