The remainder of this refactoring exercise is left to you. I’ve posted my refactored solution. It contains some interesting but simple refactorings. Most significantly, I ended up creating a Ring class that manages the list of players and associated button. I also created a few utility methods. One production utility method makes it easier to create an ArrayList with initial elements. A test utility method makes it easier to determine whether or not a list contains a list of expected elements.
Otherwise, I spent about an hour going through the code, looking for opportunities to remove duplication and make the code more expressive. I’m pretty stoked about how it ended up. I’m sure there are more opportunities for improving the maintainability of the code, but otherwise it’s ready to support the betting interaction requirements.
Some of you are probably questioning this direction. It seems as if I’ve taken additional time in coding and refactoring because I didn’t create a perfect design up front. That argument is missing the point. In a system of this size, it’s possible that I could have come up with an optimal design, one that included the Game, Hand, Player, and Ring classes. But in all likelihood I wouldn’t have thought of creating a Ring class until I recognized the duplication inherent between Hand and Game—both need to track the players and their positions.
Design is validated only by actually coding it.
For any larger system and more complex set of requirements, the likelihood that you get the initial design anywhere near perfect goes down dramatically. Any efforts spent on upfront design rapidly diminish in value. And in my estimation, teams that attempt to perfect an upfront design spend more total time than teams that understand how to incrementally shape a design to support new features.
It’s just code, after all. Learn how to change it. TDD gives you most of the tools you’ll need.
Next segment: "Driving a User Interface." Meanwhile, here’s the code (source.zip) we’ve built in this installment.