Legacy Code – costs you a hell of a lot of money
Have you ever stopped to think about how Legacy Code impacts your time & money? How it impacts your products’ quality, hence, your customers? How it affects your employees?
In this article I will try to cover the bad impacts of Legacy Code, impacts that actually cost the organization money and quite a lot of it. Mainly, it will not be based upon some empirical data, nor academic observations, instead, it will be based on pure common sense and our personal experience as mentors of dozens of teams along the years.
Great, so what is Legacy Code?
The definition of Legacy Code
In his book, “Working effectively with Legacy Code”, Michael Feathers tries to give a formal definition of Legacy Code:
To me, Legacy Code is simply code without tests
For those of you who ever worked with Legacy Code, this might sound strange – you know intuitively, that Legacy Code is simply a rotten code. Well, you’re right, but Feathers’ definition is still correct though, when a code is not covered by tests – it’s rotting. Why is it exactly?
Uncle Bob explains this very elegantly in one of his lectures on youtube:
How many of you, have looked at a piece of code on your screen and your first thought is: “my God, this is a mess, someone needs to clean it”. And your second thought is: “It’s not gonna be me. I am not going to be the one to clean this code. Because I know that if I’ll clean it, I might break it, and if I’ll break it – it will become mine…” So you walk away from this code, you will not touch it. This is why code rots.
The impacts of Legacy Code
Now that we understand what a Legacy Code is and what causes it, let’s talk about its worst impacts.
Long tests during development
Think about a code that you’re working on, and it’s not covered by tests. If you’re a programmer with good instincts, then you’ll probably stop every few lines you add or edit, to test what you just did. If you don’t have unit tests in place, then you’ll have to run the whole application to test your last changes, over and over again. Each run consists of:
- Compiling (in static typed languages of course)
- Then running the application, which most of them have some initialization phase.
- Then most of the times you go through a login step
- Then step over a few screens by a few clicks and sometimes by filling some data
- Once you’re in the screen you need to test, you need to do some regression tests on this screen just to make sure you haven’t broken anything.
Think about it, this process I just described takes half a minute at best, but I think that in most cases it takes not less than 2 minutes. But remember, as a good programmer, you ran this process every few lines you change – this means dozens of times during the day. Do the math and you will see that these manual tests consume a big portion of your time, I would say around 1 hour per a day of work (8.5 hours).
Unit tests can reduce this by an order of magnitudes.
Long development time
- Since the code is rotten, it’s probably not clear enough (the understatement of the year), and when a code is not clear enough, developers spend a lot more time on trying to understand it.
- A rotten code is also fragile and since the code is unclear and fragile, developers spend more time on testing – just to be on the safe side (if they don’t, then the product is in danger)
- A rotten code is also very rigid. When the code is rigid, developers spend more time on almost every change they do, trying to fit in their change.
Long QA time
- Since there are no automated tests, the QA process is manual and consumes quite a lot of time (human hours instead of machines)
- Since the code is fragile, more bugs sneaks into QA and the number of QA cycles is getting bigger.
Low quality product
- When the code is rigid and not reusable, developers often have no other choice but to duplicate pieces of code. When there are code duplications, it isn’t a question of whether you’ll remember to update all of these duplications when needed: it’s a question of when you’ll forget to update one of them. Once you forget – you produce a bug.
- When the code is fragile and unclear, more bugs are being produced at development time. The more bugs are being produced at development time – the more bugs get to QA. The more bugs get to QA – the more bugs sneak into production. The more bugs sneak into production – the lower the quality of your product.
- Often, in a Legacy Code environment, the Continuous Integration is partial or doesn’t even exist. By the way, having a build server, Jenkins or alike, doesn’t necessarily mean Continuous Integration. A build server is just a tool, Continuous Integration is a discipline.
Anyway, when that’s the case, developers commit their changes quite rarely and in large bulks, which leads to hard, risky merges that consume precious time and might produce bugs.
- When the development cycles are longer, the less releases you have in a given period. The less releases you have in a given period – the less happy your customers are.
- When the code is rigid, fragile, unclear and not covered by tests, you’ll find yourself too often saying ‘no’ to customers’ requests.
- The lower the quality of your product – the less happy your customers are.
The impact on your employees
Good employees like to be part of a winning team. StackOvervlow made a survey that shows an obvious correlation between job satisfaction and checking in code. The more frequently developers are checking in code, the more satisfied they are. Meaning, developers like to work in a fluent, agile environment and Legacy Code isn’t that environment.
When your employees aren’t satisfied, the retention rate drops. Moreover, it will become harder and harder to find new good employees.
If your code can be defined as Legacy Code, keeping the status quo is nearly not an option.