There are multiple approaches to modernizing legacy software. Typically, they are framed as 'the seven Rs:' rehost, relocate, replatform, rewrite, repurchase, retire and retain. While they are all legitimate in the right modernization context, there are nevertheless trade-offs in choosing one over the others.
What this means in practice is that organizations will often select an approach (or combination of approaches) that seems less risky or easier at the cost of future value and long-term business impact. So, while, say, rewriting a legacy system may be the right approach in terms of delivering value, it's often avoided because it's deemed too difficult.
However, it doesn't have to be this way: an approach we call 'test-first modernization' can upend common trade-offs and make it possible to rewrite a system without increasing difficulty or risk.
As you move from conservative tactics like replatforming towards more impactful strategies like rewriting, it becomes harder and harder to verify the similarity in functionality or indeed, whether you’ll be successful. In many scenarios, when it’s not clear if functionalities match or to what extent they do, it can be hard for businesses to take a decision to switch off the mainframe workload or to migrate users off it.
It’s not just about whether the new system works in isolation: it’s about ensuring everything still works together. That can mean extensive integration and regression testing and painstaking efforts to reconstruct the full system around the components that have been modernized. This verification effort is time-consuming and hard to properly scope. In turn, this can make modernization feel riskier, even when the end goal of a rewrite — modern, understandable code and a shedding of technical debt — is clearly better.
That’s why many enterprises are forced into a trade-off between easily verifying similar functionality in code that’s difficult to understand, or the more challenging process of verifying similar functionality in modern, idiomatic code, which will have much greater long-term benefits.
But what if you could break that verification trade-off and harness AI in a way that ensures the work is done properly?
We call this approach test-first modernization. It’s a way to apply AI and automation while keeping humans in control. It’s built around a deceptively simple idea:
Use the behavior of the running system as the source of truth.
You select a single component and capture how it behaves in production as shown through the inputs it receives and the outputs it produces. This behavior inherently includes the interactions with other parts of the system and databases, and it effectively becomes the test harness that defines the expected behavior of new code in concrete terms.
Then this is where AI thrives: you can apply the best-performing AI tooling to generate idiomatic, modern code against the specification. It doesn’t have to be right the first time, because if the output fails the safety harness, the failures are just fed back into the process. In other words, you iterate, refine and repeat until it passes the test — which will sometimes take just a few minutes. For larger and more complex workloads, humans can interject at any point to provide the system more feedback to help it converge to the right behavior.
Once you have behavioral parity, you can run it in parallel with the rest of the system. At this point, you can test it for performance equivalency within the running system. Only then do you retire the legacy component with the confidence that nothing has been lost or broken in the transition.
This ability to embed functional verification directly into the code generation process itself decreases the difficulty and risk exposure of what has traditionally been the most difficult yet most rewarding of the R’s.
This test-first approach offers three big advantages:
Traditional transpilers can create code quickly, but teams end up spending significant time untangling and rewriting that output just to make it usable. Manual rewrites might create better code, but the time and effort it takes is often prohibitive. With test-driven modernization, the code is generated just as quickly, but it comes out idiomatic and functionally equivalent.
Humans are never out of the loop, but they don’t have to do the brute-force labor of hand-writing new code. Instead, AI handles the heavy lifting of code generation, using the tests to converge on the exact output expected. Engineers can step in to review, shape and steer the outcomes.
Because the functional tests are generated from actual observed behavior, they only include what’s actually used. That means unused code paths from decades ago, like the code managing the smoking section of airplanes, don’t get replicated. What remains is not just a modernized system, but one that’s easier and faster to understand, maintain and evolve.
Modernization is hard, and every project is different. But test-first modernization gives you the ease of less-optimal modernization approaches with the much higher value of rewriting a legacy system in a way that minimizes risk and disruption. By applying even the most aggressive, AI-powered strategies in a way that makes rewrites safer and faster than ever before.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique. Duis cursus, mi quis viverra ornare, eros dolor interdum nulla, ut commodo diam libero vitae erat. Aenean faucibus nibh et justo cursus id rutrum lorem imperdiet. Nunc ut sem vitae risus tristique posuere.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique. Duis cursus, mi quis viverra ornare, eros dolor interdum nulla, ut commodo diam libero vitae erat. Aenean faucibus nibh et justo cursus id rutrum lorem imperdiet. Nunc ut sem vitae risus tristique posuere.
Missed part I from this Thoughtworks-Mechanical Orchard blog series? Go here.
Leave a comment
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique. Duis cursus, mi quis viverra ornare, eros dolor interdum nulla, ut commodo diam libero vitae erat. Aenean faucibus nibh et justo cursus id rutrum lorem imperdiet. Nunc ut sem vitae risus tristique posuere. uis cursus, mi quis viverra ornare, eros dolor interdum nulla, ut commodo diam libero vitae erat. Aenean faucibus nibh et justo cursus id rutrum lorem imperdiet. Nunc ut sem vitae risus tristique posuere.
Delete