This article is not about something new or unknown; instead we will talk about self-evident things that we forget or leave aside during our routine of consistently delivering new features in the applications we are involved in. There are a lot of excellent sources about how to handle Legacy Code, like the very well known Martin Fowler’s book Refactoring, or Michael Feather’ Working Effectively with Legacy Code.
This article is a piece of knowledge panned from the feedbacks of senior developers who answered questions about Legacy Code, how they feel about it and what approaches they use for handling it. Thanks to our colleagues, Hubert Wójtowicz, Luis Mesa, Fernando Muñoz, and Antonio Cabezas for their answers and a special thanks to Jose Anchieta, for putting the piece together.
The questions asked to everyone were:
- What is legacy code?
- How do you feel about the legacy code of your current project?
- What strategy do you use for legacy code management?
What is Legacy Code?
It’s essential to understand what we are talking about when we say Legacy Code. Legacy Code literally refers to inherited or old code, but the expression is now part of the IT jargon and has specific connotations. Analyzing my colleagues’ answers and thinking about my personal opinion, there are some common characteristics that share what is typically recognized as Legacy Code regarding comprehension of the code, maintainability, and control over the codebase, and it’s our starting point.
Let’s check out some of the common aspects of Legacy code.
The first characteristic, and probably the key one, that seems to be unanimously associated with Legacy Code is the lack of comprehension of the code intent. When the engineering team starts to lose understanding of some piece of the codebase or business domain, it can be time consuming and risky to change any business logic or introduce/refactor some design pattern.
Code clarity has a direct impact on the second characteristic, which is maintainability. If the engineering team perceives the modification of the code base in any way as a high-risk task, then the code is close to impossible to be evolved and this is also associated with the notion of Legacy Code.
This brings us to the last point, the feeling of having lost control over the codebase. Probably many engineers have heard the phrase: “It’s better not to touch that.” It may be the strongest characteristic of a Legacy Code, and the engineering team doesn’t have complete or any control over a piece of code. This can just seem like a feeling, or it can be as transparent as water, depending on the case.
Keep in mind, legacy code is not necessarily old code. You can write some code that is already a piece of legacy code as soon as you push it to your repository.
How do you feel about the legacy code of your current project?
As expected, we don’t have many good things to list about Legacy Code and how we feel about this as software engineers. Three words collected from the answers caught my attention: uncomfortable, frustration, and dissatisfaction.
Thinking about these words and trying to extract their meaning reminded me of a well-known expression: “The elephant in the room”. Sometimes Legacy Code can be just like that, we know it exists but we prefer not to handle that complexity since we don’t have the trust to do it, or we forget about it because “it works”.
This is a simpler case when the Legacy Code doesn’t stop you from doing your work, but there’s another case when the Legacy Code is more like another expression: “A thorn in my side”. But imagine that a specific piece of Legacy Code is stopping you from delivering a feature like upgrading the version of a tool, it happened to me sometimes, and I can not agree more with the words used to describe how these engineers feel about it.
For sure, the good part of this answer was the feeling when these people managed to update or refactor the Legacy Code they were responsible for. A good reflection on this is: Fixing or refactoring gives you knowledge about the codebase and business logic, improves your skills as a software engineer, and provides you more confidence the next time you have to handle something similar.
Which strategy do you use for legacy code management?
Now we have reached the good part of this article, in my humble opinion, as we have a clear vision provided by these excellent software engineers sharing their knowledge on how they approach the management of Legacy Code in the current or previous projects they have worked on.
The first approach is undoubtedly another oneness between them and me as well: tests! Writing automated tests if they don’t exist or improving the test coverage of the most sensitive part is a good start on how to handle Legacy Code, and make sure it will continue to work as expected after refactoring it.
Writing automated tests for a piece of code, legacy or not, gives us confidence and knowledge about the business domain of this code. It’s even better if we can isolate it to write more specific tests based on its functionality. With time these tests could be used as documentation for other engineers or even ourselves in the future.
Minimum Viable Documentation
As mentioned before, documentation is another essential thing we can do about Legacy Code, gathering knowledge about this with people who might have important information about a specific functionality like Product Owners or the people who wrote the code themselves, if it’s possible.
Technical Debt Management
It’s sometimes tempting to want to just drop the Legacy Code and just start from scratch, but well, usually it’s not how it works. As we are talking about Legacy Code from a software engineer perspective, we have to handle our expectations and frustrations about the technical debt (another term that could be related to a piece of Legacy Code) of our projects.
Each engineering team has its way of handling its technical debt. Some of them set aside a specific time for this, and it could be an excellent way to keep the balance between delivering new features and keeping the codebase healthy. Still, it’s a particular approach that each team should decide.
Legacy code is a reality of most applications, and it’s widespread in the software engineering world. There are many ways to handle it. The most important is to set the expectations and frustrations of the team about it and create a plan on how to handle it based on the team’s current scenario.
So, I hope this collection of thoughts helps you to have a better understanding of it and gives you the wish to treat the Legacy Code of your project as a daily task where you don’t need to be afraid of it and can always do something to improve the codebase you work with.
Many thanks again to our engineers who helped us put this article together.