One of the
Learn Ruby Koans exercise is about implementing a method that calculate the score of the Greed dice game.
A friend reviewed my solution pointing out some conditional expressions that could be avoided (from 3 they are zero now), some state that could be removed (greed_roll_scores is calculated and never changed now), and in the way of the refactoring some duplication (2 similar rules of the games now are both applied with a unique common logic) become evident and I removed it.
Here is the resulting
score method, I left also the comments with the Greed game description and the original tests:
-
http://pastie.org/3146621
How good is this solution?
Again my friend suggested to see
how easy is to read (you judge this then) and
how easy is to extend with new features.
Well a good design, is
emergent, is not required to and do not predict/anticipate future features (
YAGNI).
Instead when
a new rule is similar to the existing ones, it should be easier/faster then before to implement.
And when
a new rule is completely different, well here is where you cannot and should not even try to predict and anticipate; the more you can add new unpredictable rules just adding/extending code and without throwing away the existing code, the more the design is good.
Here there are new rules that I didn't know when I implemented the code in the first place. I can try to add to the initial implementation of the
score method:
-
http://en.wikipedia.org/wiki/Greed_(dice_game)
The first 4 new rules (4-of-a-kind, 5-of-a-kind and 6-of-a-kind) are similar to the existing rules (3-of-a-kind), let see how easy is to extend the implementation:
-
http://pastie.org/3146856
Quite well: only a small change of the existing
score method implementation is needed.
The last 2 new rules (a straight and three couples) are quite different to the existing rules, let see how easy is to extend the implementation:
-
http://pastie.org/3146991
Quite well: only a small addition of the previous
score method implementation. No evidence from here that the design is bad.
Happy to hear your
comments and see
others solutions
Update: a reflection suggested by Riccardo while discussing off-line is about splitting the logic of each rule in a separate method and having the
score method that apply the set of rules. This way make it easier to add a new rule: just define the new rule in a method and add it to the rules collection in
score method.
This is the result:
http://pastie.org/3151265
Update: a new version inspired by Matteo solution
https://gist.github.com/1617603
and here the related unit tests
https://gist.github.com/1725633