picture home | pixelblog | qt_tools

omino code blog

We need code. Lots of code.
David Van Brink // Tue 2006.09.5 21:47 // {Uncategorized}

Bad Code (3 of 3): In Hope Of Good Code

Read part one first, please,
and then read part two!

There is Hope
I think there is hope. Perhaps you’re expecting me to now discuss how to refactor Bad Code into Good Code. I’m not. One of the properties of Bad Code is that it’s easier to rewrite than to refactor.

Or, conversely, one of the properties of Good Code is that you actually can refactor it. Of course, when I say “refactor” I’m thinking of benign explicable tasks like “make this its own class” or “gently move this functionality from here to there.” Because with Good Code that’s all you ever need to do.

No, this old engineer thinks the claim that “You can refactor Bad Code into Good Code” is just a glib and meaningless phrase, up there with “agile development.”

But when you’re called upon to rewrite it, here’s some strategies that might help. A little. I can’t help you with rational architecture. But I can offer a few tips that will at least let your code be usable in 20 minutes.

Setup, Then Run
Here’s the general pretty picture approach to managing your dependencies:

Put your dependencies all in one place, and deliver them to the workhorse in one lump. If you gather them up, first, and name them (don’t just pass System.properties or @ENV around!) then you can clearly identify what they are. And then, why then — it brings tears to my eyes — you can control the workhorse completely. And the obligations of a user of the library are clearly spelled out by the empty holes of the SetupInfo object. That setup object can turn weeks into 20 minutes, for the recipient of this Good Code.

Don’t Use Files
Design your core API around in-memory data rather than files:

Files are just another kind of system dependency. If you pass around in-memory objects then a user of the library can create the input however they like, and can manage the output however they like too. And if they do want to read or write files, well, they can do that, too. (Also, this can speed up your unit tests considerably!)

Easy To Say == Easy To Do
Any software library has some purpose. You should be able to say what that is. You should be to easily say, in English (for example), a few of the things that the library can do. And the code to do those things should be very nearly as brief!

If you say “This is a package for analyzing Toves for their degree of Slithiness, and applying Gyre to them,” then there simply must be a complete example that is very nearly as short:

ToveManager tm = new ToveManager(); // by default, no config file
ToveConfig tc = getMockToveConfig(); // something I cooked up
tm.setConfig(tc);
Tove[] toves = tm.createToves(13);
double k1 = toves[0].getSlithiness();
toves[0].setGyreAndGimble(5,Gimble.WABE2);
double k2 = toves[0].getSlithiness();
assertTrue(k2 > k1); // should increase slithiness

Conclusion
I’ve had quite a few years of dealing with mostly Bad Code, with the occasional gem Good Code to be found. But it’s rare. I try to write Good Code, but I don’t always succeed. I think the important thing to realize is that your code is a gift to the future. Sometimes a pet-owner will say something like, “Oh, dear, Fifi left us another gift.” All too often that’s how code is. But it can be otherwise. Try to be generous.

oh, i dont know. what do you think?



(c) 2003-2011 omino.com / contact poly@omino.com