Report of the first run of the OCP kata

Two weeks ago we had our first meeting of the Milano Coding Dojo. It was great fun, and I was honored to see Giordano had prepared such a good presentation mentioning, among other things, the “OCP Kata” of my earlier blog post. The “Open Closed Principle” says that we should be able to add new feature by adding code, not by changing existing code (with an exception made for the place where the objects are created; after all, for the new class to be used, it must be instantiated somewhere.) The OCP Kata is a set of rules, to be used in a training session, that force us to apply the OCP.

So this was not only the first test-drive of this Dojo, but also of the OCP Kata. How did it go?

We worked randori-style on the Yathzee kata. My impressions follow.

On the OCP Kata rules

The OCP Kata was an influence only for the first test (forced us to use an explicit factory) and the second test (forced us to apply the OCP). After that, the OCP rules did not fire, as the problem was naturally easy to be solved in OCP style. After all, it was the implementation of a series of scoring rules for the Yathzee game. Once you have the scoring rules machinery in place, everything else can be completed just by adding a new class (and modifying the factory).

One class, many uses

We must always keep an eye on the design. The complexity of the code kept going up, until we worked hard at removing duplication. The OCP rules do not produce a good design by themselves. Early in the kata, the rule for “twos” was the same as the rule for “threes” with 3 in place of 2. The solution was to create a SingleNumberRule that takes the number in the constructor. We avoided making two classes, when a single class could be used in different context with different configuration.

The driving force was removing duplication.

More duplication

Later, we had a lot of duplication between the “pair” rule, and the “double pair” rule. The code that looks for a pair is needed in both rules. An old-school OO programmer would have made the two rules derive from a common, abstract base class. The abstract base class would be a repository for shared methods. Modern OO programmers know to use inheritance only as a last resort. So what could we do to remove duplication without inheritance? One key observation was that most of that duplicated code was looking heavily into the array of rolls. When you have code that uses heavily a data structure, it’s a good idea to move both data structure and code in an object.

The natural name for that object is “hand”, so we created a Hand class that wraps the array of die rolls. The duplicated code disappeared.

The driving forces were removing duplication and avoiding direct access to data.

Finding abstractions

The code in the Hand class was still not good enough. It was full of loops. There was no flash of insight here, we just applied a few “extract method”s that moved each loop in its own little method. Once we did that, we realized that some loops depended on another one that counts the occurrences of each number in the hand. For instance, the occurrences in the hand (1, 1, 3, 3, 4) are (2, 0, 2, 1, 0, 0). This is a key abstraction in this domain.

The other abstraction that is needed to implement the pair rule is “find me the highest pair”, which is just max{i | occurrences(i) ≥ 2}. (It is not enough to score *any* pair. It must be the highest pair, if more are present.)

To implement the “double pair” rule, we need a way to say “find the second highest pair”. One way to say this is that if the highest pair is, say, 4, we must look for the highest pair that is less then 4. The method we need is

    public int highestPairLessThen(int n) {
       return max{i | occurrences(i) ≥ 2 && i < n};
    }

Now the two pairs rule was easy to implement:

    public int highestPair() {
      return highestPairLessThen(7);
    }
    
    public int secondHighestPair() {
      return highestPairLessThen(highestPair());
    }

The solution here was to find the right abstractions, and implement complex things in terms of simple things. It’s a bit of functional programming in the small.

Conclusions

The goal of good design is to have simple building blocks that can be combined together to create complex things. When we are at the object-talking-to-other-objects level, the OCP principles guides us to invent object abstractions. When we are in the small, within-the-object level, it’s good to apply some mathematical thinking. It’s not deep, difficult mathematics. It’s just a game of finding the right definitions, and using them to express complex things in terms of simpler things.

Update: cleaned up HTML, added headings

One Response to “Report of the first run of the OCP kata”

  1. Andrea Maietta Says:

    Thanks for the post, as always very instructive for those who, like me, were not lucky enough to join the dojo

Leave a Reply