Why not unit test private methods? Does an object know if it lives or dies? Beats me.
I spent a Sunday in January at Corey Haines’s Code Retreat, out on the LeanDog boat. Aside from being too darned early in the morning, and aside from the fact that I had to bail at the 3pm break because my kid thinks she needs a ride to college, it was a fantastic use of time.
The event is like this: You show up, hang out, grab a pair partner, and start doing test-driven development (TDD) on a specific programming problem. After forty-five minutes, you stop programming, join the big group again for a debriefing, and do it again from the beginning with a new pair partner.
And you do this like six times during the day. (I only stuck around for four iterations.)
The problem space
The actual programming problem was to mplement Conway’s Game of Life. It’s a devilishly clever assignment, partly because anyone who’s taken more than one Computer Science class thinks they’ve already solved it. But oh no.
If you don’t know about the Conway game, it’s not really a game you win or lose. You have an unlimited “board” of square cells arranged in rows and columns. Each cell is considered either “alive” or “dead.” On each “turn” every cell counts its eight immediate neighbors (including diagonals); if it has fewer than two live neighbors it “dies” of loneliness; if it has more than two live neighbors it “comes to life”; and if it has exactly two live neighbors it just stays the way it is. That is all. You just watch it go, turn after turn. It’s just cool. There is no object other than watching the patterns that “grow” from various starting configurations.
(If the above sounds like a really stupid waste of time, you are not a geek. Please find another career.)
Harder than it looks
This is actually kind of hard to implement in a real object-oriented way. How do you design your classes? Is there a Board that contains (“has-many”) an infinte number of Cell objects? That won’t work quite the way I made it sound, will it? How about keeping a collection (like a C# generic) of just the live Cells? (It’s a lot easier if you get to assume a limited playing field. But alas.)
What I learned
Somewhat importantly, Corey didn’t expect us to use any particular programming language. He encouraged us to pair with colleagues who were using languages we might not even know yet.
I learned a bit about object-oriented design, if by “learn” you mean “find things to argue with.” Briefly, master crafters like Corey seem to prefer a lot more abstraction in class design than I feel like wrapping my head around. I usually like a one-to-one relationship between code space and problem space; so to me an object is “a thing that does things,” and a class is the idea of what that object looks like and does. If I can’t think of it as a thing, it’s not an object– it’s a method. Maybe.
I didn’t get very far with my pair partners on any of the iterations. We kept getting hung up on the TDD cycle, confused with the problem space, or stuck on mundane tactical issues. In that way it was frustrating.
On the good side, I got to hang out and pair with Angela Harms on an iteration. There was a mutual aha moment when I said out loud, “A cell knows if it’s going to live or die.” Angela thought it was some Zen kind of cool. I thought I was having fun anthropomorphizing the code. We’re both right.
My man Chris Sanyk was there too. He wrote about it, and wrote about it again, and wrote about it yet one more time. Our favorite insight occurred when Corey said something about running unit tests only on public methods, which annoys me because sometimes all the interesting logic is in private methods. I was launching into a “rant” on this topic, according to Chris, when Chris simply said, “So write the test method inside your class.”
I was stunned for a moment, then opened my mouth to argue, realized what I was about to say would be wrong, then started to say something else that was wrong, and finally looked at Chris and went “aaaaaaah.”
Is that the right answer? Beats me. It’s not mainstream as far as I know. But it turned my idea of unit testing on its side.