Nightmare Before (Last) Christmas
A little over a year ago I was plunged into a nightmare world. I had accepted a new job as the lone PHP developer at a relatively small business, and when I finally got my hands on the code, I realized I'd gotten myself into a giant mess. While I'm happy at my job today, my first months were filled with disbelief, horror, anguish, doubt, and despair as I began to dig into the legacy codebase I had inherited.
Things were a little dicey those first few months. I'd seen really bad code before (I've written some truly awful code myself), but I'd never seen anything quite like what I was dealing with.
Rather than run away screaming, I decided I'd try to wrangle this code into shape, one tiny piece at a time. Here are a few of the things I've learned over the past year about dealing with legacy code.
There's a Difference Between Internal and External Quality
I once heard Stefan Priebsch comment on the fact that there's a difference between internal and external quality where web apps are concerned. That was an a€oAha!a€¯ moment for me, and I've never forgotten it. As bad as the code at my new gig was (and in many cases still is), the apps worked, and most of the users were very happy with them. Where I wanted to rewrite every bit of every app (including all of the front end), I had to remember that most everyone at the company was pleased with the way things were. Sweeping changes would cause more problems than they would solve.
One of my favorite stories to tell about my first week on the job was when I asked, a€oWhat version control system are we using?a€¯ I naively expected we were using Subversion or Git. To my shock and horror, the developer replied, a€oThere's only one developer; we don't need version control.a€¯ As soon as I recovered from that, I installed Subversion and versioned every bit of code and configuration I could find.
Not only was the code itself a mess, its location and organization was such that it was nearly impossible to find the code I was supposed to be working on in the first place. The situation with the server config files was nearly as bad. I did two things that helped immensely:
- I placed all of our sites in /sites and named each site's directory after the site's URL.
- I reorganized the existing Apache config files, breaking out the numerous VirtualHost directives into their own files.
Do. Not. Rewrite. Seriously, Don't Do It.
Rewriting should never be the first option. It shouldn't be the second option, nor even the third. Previous developers have domain knowledge you don't; they've solved bugs and addressed user issues you don't know anything about. Unless the external quality of the app has degraded to the point a complete rewrite is necessary, the best thing to do is take it slow.
Take It Slow
Refactor the code one little bit at a time. When I say one little bit, I'm not joking. Tiny changes. Small things like instituting a coding standard and reformatting the code you're working on can work wonders for readability. You might change variable names to be more descriptive, or move functions closer to where they're being called. At that point, and before you begin refactoring, it's time to write tests.
Tests Are Your Best Friend
The code I found seemed to be untestable, but over time, I've discovered that there's very little code that's truly untestable, even if you have to go through contortions to test it. The orthodoxy of automated unit and integration testing is excellent in theory, and amazing when you can make it happen (it should be a number one goal), but sometimes the reality of your situation won't allow for that. I frequently use the following technique when I begin testing disastrous code:
- Make a small change.
- Refresh the browser.
- Rinse. Repeat.
Don't Forget to Have Fun
Derek Siver's post, Because It's Fun!, really resonated with me. I started programming for many different reasons, but one of them was that programming is fun. There's nothing more excitinga€‰-a€‰nothing that makes me happiera€‰-a€‰than solving a really difficult programming problem. What bigger problem is there than a disastrous legacy codebase? When I stopped crying over how bad I had it and started laughing at what I found, I started enjoying my work again. Now, I find I enjoy coming to work and making something beautiful out of something bad. I hope you can, too.
I'm a huge fan of gift certificatesa€‰-a€‰hugea€‰-a€‰and I can't think of a better place for a developer shopping spree than ThinkGeek.