Author: Gökay KAÇAN, SW Expert / Embedded Systems Group
A legacy system can be defined as outdated computing software and/or hardware that is still in use. Most legacy systems or setups exist due to some reasons such as long-term ongoing projects, support contracts, the difficulty of replacing modern ones due to cost or any kind of limitations.
As technology advances, most software companies find themselves dealing with the issues caused by existing legacy codes. The term “legacy code” refers to code that has been passed down to us from previous developers. Maybe our company acquired code from another company; maybe people on the original team moved on to other projects. Legacy code is somebody else’s code. However, there are some threats and challenges that come with legacy software. So, what are the biggest problems with legacy codes and how can we deal with them?
Online security attacks or threats are increasing every day and they are becoming more serious and harmful. Some vulnerabilities may not be easy to fix due to the incompatibility of the legacy code. Even there is a fix, sometimes it is hard to implement that fix to the legacy code due to the complexity of creating a legacy fix for an old code block. Moreover, since legacy codes are inevitable old, most of the time it may be impossible to update the software with the new security patches due to unsupported functionality. As a result, when the software cannot receive the security updates, the outdated security functionalities could be extremely vulnerable to attack from the outside.
Inefficient and high cost maintenance
Legacy codes can be hard to maintain, improve, and expand since there is a general lack of understanding of the system; the staff who were experts on it have retired or forgotten what they knew about it, and staff who entered the field after it became “legacy” never learned about it in the first place. This can be worsened by a lack or loss of documentation.
Inevitably, you might need to re-train developers on how the legacy system works, which increases a company’s operating costs. Furthermore, managing and controlling changes occurring in the software can be difficult. A lot of time and effort is required to keep the systems operational, which is expensive and time-consuming.
Moreover, if you are working with legacy codes, you probably find the codes very complicated and hard to read. That is probably because of the spaghetti codes. They are messy codes since they have been changed a lot from the first day they have been written. Of course, there are some reasons behind that. The most important of them are cursory bug fixes and special use cases: Somebody patches and apply a special case to the software without a clear understanding of the root cause of the bug and this may cause unwanted behaviors in any other cases and as a result, new bugs may born. And if the developers do the same logic repeatedly on related code blocks, it is unavoidable for the code to become complicated, hard to be read and understood. Thus, nobody will exactly sure how it works, or even how it is supposed to work.
Sometimes, instead of dealing with messy code, you may want to rewrite the code. It is not a bad idea however, there are some reasons why it is hard. The first reason is the cost. Depending on the size of the code, writing can take a significant amount of time and resources. This is the velocity taken away from new features, customer requests and other bug fixes. The second reason is the risk. As far as functionality evolves, it is mentioned before that spaghetti code often comes from the handling of special use cases which weren’t initially considered. Often, these aren’t well documented thus, making them more likely to be missed out on a rewrite.
Incapability to support new technologies
There is a competitive market out there. The competition becomes more difficult since the internet took over the world. Everyone can reach the latest knowledge and resources. Sometimes, we need to apply the latest features to our system. However, when we take a look at it from the software side, if the software does not support the new technologies due to legacy codes, that means integration with newer systems may also be difficult because new software may use completely different technologies.
How do we communicate with the customers if we are stuck using a legacy system? Every customer wants to use new technology. They may not understand whether the software is old or not. They just want to move on with new features. If we cannot support our customers, our competitors may help them with the latest and the newest technologies to fix their problem while we are stuck with our legacy software. At the end of the day, customers won’t stay loyal to us unless we can’t provide them with cheap, quality, fast and newest features.
Ways to work with legacy codes efficiently
Where it is impossible or very hard to replace legacy codes with new ones, it is still possible to enhance them.
The first and maybe the most important way is testing the code. While we may not want to invest time to test legacy code, this will help us and others to understand what the code actually does and prevent the code from other’s improper changes. Michael Feathers who is the writer of the “Working Efficiently with Legacy Code” book says: “Legacy code is code without tests… Code without tests is bad code. It doesn’t matter how well written it is; it doesn’t matter how pretty or object-oriented or well-encapsulated it is. With tests, we can change the behavior of our code quickly and verifiably. Without them, we really don’t know if our code is getting better or worse.” On the other hand, once the unit tests are in place, the code coverage number will increase and hopefully achieve some enterprise’s standard.
Secondly, try refactoring the code rather than rewrite it. Actually, this is one of the best techniques for learning the code. The basic purpose of code refactoring is to make the code more efficient and maintainable. Code refactoring makes the QA and debugging process go much more smoothly. And while it doesn’t remove bugs, it can certainly help to prevent them in the future. Before start the refactoring, of course, we must understand what the code is doing currently, then start refactoring to optimize. In the end, refactoring should not change anything about how the product behaves. One tip that can be taken into account is, we should not do make too many changes at once while refactoring the code. It’s a bad idea to refactor in the same review cycle as functional changes. Plus, this makes it easier for code reviews. Isolated changes are much more obvious to the reviewer than a huge of changes.
Another way is keeping new code clean. If our new codes are clean, which means easy to understand and easy to change, it will be easy to fix bugs in the future. Teams do get better and start to write clean code, but it takes a long time for older code to get clearer which should not be forgotten. While writing a clean code is it takes time, effort, attention and care. All those factors should be taken into account, especially when considering the project delivery.
To conclude, developers must handle and maintain legacy code. We simply cannot afford to ignore maintenance. We must control it until it begins to control us, and when adding new codes, we must remember that today’s code will become tomorrow’s legacy.