I Feel a Framework Coming On
[Agile Programming: Lesson One, Part Four]
I’ve been pitching to the world this notion of a gradual ascent into programming excellence, starting with just a bit of refactoring the innards of classes in a small problem space, and just a bit of test-driving in the same problem space.
I ask people to do the exercises, keeping methods really, really small, and really simple. But up until now, if someone asked, Got a Test for That?, my answer, sadly, was No, Sorry, Use Static Analysis Tools – There Are Tons of Them Out There. Lame answer.
Inspired (again) at a recent CodeMash by another whack at the excellent Ruby Koans, and having heard great things about similar Scala Koans, I wanted a koans-ish learning tool for refactoring. You know what’s cool and fun about these koans? Everything, that’s what. Learning should be fun. Yes, that’s right. You heard it here first. These test-based koans are super fun.
When I asked people to keep methods under some number of lines of code, and under some cyclomatic complexity threshold, I Wanted a Test for That. And now, indeed, I do. I have two Whack-A-Method exercises; one for refactoring a sub-optimal implementation of BankOCRKata, and another for continuing to test-drive a pretty-good-so-far partial implementation of the BankOCRKata. The first exercise has a couple of really Eager end-to-end tests, but Hey! They give you 100% Code Coverage! Yay for anything!
So, these are Eclipse projects. If you have Eclemma installed, then you can pull down Coverage As > JUnit Test, and behold: you see your code coverage, of course. And in either Whack-A-Method exercise, you see the results of the tests for current production code behavior, AND YOU ALSO see results of tests that automagically recurse through your output folders for .class files, and ask a little jarred-up, embedded static analysis tool called CyVis (Tx, Guys!) to instantiate a test case for each of your classes, and instantiate a different test case for each of your methods.
Because I used the Junit 4 built-in parameterized test runner extension, you don’t get much info from the tests that run green, and you cannot (at least as yet) click through ugly classes or methods in the failures (though I’ve provided meaningful failure semantics).
But Hey! It’s totally version 0.1, and it works OK.
Caveat Lector: Yes, We are Refactoring on Red
So, in the real world, you never want to refactor on a red bar, because you cannot tell whether you are screwing up existing behavior.
And, on the other hand, in the world of koans and learning tools, tests are an awesomely addicting, engaging learning mechanism. So, friends, consider this current Whack-a-Method a proof of concept. It’s easy to try, requires no installation, works right outa the box, and is fun.
But you must indeed distinguish between red bars in the tests that cover the production code, vs whackAmethod red bars. In this pair of exercises, it’s OK if your whackAmethod tests are red while you refactor. The other tests are saving your bacon with respect to code behavior. It’s not OK if those non-whackAmethod tests are red.
Of course, you are heading toward a green bar. And you want to get there as fast as you can, and stay there as much of the time as you can.
And ultimately this tool is likely to become plugins and extensions for editors like emacs and eclipse. Not because the world needs scads of additional source analysis plugins, but because most of them are as simple as a Saturn V rocket, and this one is dead simple. And for now, as I’ve said before, you really only need a couple of metrics.
Whack-Extract Till Green
In the refactoring Whack-A-Method exercise, you just keep extracting methods and classes until everything runs green. Easy? Try it and find out!
In the TDD Whack-A-Method exercise, you just keep test-driving your code till you have fulfilled all of the requirements in the Requirements.txt file, and you keep all the tests green as much of the time as you can.
Tweak the Thresholds, Once You Know What You’re Doing
You can tweak the constants in CleanTestBase.java to tighten or loosen the method/class size and complexity thresholds. But please don’t at first. The defaults help learning to happen.
Does it Eat its Own Dogfood?
Yes, it does. All the classes in the whackAmethod package are themselves fully Whack-A-Method compliant, given the default thresholds. Let’s see a plugin do THAT.
A Bit of 0.1 Framework Fer Ya
So, if you want to try this experiment on any Java codebase of your own, you totally can, with minimal copy, paste, config (well, as far as I know today — again, version 0.1).
- Copy the entire whackAmethod package from my test source-folder to your own test source folder. (If you want to refactor my source, go for it, lemme know, and I’ll likely give you commit rights to the project).
- Copy the cyvis.jar and the asm-all-2.1.jar to your project and build path.
- Change the constant STARTING_DIRECTORY_NAME in RecursiveClassFileFinder.java to point to the root of your output folder (it currently defaults to “bin”).
- Run the tests. The Whack-A-Method tests should all run.
- Contact me with any problems.