Legacy-Code And A Small Codebase: Don't Reuse! Re-Implement!

Sunday, July 29. 2007
Well, we fucked up. As always - we just haven't accepted yet how nonsensical and absurd a Client's requirements mostly are, we haven't learned yet how to interpret them correctly and we still don't know how to do precognition properly - but that's what's expected of you, it seems.
This time, our project was to make "some small changes" to a custom content management system written in our beloved (beware of the irony) PHP a year ago. Before accepting the contract we not only had a chance to see the functionality of the system, but also the code. While it was quite unimaginable to us how you could still write code like that in 2005 we didn't investigate any further - granted, it was ugly, badly (if at all) designed, not secure, not using any of the web's newer features, using a mixture of all PHP-Versions available while avoiding to use the newer features in a way that actually made sense, using indentation as a kind of graphical, artistic element unrelated to syntax or semantics and mixing PHP and HTML in a really clueless old-fashioned "let's quickly write a dirty script"-fashion quite unsuitable for a "professional" project. But hey - the small feature-changes we were asked to do wouldn't require us to change any of that...right?

Well, it wasn't until we actually began coding that we discovered sweet examples of "I ain't got no clue - but I took the money anyway" of our predecessor. Like the following fields in a database-table:
date, time, date1, time1, date2, time2, date3, time3, date4, time4.
It seems like our dear colleague just changed the database every time he discovered that an item could appear more than once. Of course he also hardcoded those things into the code.
What's even nicer was that he hadn't managed to centralize database-access, he just kept writing the same queries and mysql-statements into every file. Which meant that when we began normalizing the database we had to touch about every file, change it, test it, etc. It was of course work we weren't paid for because we hadn't expected we would have to do it. Further along we discovered that code he hadn't managed to get to work actually didn't work - he'd just created dummy-functions without any functionality. Users weren't supposed to be able to enter more then one entry of typeX per day - but in reality nothing prevented them from doing so because
function checkUserPermission($user) 
{ /*hm...this ain't working
blahb, lahblah;
blah;
blahblah;
*/
return true; }
didn't really care. (And yes, the crappy formatting is genuine, that's the way the guy writes code! Python should be compulsory for weirdos like him)
His use of javascript was especially heartwarming. In short, its only purpose in the CMS was to make it non-accessible to JS-disabled browsers. No, I'm not exaggerating even a little bit. To submit data to the server, for example, he would use a hidden form in the page, monitor updates to fields outside that form via javascript, update the hidden-form with the new values, and then monitor clicks on links via javascript as well and in case of a click call submit() on the hidden form! The hidden form would have an onsubmit()-handler defined, but you can already guess its definition:
function validate() 
{
return true;
}
It really made no sense at all. You still had all the page-reloads the standard-use of forms would have given you (but those would have been accessible), you had no additional value (the checking functions didn't do anything), but with JS disabled you wouldn't have been able to do anything at all because not even the simplest link would have shown any function. Yep, of course the JS wasn't used in an unobtrusive way, it was just intermingled and hardcoded in the middle of all the PHP and HTML, the guy hadn't even bothered to set href-attributes in <a>-tags, he just used all the tags as event-targets.

Well, I could go on for hours, but I guess all I'm trying to say is that not only is a good design (and I ain't talking about graphical designs, for all you webdesign-only guys) at the beginning of every software implementation process, but a thorough examination of requirements, the environment, available code, flexibility with respect to changing requirements needs to be a cornerstone of any work on legacy code. Unnecessary to mention that course the "small changes" were just the beginning of what we've been doing for weeks now. We've implemented several new features, and in the course of that we had to touch the old code many times. The side-effect of that is quite some improvement when it comes to overall code-quality, but all in all the legacy-stuff really slowed us down so much as soon as we began making major changes and adding features that it would have been better, cheaper, faster, and it would have boosted quality-of-life if we'd just sat down and properly re-implemented the whole system from scratch. Even more so when thinking of the side-effects like producing good-reusable software-elements that we could have used in future projects. Now much of our new code needed to be tied to the legacy-code in ways that would require at least some modification to make it reusable.

Lessons learned: Don't trust your clients - they want a lot more than what they're telling you. Don't continue to use a hacky-crappy-bad codebase, if it isn't really that large. And the size of the existing code might be irrelevant anyway. Just look at the functionality - maybe you can implement it with much fewer codelines.