Brand New Legacy
In Working Effectively With Legacy Code, Michael Feathers defines “legacy code” as code without tests. I love this definition for two reasons: first, it provides a succinct, objective way to measure whether code is legacy or not; secondly — and this really is the main reason I love it — it asserts that any code, written by anyone, at any time, without accompanying tests, is legacy the moment it’s written.
Well, shit. That means that I’ve personally written rather a lot of legacy code in my life — especially before I started practicing Test-Driven Development. While TDD prevents me from making this conscious and inexcusable mistake now days, that doesn’t retroactively absolve me of the thousands of lines of untested code I’ve certainly written in the past. I’d even bet that a large portion of the legacy code I’ve written is still in use — still causing companies major headaches and heartburn. It might even be costing them major money. They’re having to pay for my lack of professionalism in my craft.
That stings, but here’s the real punchline: if legacy code is defined as code without tests, and making changes to untested code is extremely risky, then making changes to legacy code is, by necessity, extremely risky: a equals b equals c. Now that really sucks, because legacy code is commonly the source of many problems in applications, and consequently, the source of necessary changes and refactorings. Once you have legacy code, you’re already in a tough situation, and there’s not a ton that can be done to really reduce the risk of your [necessary] refactorings. For this reason, legacy code is easier to prevent than to cure, which is to say, if no one wrote any code without tests, there would be no more legacy code, and a huge chunk of the risk involved in the day-to-day maintenance of an application would drastically diminish. Learn from my mistakes, please. For all of us: don’t leave behind a legacy of legacy code.