Modernizing legacy C++ without losing compliance
Refactoring old code in a regulated product is not blocked by the standard — it is blocked by traceability. The strategy that works: small, isolated changes with a clear equivalence argument.
Refactoring old code in a regulated product is not blocked by the standard — it is blocked by traceability. The strategy that works: small, isolated changes with a clear equivalence argument.
This article is the perspective of an engineer who has worked under these requirements, not regulatory advice. For compliance decisions, consult your quality/regulatory specialist.
A lot of the medical software running today is C++ written ten or twenty years ago. It works, it is validated, and nobody wants to touch it. Until they have to: a new requirement appears, a compiler goes out of support, or a library turns up with a vulnerability.
I spent years in this space — real-time imaging components at GE Healthcare and laboratory data system code at Waters. What follows is what I learned about doing it without destabilising everything.
In ordinary software, a good refactor is one that does not change observable behaviour. Under regulation the bar is harder: you must be able to demonstrate that it did not change.
The difference is enormous. “I am fairly confident it behaves the same” is not an argument. You need evidence — the tests before, the tests after, and a clear link between what you changed and what you verified.
This makes large rewrites nearly impossible to justify. Not because they are forbidden, but because the effort of demonstrating equivalence for an entire system is disproportionate.
The usual case: no tests, no design documentation, original authors long gone.
The order that works:
Step 1 is the one teams skip most often under time pressure. It is also the one that costs the most when missing.
When you modify validated code, the question you must answer is: does the result stay the same where it matters?
For numeric code — signal processing, calculations over measurements — this is subtler than it sounds. Reordering floating-point operations can change the last bit of a result. Sometimes that is irrelevant. Other times, if the result crosses a decision threshold, it matters a great deal.
What helps:
The equivalence argument is the artifact that convinces. Without it, you only have a promise.
The principle that helped me most: never mix refactoring with behaviour change.
When the two are mixed, nobody can say what caused a difference, and impact analysis becomes guesswork.
In addition:
From experience, in order of benefit-to-risk ratio:
const-correctness. Cheap, catches errors at compile time, changes no behaviour.What I learned to avoid: enthusiastically adopting every new language feature. Each change must be justified by benefit, not by modernity.
Modernization under regulation is slower, but it is not impossible. It is essentially the same discipline we should apply everywhere — except here it is not optional.
If you have an old system you need to carry forward without destabilising it, that is exactly the kind of problem I have worked on.
GE Healthcare — Voluson Ultrasound
Software Engineer (contract, remote)
Dec 2022 – Jan 2025
Capgemini — client Waters Corporation
Software Engineer (contract)
Jun 2022 – May 2023
If you are building in this space, let us talk for 30 minutes.
Book a call