Progress powers technology forward. But progress also has a cost: by adding new capabilities and features, the developer community is constantly adjusting the building blocks. That includes the fundamental languages used to code technology solutions.
When the building blocks change, the code behind the technology solution must change too. It’s a challenging and time-consuming exercise that drains resources. But what if there’s an alternative?
The problem: reading code someone else wrote
Let’s take a step back and take a look at one of the fundamental challenges in development: editing someone else’s code. Editing code you just wrote, or wrote a couple of weeks ago, is just fine. But editing your own code written years ago – never mind someone else’s code – that’s a different story.
In-house code style rules can help but there are always odd naming conventions for variables and functions, or unusual choices for algorithms. Arguably, a programmer’s ability to read code is a key skill – but it’s tough for everyone.
Developers call the process of editing old code “refactoring” and it’s a process that commonly introduces new bugs or performance problems. So that’s why, going back and editing old code, well – that’s the last thing most development teams want to do, particularly when the existing code base is running stable and doing its job.
It’s a real headache, but sometimes there’s no alternative
Refactoring is something every developer wants to avoid for as long as possible because it can feel like a waste of time. Nonetheless, developers must refactor from time to time for a variety of reasons, and one of the most common reasons is due to changes in developer building blocks.
That includes changes to the programming languages used to build software, which inevitably evolves over time. New versions of a language will often deprecate old ways of doing things while introducing new features. If developers don’t adopt the new language version, they’re excluded from the new feature set.
However, existing code usually needs adjustment to run on the new version of the language, and that implies a refactoring process. And that’s the conundrum: to adopt the new, more advanced version of a language developers need to refactor, and along the way they’ll spend a huge amount of effort – and break all sorts of unexpected things, introducing new bugs into an application that was running just fine.
Worse, refactoring alone doesn’t give you the advantages of the new language version, instead you need to redevelop your codebase to tap into improvements. Otherwise, despite adjusting the code to fit the new language version, you’re just where you used to be: a codebase running on a new language version, but with no new features.
Vendors commonly leave end users to deal with it
It can seem like a pointless exercise but, with the steady march of technology change, there’s often little choice in the matter – with your technology partners choosing for you.
Let’s say we’ve just moved from Python 2.7, to Python 3.0. If you’re developing your applications in-house, you’re in full control and can make the shift, or not make the shift. Developers, on the other hand, may well decide to leave things be. If an app is developed for and runs on Python 2.7, the developer will just leave it at that – and tell users an app was developed for Python 2.7, with no support for other versions.
It can leave users in a tough spot – stay on the older version of Python 2.7 to accommodate the application, leaving behind progress, or switch to Python 3.0, and risk a range of incompatibilities with apps.
The net result: a major security risk
Programming languages (and their assorted libraries) are not immune to security vulnerabilities. When these vulnerabilities do come up, a language version upgrade can be forced on you by the developers.
But these upgrades will not be limited to simple bug fixes – they will bring along deprecation of language constructs with new constructs brought in, and that will force developers to go through the motions of doing changes to existing code, again with all the potential issues that brings.
The situation gets even worse when you think about the compounding effect of included libraries. After language changes these libraries must be updated too – but if one of the libraries in use is not updated by its authors, the developer won’t be able to use it after upgrading the rest of the code to a more recent version, again leading to more code writing.
It’s easy to see where it all leads: more effort, additional risks of introducing bugs… and a reluctance to carry on refactoring to accommodate updates. Next? The updates simply don’t get done which means that workloads rely on insecure, outdated building blocks.
The story is similar to what we see play out all over the technology world, as old and vulnerable building blocks leave the door open to cyberattacks. There is, however, some good news emerging.
Is there a better solution?
Take unsupported operating systems, for example. In the past, when an OS reached end of life, the only choice was to upgrade to a newer OS – a major investment, and full of risks. The net result is that many organizations rely on unpatched, unsupported operating systems even for critical workloads. If you don’t have updated applications, because developers won’t refactor old codebases, you can’t move your applications to newer operating systems that don’t support the old versions of the language – and thus break the application.
Thankfully, this scenario changed as end of life support is now a reality for many Linux operating systems, which means that organizations can buy time to migrate away from an unsupported OS to an OS with official vendor support, without taking any security risks.
Can something similar be done for language versions? A way to effectively “upgrade” a language runtime with the latest security fixes while at the same time not changing how that specific language version or libraries otherwise work, thereby removing the need to refactor?
Repeating what’s been achieved for operating systems and applying it to language versions will give developers enormous breathing room, reducing the need to continuously refactor. In turn, there’s a higher probability that workloads run safely and securely.
Is it possible? Well, what was achieved for operating systems can be expanded to other areas. Watch this space.