Ugly vs Clean Code: an A/B Comparison Exercise

A Tale of Two Codebases

I have been working for years, off and on, on a “breakable toy” codebase to use for three main purposes: evaluating the technical skills of programming candidates at Pillar Technology, making baseline assessments about the technical skills of new hires and client programmers, and conducting classes on agile/OO programming practices. In this and coming blogs, I am going to share with you the codebase itself (Java/Eclipse project), and my experiences and insights while developing and using it. I am also going to solicit your input on how to improve it as a teaching/mentoring tool, and as a set of exercises for evaluating programmers.

The Problem Domain

The codebase is two completely separate implementations (Legacy and “Cleaner” implementations) of a 10 x 10 TicTacToe game where the first player to 5 in a row in any direction wins. You play against the computer, and it typically kicks your patootie, whichever version you are playing against. (Well, it kicks mine.)

So I happened upon the Legacy version of this codebase more than a year ago, when looking to design this pedagogical tool, and determined it to be perfect, in a kind of sick, pathological way. Let me explain. The original codebase is a Java applet. It is, including all the applet code, a single, 1200+ line “class” with dozens of methods that looks like this:

Actually, that snippet includes method extractions and renames that I did. It was much worse before I got a hold of it and starting retrofitting Mike Feathers-style “characterization tests” and doing bits of opportunistic refactoring here and there.

So the whole thing has a fabulously high cyclomatic complexity. In other words, though this little TicTacToe applet is quite clever algorithmically at kicking your keister, it is supremely inextensible code, along at least several axes of extension. That was exactly what I needed.

The Point of the Exercise

The entire point of the codebase and its various uses is to make the point of the differences between extensible and inextensible code, and to measure and teach these practices that are most central to the extensibility of a codebase. The point is actually to give people an experiential sense of the sum of NOT using the best practices listed above, on the one hand, and using them, on the other. It’s a sharp-edged little A/B comparison exercise.

[Note: this exercise was conducted, to rave reviews, at both Agile 2008 and Agile 2009.]

What I Did, Crazy Man that I Am

I began with this Legacy game code, and with the tentative steps of poking and prodding it with tests (more on all of that later). I played against it (and lost!) a lot. I began to learn the algorithmic problem domain (entirely despite the maddeningly bad design).

I then constructed a jUnit test harness that would enable me to play a new, test-driven version of the game against the old one, and measure how much of the time I won. And I began to test-drive my first version of this game.

I ran my head-to-head test a lot. It was depressing. Despite months of research and learning, I was still getting my rear kicked 98% of the time, or so.

And that is roughly where we shall pick up in the next blog post, when I’ll share with you a zip file of the entire Eclipse project, including the Legacy and Less-Legacy versions of the code.

Until then, fair readers.