Ask your average developer what they think of legacy code (go on, try it), and you’ll likely get some sort of groan before a further response. Legacy code is the term usually used to brand code that hasn’t been consistently maintained and upgraded, becoming undesirable, complex, and hard to improve. These systems, while often serving critical business needs, become incredibly difficult to change due to technical debt, a feature-only focus, an outdated model for ongoing development, and too much deferred maintenance.
Legacy code is everywhere, and it’s here to stay. As Scott (CEO of Corgibytes) says on the Legacy Code Rocks! Podcast- anything that someone else has left behind is their legacy. After a while, what they left behind might not play nicely with new code that has been added since then. Several key issues can come into play with legacy codebases, ranging from ticking time bomb red flags and alarming security vulnerabilities, through to frequent bugs and plummeting developer productivity.
Upgrades and tasks associated with overall code modernization can be hard work and do carry risks, so teams often put them off as long as possible.
An outdated codebase is not a secure one
Open source software is recognized to be plagued by far more security vulnerabilities than closed source software, which makes an outdated codebase even more dangerous. In their 2020 Open Source Security and Risk Analysis Report, Synopsys found that 75% of codebases surveyed contained vulnerabilities, with 50% of codebases containing high risk vulnerabilities! This allows hackers to exploit vulnerabilities for common dependencies that are used by thousands of companies in their products and applications - an infamous example of this was the Equifax breach, enabled by a vulnerability in Apache Struts.
Why is it such a common story that dependencies are the reason applications get attacked, and why aren’t systems getting upgraded more consistently?
In his talk, A Deep Dive into Measuring Dependency Freshness with Libyear, Scott identifies some of the major drivers behind this never ending uphill battle:
- Fear: upgrading might cause a breaking change, which will intro a bug, or there might be new bugs (in addition to bug fixes) in the new version. Developers might have also heard stories, bordering on myth, of how the last person to attempt an upgrade “nearly brought the entire system to its knees”
- Time: keeping dependencies up to date is not only challenging, but requires serious time and commitment
- Priorities: modern software teams face constant demands, and keeping dependencies up to date is often not one that they have a lot of time to devote to (usually, things such as new features, fixing bugs, and responding to user concerns win out)
- Difficulty: real or perceived, upgrading dependencies is not easy, especially if the libraries you’re targeting are changing or moving often, and may not be supported for very long
- Invisible problem: dependencies, and how out of date they are, are largely invisible to a lot of dev teams, as well as the people typically responsible for footing the bill for various software projects.
Modern codebase, happy dev team (and, your bottom line!)
A clean, workable and consistently maintained codebase will keep your developers happy - an oversimplified statement that implies tons of increased productivity, and rapid releases for new features, which, in turn, directly affects your customers, internal departments, and bottom line.
It’s not just about a happy dev team, though. The fact is, once a codebase reaches a certain state of legacy (this doesn’t necessarily mean “old,” but rather refers to its inherent complexity), only very senior developers, or the original developers who built the system, can even understand it (read: untangle the ball of extremely knotted string that your codebase has become). This inherent lack of accessibility and workability introduces further strains and slowdowns to businesses, at a time when it is crucial to scale, release new features, and serve customers.
Maintenance and modernization save the day!
Doing dishes and laundry regularly ensures a generally orderly (and habitable) house, and avoids the alternative - of creating a hazardous waste zone! Likewise, if you simply stay on top of your codebase, the “dreaded” tasks that are challenging and slightly monotonous today, will not become unbearable and in some cases, impossible - a few months or years from now. This means regularly upgrading dependencies, patching security vulnerabilities, keeping test coverage high, documenting often and thoroughly, and paying down technical debt.
What does “modernization” really entail, anyway?
Modernizing a codebase is by no means a one size fits all exercise. The systems you have in place, how and when they were built, how large, custom and complex your applications are and the functions they support, all influence how and when codebases need to be modernized.
Efforts to modernize could entail version upgrades (if you’re on Python 2, you’d better be thinking about this now!), migrations between languages or frameworks (i.e. Struts to Spring, or VB.NET to C#), migrating from a monolith to microservices, and along the way, paying down technical debt (by implementing best practices like TDD and CI/CD, and removing dead and redundant code).
Slow and steady wins the race (and pays down technical debt)
Modernizing your codebase doesn’t have to happen overnight, and it shouldn’t. Gradual, incremental changes, applied consistently and continuously over time, are what will keep your codebase in a healthy, secure, scalable and maintainable state. This allows you to minimize risk by spreading changes out over several releases, and makes isolating issues much easier when things do go wrong.
Start where you are
There is no shame whatsoever in having or working on a legacy codebase. Remember- once the code gets pushed to production it instantly becomes legacy code! With thousands (if not tens of thousands) of new software businesses starting each month, it is simply a fact that the number of legacy codebases in existence is steadily increasing.
Legacy code that’s hard to maintain and that has security vulnerabilities can be a nightmare both for businesses that have to use it and for developers who have to deal with it. The first, and often most important, step in beginning a modernization strategy, or any upgrade, is to determine if change is really warranted, decide on the approach most appropriate for your business, and commit for the long term. At Corgibytes, we refer to this as the decision to rewrite or to remodel.
As with many of life’s less desirable processes, getting started is truly half the battle. So, start where you are. Eliminate the shame and headache that goes with having a messy codebase. Embrace that your system is worth investing in and start making it better from where you are today.
If you feel stuck, don’t know where to begin, or simply want to talk through some of your frustrations around legacy code, we are glad to have that conversation with you. As genuine lovers of legacy code and true menders, Corgibytes’ team would be delighted to help you start modernizing!