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.” Originally, it even meant code that runs on platforms that are no longer supported.
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.
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
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 goes 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, or never learnt it. Or worse, 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, which we’ll get into later. But more importantly, they will have to test things manually, which is a lot slower 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 of the above applies.
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. Now a break is necessary and useful now and then, but not constantly or when the developer is feeling productive.
The stereotypical developers is someone that wants to use the newest and most shiny technology. Use what’s hip and cool at the moment. Unfortunately, this changes every month or so. Definitely 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 it can also be because 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.
Again, there are various strategies to deal with bad quality code. Those are out of scope for this article, but I will touch on them later.
Understand Your Developers
Now you should have a fair understanding of what developers mean when they talk about legacy code. It’s code with little 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 their 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.