Tuesday, August 5, 2008

A little time to think , please

So as you might imagine in any creative endeavor there are shades of gray in what is considered a finished product. For programming the "completeness" of a block of code can be examined and broken down in ways other artistic compositions cannot. Most examinations of code consist of test case examination, it's pass or fail, you do what you coded to or you don't. But there is an even more important and subtler test you should be looking for, elegance.

Elegance is difficult to define but you can see it's influence when a programmer comes out of a hectic hack-phase and announces "It's done, it's ugly but it's done". Looking through the code he feverishly produced he cringes at bad hacks and edge case problems. Still the cry echoes through the halls of his business "we don't have time to 'optimize' we have to beat the competition". So reluctantly he checks in the hacked code and turns to other projects. Like an artist churning out sculptures, hoping never to look back.

Life continues on, after all the code passed all the tests. But eventually the programmer (or more likely some other junior programmer *cringe*) will return to that block of code. Poring through it looks even worse than before like a fungus breeding the code embodied in that past hacked frenzy has spread throughout the rest of the code base, tarnishing everything it comes into contact with. The poor maintenance programmer finds a nice dirty fix that should work and, as he is needed to fight other fires, drops the fix in place and runs away. Glue still dripping out of the crevices of this ugly wart added to the already hideous code structure.

These two scenarios are constantly occurring, anywhere programming is happening. And the key factor is time, it takes time to make code elegant more time than just "making it". As Pascal writes,
"I apologize for the length of this letter, for I lacked the time to make it shorter."
He illustrates the goal of the extra time. It's not to add more functionality, or catch more edge cases, it's to shorten what you put in. To trim as much as possible out of the sculpture so only beauty is left. When code is shorter it automatically curtails many potential bugs. Take a look at this snippet (my own of course)

Date [] dates = getSomeDates();
Date special = getSpecialDay();
for(int i=0; i < dates.length; i++)
{

if( special.after(dates[i]) && special.before(dates[i+1]))
{
dates[i] = special;
}
}
For those syntactically challenge this bit of code takes an array of dates and then determines if the special day falls in between any of the two dates. If it does it sets the earlier date to the special day. So what's wrong with this code? I will tell you now it functions under most normal circumstances. If you've figured it out, think about how long it took you. Imagine how much harder it would be if you wrote the code and weren't looking for an error. The problem is that [i+1], at the very end of the array of dates you ask for the end +1 which doesn't exist. Java doesn't mind because normally you'll get back a null and before() handles a null just fine. But if for some reason java had to put something next to your array... you could get back any kind of random thing. Making a fun intermittent bug. It took me a good while after having written that code to see the problem. Maybe a reviewer would have caught it, if he were lucky or super competent, as long as he wasn't overloaded with reviews.

My point here is I was able to catch the bug (and actually rewrite the whole thing to increase it's elegance and cut out a few potential bugs) because I had spare time. I wasn't running headlong for a goal spraying crappy code willy-nilly. This was not because my employer didn't wish me to, it's just my bug load happened to be low so I took my time. So I'm begging you, future employers, please give us a little time to think. Give us time to create elegance, you'll be better off in the long run.

No comments: