rentzsch.com: tales from the red shed

Teststands for Exploratory code

Code
Lately Dave Thomas and his evil-nontwin Andy Hunt has been harping on the need for developers to practice. Their articles have brought to mind a technique that's worked quite well for me over the years: teststands.

Create a new, empty project. Set it up as you like it, so it's easy for you to use. Include your favorite libraries, and turn off the optimizers (which slow down compilation and make low-level debugging more difficult). Now leave it, empty, sitting there. This is your teststand.

Your teststand is your sandbox. Your scratchpad. Your playpen. Teststands are handy because they're not involved with your "serious", real project. They're stand-alone. You can afford to royally screw-up in your teststand without taking a hit on your real project. However, the opposite is thankfully not true -- you can copy the "wins" from your teststand and plop them into your real project.

So, the next time you run into an area of a language you don't completely understand, you can quickly open up your teststand and write some exploratory code. This might sound somewhat "unprofessional" -- you should look up the standards document of your language for the answer. Actually, I've found it better to go ahead and write the test code to discover the answer for yourself. Reasons:

  • Writing the test code itself helps clarify exactly what you don't understand, or what the problem is.

    I think it's related to the well-known phenomenon of how explaining a problem can suddenly cause you to realize its solution. I've written countless email to mailing lists that never get sent, since the act of writing out the email and anticipating potential responses opened my eyes to the solution. Others recommend investing in a little yellow rubber duck.

    The worst case is that the code you've written doesn't clear your fog, but then it's something concrete you use to illustrate your confusion/problem when asking for assistance from others.

  • Standards are theory.

    Your compiler's implementation may be inconsistent or incomplete. By writing the test code, you are testing your immediate reality.

This doesn't preclude going to the "official standard" (if one even exists for your language!), but it puts you in a stronger position of understanding if you do.

Teststands are also handy for drafting, refactoring and verifying tricky code. Reviewing my C teststand (I never throw away my teststand code, I just push it aside and move ahead), I learned I've used it to:

  • Make sure code that should operate solely in a 32-bit word was in fact not spilling over and scribbling over memory it doesn't own.
  • Draft and complete a fast URI character encoder/decoder, which was later dropped into a project.
  • Learn exactly how various #pragma pack(push, N) compiler directives effect structure padding (used for my paper on data alignment for MacHack 2001).

Interestingly, in my Java teststand, I see most of my code revolves around string manipulation. Specifically, making sure I get all the zero-based index math right, especially in edge cases. I find when I move code "wins" from the teststand into the real project, I replicate the edge cases using unit testing.

A concept related to teststands are spikes. I also use spikes all the time. Indeed, it's how I learned WebObjects. This was back in the 4.5 days, when documentation was scant and books nonexistent. So I wrote spike after spike after spike, for three weeks. Perhaps somewhat inefficient, but it really helped me understand the product.

I view spikes as different from teststands in terms of size. I tend to create a new project for each spike I write. So, when dealing with a fragment or two of code, I use the teststand. If it's something more, I use a spike.

Thursday, March 27, 2003
12:00 AM