Do you often hear your developers talking about legacy code? Most likely in a negative fashion? Let’s take a moment to look at what legacy code is and what developers mean when they mention it.
There is no “official” definition of legacy code. Michael Feathers defines it as “code without tests” in his book “Working Effectively with Legacy Code.” Others talk about “code inherited from others,” or applications that run on unsupported platforms.
I believe that neither of these definitions are what most developers mean when they talk about legacy code. While these can be characteristics of said legacy code, they don’t define it as being legacy code.
It’s perfectly possible to have an application that runs on supported platforms, is still maintained by the original developer, and has automated tests, but still have it regarded as legacy.
Every developer will define the term legacy code differently, yet they will know what they’re talking about among each other. So rather than try to formulate a definition, I would like to list some characteristics of legacy code:
- There are no or not enough automated tests
- The automated tests are of bad quality
- The code uses old technology
- The code is of a bad quality making it hard to maintain or change without introducing subtle bugs
- There is no documentation or it lacks in quality
Let’s dive into each of these in detail.
Insufficient Automated Tests
Even in the early days of programming, developers wrote tests to check their code. Given a certain input, they hand-calculated the expected output and then wrote their code until they received the same result.
This dates back to the 1950’s. Computers and applications have become exponentially more complex since then, so you would think we would have increased our usage of tests. Unfortunately, many developers seem to have forgotten this technique, never learnt it, or just don’t like it.
One thing that has changed since then, is that we now have improved techniques. Current technology allows use to write our tests in code and run them automatically.
Having automated tests allows us to be sure that changes to the code doesn’t break anything that used to work. It provides many more benefits, but for the sake of legacy code, the safety net that automated tests provide is the most important one.
Without automated tests, developers lose confidence and become nervous when they change code. A professional developer doesn’t want to introduce new bugs. This leads to stressful moments when an end-user makes a support call and the bug must be found and fixed ASAP. Developers especially want to avoid these situations at night.
When the code doesn’t have enough automated tests, your developers will tread slowly and carefully. They will change as little code as possible, which stops them from improving any code. This in turn leads to more technical debt.
But more importantly, they will have to test things manually, which is a lot slower and more expensive than automated tests. It’s also more error-prone. They can easily forget specific edge-cases. Or they could interpret the results incorrectly.
Developers will work to the best of their ability. But the absence of automated tests can severely hamper their ability. And the developers realize this. They won’t have a lot of confidence when they have to release the new feature to production.
Over time, this can also have a detrimental effect on morale. In a market of high shortage of developers, you want to avoid this.
Bad Quality Automated Tests
This is linked to the previous issue. An application might have a lot of tests, but if they lack the necessary quality, they are of little to no use to a developer.
One aspect of quality is whether or not the tests provide confidence to the developer to make changes to the code. If the tests don’t test the behavior of the application well, then they’re useless and all the problems of our previous issue remain valid.
Another aspect is determinism. Tests should always lead to the same results, given the same input. If they don’t, developers can’t rely on them for their safety net.
A final aspect is speed. Automated tests should give the developers fast feedback of their changes. If they have to wait 30 minutes to know if their change broke anything, they will become frustrated and unhappy. They will almost always start slacking, go talk to a colleague, or surf the web. Of course, a break is necessary and useful now and then, but not constantly or when the developer is feeling productive.
The stereotypical developers is someone who wants to use the newest and most shiny technology. Use what’s hip and cool at the moment. Unfortunately, this changes faster than your application can change.
Personally, I don’t mind working with older technologies. But it is a characteristic of code that puts it into the legacy code “bucket.” And while professional developers realize that there is still a lot of work in older technology, it is true that they like working with newer tech.
Tackling this can be an article of its own. But for now, suffice to say that software development can also be fun, educational and efficient in older technologies.
With the correct techniques like automated tests and deployment, and with the correct attitude like continuous refactoring, you should not need to worry too much about using older technologies. Though you must realize that your company will have to have a migration path somewhere in the future.
Bad Quality Code
What is quality code? Quality code is code that is easy to maintain, easy to change and easy to read. Many pieces of legacy code are often hard to read. When it’s not the original developer on the job, this makes the code harder to change without introducing subtle bugs. This can even be the case when it is the original developer.
Code can often lose its quality over time. This can be because small changes are introduced that make the code a little bit worse step by step. Each change didn’t mean a significant deterioration by itself. But over time the cumulative effect of all these changes can put the code in a very bad state. This is a process often called “code rot.”
But code can also become “bad quality code” almost overnight. This happens when standards change. What is a perfectly acceptable way of coding now, can be regarded as an ugly, legacy way of writing code in 10 years time.
Documentation comes in many forms. It may even be oral, i.e. a developer that the team can talk to when they have questions about the code. But if there is no or not enough documentation on how the code works, this will be detrimental to the productivity of your team.
Too much documentation can be bad too. Good documentation is easy to find, explains things clearly, without going on about details too much. This is important because if there are too many details, the documentation risks becoming out of sync with the code.
This is bad quality documentation and leaves developers puzzled: is the documentation wrong, or is the code wrong and do we have a bug on our hands?
A good developer not only knows how to code, but also knows how to communicate to other developers about the code he or she is writing.
Understand Your Developers
Now you should have a fair understanding of what developers mean when they talk about legacy code.
It’s code with few quality tests, using outdated technology, and often lacks in quality. It’s code that developers don’t like touching because they don’t have enough confidence that they won’t introduce any bugs.
This is regardless of experience. In fact, the lesser experienced developers will often have more confidence. They haven’t learned the hard way how subtle bugs can be introduced and lead to an unpleasant support call at night.