A pragmatic guide for evolving long‑lived software without ideology, rewrites, or unnecessary pain.
When a system has survived for decades, the question is no longer “How do we replace this?” but “How do we understand and evolve what truly matters inside this?”. These commandments are aimed at making that process more scientific, more honest, and more sustainable.
Old systems accumulate myths. People think they know what parts are used, but reality is often different. Instrumentation cuts through folklore and reveals what actually happens.
Measure things like:
Replace guesswork with evidence before making structural decisions.
Timestamping is one of the most powerful tools in legacy analysis. Over time, it reveals which parts of the system are alive, dormant, or fossilised.
Track, where possible:
After a year, you know what is cold, warm, or hot. After several years, you know what is truly untouched.
Dead code is not dangerous; believing code is dead when it isn’t is dangerous.
A safer process for removal:
This avoids the classic “we deleted that and now payroll doesn’t work” scenario.
Static data belongs in configuration, not in the core engine or orchestration logic. Moving lists, constants, and static rules into configuration:
Your “meaningless words” list is a good example of this principle in action.
Old systems are full of comments like “temporary fix” from decades ago. Intentions age badly; behaviour is what actually matters.
When documenting, focus on:
This is software archaeology: describing what the system really does today, not what someone once hoped it would do.
This is the antidote to purism. When a piece of the system comes into focus because you are working on it, clean it up. Don’t go hunting for theoretical improvements elsewhere.
This keeps the codebase evolving without destabilising it and avoids large, speculative refactors that bring more risk than benefit.
Large refactors are risky in old systems. Small changes are easier to understand, test, and roll back.
Favour changes that:
Evolution beats revolution, especially in systems that people depend on every day.
A system that has survived since the 80s contains knowledge no documentation can fully capture: business rules, edge cases, user expectations, and historical decisions.
Replacing such a system wholesale often destroys that wisdom and replaces it with expensive ignorance. Modernisation should respect and preserve this accumulated intelligence wherever possible.
Logs, metrics, traces, and timestamps give you the map you need to navigate an old system. Without observability, every change is guesswork.
Before adding major new features, invest in being able to see what the system is doing: performance, errors, usage patterns, and unusual behaviour.
A stable system is a rare and valuable asset. Modernising it should enhance stability, not jeopardise it.
The goal is not purity or trend‑compliance; the goal is longevity, clarity, and the ability to keep adapting without breaking what already works.
A system that has lasted for decades has already proven its worth. The task is not to “purify” it, but to keep it supple, understandable, and adaptable. Incremental, evidence‑based changes—guided by real usage and careful observation—are the most practical way to mould old systems for the future.