On Friday I was faced with making some changes to some old code that nobody really understood. Nobody liked to go into this code, so nobody was familiar with it. I too dreaded to make changes to it, and only dipped my toes in it as little as possible to understand what I needed to know.
Well now I needed to understand it better in order to make a bug fix. It turned out to be a good opportunity to learn what this code was doing and make it easier to understand.
Here are some tips for understanding legacy code that is hard to grok:
Step 1. Print out the code.
Sometimes the code you face is so gnarly that you just have to print out the sucker. The code needs to be printed out onto hardcopy so you can lay it out on a table and get a sense of what it is trying to do. So I printed it out. The code itself wasn’t very long – about 10 pages or so – but it was extremely confusing. When I laid the pages out on the table, though, I could start to get a handle on it. I could make connections between the 3–deep class hierarchy – I could see what was overriding what.
Step 2. Tidy up the code.
Tidying up whitespace and fixing the style of the code is a great, low–investment way to get familiar with the code. This is a tip I picked up from the interview with Douglas Crockford in the book Coders At Work (fascinating book of interviews with famous coders, btw):
Seibel: “How do you read code you didn’t write?”
Crockford: “By cleaning it. I’ll throw it in a text editor and start fixing it. First thing I’ll do is make the punctuation conform; get the indentation right, do all that stuff.”
So fix up the superficial things, just so you can start getting your hands (a little) dirty working with the code.
Step 3. Make the code easier for yourself and others to understand.
What I mean here is adding doc, and especially renaming variables, methods, and classes to be easier to grok. For example, renaming $compiled to $configValues made a quantum difference in the understandability of the code, and I made 13 other renames like that. There is power in names – I have a hunch that design is nothing more than the art of precise naming (if you know of a paper, perhaps in linguistics, that backs up that statement, I’d be interested – let me know).
Having printed out the code, tidied it up a little, and especially documented it and renamed things to be easier to understand, I now understood the dragon that we had long feared, and made it grokkable for my teammates as well. I knew how to fix it, what part of the code I needed to change – that took about 20 minutes, including writing a unit test.
It feels good to slay dragons.
What tips do you have for dealing with obtuse legacy code?