Things learned while pairing
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.
Chris Sanyk
March 14, 2011 @ 2:14 pm
If you really wanted to keep your test methods segregated, in C# at least you could write them in separate text files, using partial classes to keep all your test methods together, apart from your “real” class members.
I’m not sure how else one would go about it, but I’m sure my mind isn’t yet experienced enough to be able to say whether there aren’t any other approaches that would be equally or more viable.
It was fun partnering with you, and a really enjoyable day overall. I love events like that.
Mark W. Schumann
March 14, 2011 @ 3:21 pm
Hey Chris.
Keeping the methods segregated wasn’t my goal. I was simply playing along with the idea that you only unit test public methods, because that’s what all the TDD gurus say. I like to use unit tests to pinpoint defects, so I kind of want to test private methods, which is where all the gutsy stuff happens.
So I really like your idea of adding test methods to the class being tested, but I also want to hear from the gurus: why exactly is it not a good thing to unit test your privates? And if you do put NUnit test methods into a production class, do you go ahead and decorate the production class as a TestFixture? (I guess you’d have to.)
I haven’t thought this through, but I know it’s kind of important.
Yeah, I liked pairing with you on that project too. Events like CodeRetreat attract the people who really want to learn.