Like many people, I am a huge fan of Sandi Metz. I find that she has an uncanny ability to take complex topics and deconstruct them in ways that my brain can understand. So, when I saw that she had recently co-authored a new book - 99 Bottles Of OOP - A Practical Guide To Object-Oriented Design - with Katrina Owen, I knew that I had to check it out. And, of course, I was not disappointed. Well, maybe I was a little disappointed when I realized that the last 2 chapters were missing (the book is currently in Beta); but, I'm just taking that as a promise of future-goodness coming directly to my Inbox.
The entirety of the book revolves around the very concrete example of creating and refactoring an object that is responsible for producing the lyrics to the song, 99 Bottles of Beer (on the wall). While the focus of the book is very narrow, the exploration is deep and iterative. Metz and Owen walk through the problem space, talk about the challenges in moving forward at every step, and layout the various strategies that one can use when deciding how to refactor the code.
A consistent theme throughout the book is the idea that you don't have to know all of the answers ahead of time. Which is great, because I almost never feel like I know the answers to good Object-Oriented Design. As the book unfolds, Metz and Owen demonstrate the promise that if you just chip away at the problem, "one code smell at a time," the patterns will emerge and the abstractions will become obvious.
Writing code is the process of working your way to the next stable end point, not the end point itself. You don't know the answer in advance, instead you are seeking it.
The verse method is accumulating lots of duplication, and this may feel troubling. However, you are very close to having code to produce every verse. While it may be tempting to veer onto the vertical path and begin DRYing out duplication, it's best to push forward horizontally.
With the end in sight, the cost of finishing the horizontal path is low. Once it's complete, you'll have an example of every different kind of verse, and therefore maximal information about the problem. When the current code is easy to understand, and more information is imminent, be shameless and scramble towards green.
Before undertaking this refactoring, it must be admitted that there is no direct connection between removing the duplication, and succeeding in making the code open to the six-pack requirement. That, however, is the beauty of this technique. You don't have to know how to solve the whole problem in advance. The plan is to nibble away, one code smell at a time, in faith that the path to openness will be revealed.
Considered from a higher viewpoint, each variant is merely a verse in the song; in that sense they are all the same. Underlying each concrete variant is a generalized verse abstraction. If you could find this abstraction, you could use it to reduce the four-branch case statement to a single line of code.
The good news is that you don't have to be able to see the abstraction in advance. You can find it by iteratively applying a small set of simple rules. These rules are known as "Flocking Rules"....
With the "Flocking Rules," Metz and Owen articulate and then apply a set of simple rules for continuously making small, incremental changes to the code while searching for the patterns and the possible abstractions. The rules are simple; but, the real value is sitting inside the brain of Sandi Metz as she talks about how the rules can be applied to the problem at hand.
I think one of my biggest take-aways from the book is to not try to find the abstractions too early. Instead, work towards a solution that satisfies the problem; then, when you have all the information about the solution, refactor towards a cleaner, more elegant implementation.
While the primary value of the book - for me - is the Object-Oriented Design, the entirety of the book is written in the context of Test-Driven Development (TDD). And, while I don't know all that much about testing, I did want to leave you with a few excerpts on the matter that made a whole lot of sense to me:
DRYing out the lyrics in the test would force you to introduce an abstraction. Tests are not the place for abstractions -- they are the place for concretions. Abstractions belong in code.
If you rearrange code without changing behavior and tests begin to fail, then the tests themselves are flawed. Tests that make assertions about how things are done, rather than what actually happens, are the prime contributors to this predicament.
This last quote speaks directly to my belief that testing Private methods and implementing Spies is a bad idea and goes against the fundamental value of encapsulation. So, at least for that, I feel some vindication.
Like I said above, the book is currently in Beta and is missing the last two chapters. The current incarnation, however, is excellent and leaves me eager to see what the last two chapters entail. The book is a little bit more expensive than other technical books; but, I rather enjoyed it and I believe it contains strategies that will help me become a better software engineer.