Home About References

Use Cases

Articles Interactive Survey Members Area

Why Dead-Code Discovery Matters Before Migration or Refactoring

The question is not only what looks unused, but what the system still depends on.

A modernization plan often begins with an attractive idea: do not migrate what the business no longer uses.

That idea is sensible. Large legacy estates carry old programs, copied routines, duplicate layouts, retired screens, report paths, batch steps, utilities, test harnesses, migration leftovers, and business rules that may no longer be active. Moving all of it into a new platform or refactoring all of it in place can waste budget and make the target system harder to understand from day one.

The difficult part is the word "unused."

A COBOL program may not have been changed for years and still run in a monthly batch process. A copybook may look redundant until one rarely used path includes it. A JCL step may create a file that a downstream team quietly depends on. A report may be generated for a small operational process that never appears in the modernization diagram.

Dead-code discovery is not a license to delete faster. It is a way to make retirement decisions with better evidence.

At ITP Software, this is one reason we position Panorama as a code-comprehension and software-intelligence tool for large legacy and enterprise systems. Before code is excluded from migration scope, removed, rewritten, or left behind, reviewers should understand the relationships around it.

Why Dead Code Is Hard To Prove

In small systems, unused code may be obvious. In large enterprise systems, absence of attention is not the same as absence of use.

Legacy estates often contain COBOL, PL/I, Assembler, C, Java, JCL, CICS transactions, DB2 or IMS access, files, reports, copybooks, screens, schedulers, and external interfaces. Some paths run every day. Others run at month end, year end, during exception handling, after a regulatory change, or when a specific product, region, customer segment, or operational event appears.

That makes dead-code discovery more than a source-code search.

A reviewer may need to ask:

  • Is the program called directly or indirectly?
  • Is it referenced from JCL, a transaction, a scheduler, a report, or an operational procedure?
  • Does it read or write a file, table, queue, or shared data structure still used elsewhere?
  • Is a copybook, field, routine, or interface shared with active components?
  • Is the code genuinely unreachable, or just outside the most common path?
  • Which findings are supported by system evidence, and which require a human decision?

The last question is essential. A tool can help reveal evidence and candidates. It should not pretend that every retirement decision is automatic.

Wondering how ready your legacy systems are for change? Take a look at our Code Comprehension Readiness Check and find our within minutes.

Migration Scope Can Grow From Old Assumptions

Dead-code discovery matters before migration because migration scope has a habit of hardening early.

If the initial assessment says "all COBOL programs move," the project may spend time converting code nobody wants in the target estate. If the assessment says "these components are obsolete" without enough evidence, the team may discover a hidden dependency later, when schedules and budgets are already committed.

Both mistakes are expensive in different ways.

Migrating unnecessary code increases the amount to convert, test, document, secure, and maintain. Removing necessary code creates production risk, rework, and uncomfortable explanations. The better question is not whether the estate contains dead code. Most long-lived estates do. The better question is how confidently the organization can classify it.

What Useful Evidence Looks Like

A practical dead-code review should combine several views of the system.

Structural relationships

Calls, includes, shared definitions, imports, references, and cross-references help reviewers see whether a component is connected to active application structure. This is where a candidate that looks isolated may turn out to sit behind an indirect relationship.

Operational relationships

JCL, batch flows, schedules, CICS transactions, runtime configuration, reports, and operational scripts can keep code alive even when source-level references look thin. Migration planning that ignores these relationships can miss the way work actually runs.

Data relationships

A field, file, table, queue, or record layout may connect old and new components. Data-flow analysis is especially useful when code appears dormant but still produces, changes, validates, stores, or exports information used elsewhere.

Human and business confirmation

System evidence is the starting point. People who understand month-end processing, exception flows, product variants, compliance reporting, and operational history still matter. Dead-code discovery should help them review a better candidate list, not replace their judgement.

How Panorama Fits Into The Review

Panorama helps organizations investigate large legacy and enterprise codebases across languages, dependencies, cross-references, data movement, and supporting artefacts.

In a dead-code review, an investigation might start with a suspected unused program, copybook, data item, JCL job, transaction, report, file, or interface. From there, reviewers can examine related programs, shared definitions, database access, batch flow, CICS connections, DB2 or IMS usage, PL/I or Assembler links, C utilities, Java consumers, and downstream relationships.

The output should not be a simplistic keep-or-delete list. A more useful result is a set of candidates with supporting evidence, open questions, and review notes:

  1. Components with no obvious active relationships that may be retirement candidates.
  2. Components that looked unused but still have dependencies.
  3. Components that require operational or business confirmation.
  4. Components that should stay in migration or test scope until the evidence is stronger.

That distinction matters. It keeps the modernization conversation grounded in what the system shows, while leaving room for experienced people to decide what the evidence means.

Refactoring Has The Same Problem

Dead-code discovery is not only a migration issue.

Refactoring a large legacy system can be just as risky when unused-looking code is misunderstood. A cleanup project may remove a conditional branch, generated module, old interface, or shared data structure because it looks stale. The change may pass ordinary tests and still break a rare path later.

The safer approach is slower at the beginning and cheaper later: identify candidates, trace relationships, check data movement, review runtime and operational context, then decide whether removal, isolation, documentation, or continued monitoring is appropriate.

Sometimes the right answer is deletion. Sometimes it is documentation. Sometimes it is leaving the code in place until a better test, runtime signal, or business answer is available.

A Practical Starting Point

Start with one migration or refactoring boundary.

List the components proposed for retirement or exclusion from scope. For each one, check structural references, operational usage, data relationships, and cross-language paths. Mark what is confirmed, what is uncertain, and what needs subject-matter review. Use that evidence before estimating conversion effort, deleting code, or promising a smaller target estate.

This is not glamorous modernization work. It is the work that prevents an apparently tidy plan from carrying old uncertainty into a new platform.

The goal is not to keep every line. It is to retire the right code for the right reasons.

Let’s have a chat about your legacy system.

We’d love to learn more about the systems you maintain, the risks or bottlenecks you’re navigating, and where Panorama could help you understand, modernize, and change them with more confidence.