Establishing Maintainability Index Metrics

Establishing Maintainability Index Metrics for COBOL Applications

The Maintainability Index (MI) is one of the most widely used composite metrics in software quality measurement. It condenses three structural properties of code, size, complexity, and volume, into a single numeric score that predicts how hard the code will be to change. For modern languages, the formula, thresholds, and tooling are well-established. For COBOL, the situation is more complicated, and most teams either apply the generic formula without adjustment or abandon quantitative measurement entirely because the scores do not seem to correspond to what developers actually experience.

Both approaches produce misleading results. Applying the standard MI formula to COBOL without understanding how its components behave in COBOL’s syntactic context produces scores that are systematically biased in ways that make high-quality programs appear marginal and low-quality programs appear acceptable. Abandoning measurement entirely leaves modernization decisions without the quantitative foundation they need to be defensible to business stakeholders and to prioritize remediation work against a portfolio of thousands of programs.

Get the Full COBOL Metrics Picture

SMART TS XL ranks every COBOL program by complexity, fan-in, and JCL dependency depth simultaneously.

More Info

The correct path is to understand what the MI formula measures in COBOL specifically, where it understates and overstates quality, what supplementary metrics correct for its COBOL-specific blind spots, and how to calibrate thresholds against your actual portfolio rather than against generic benchmarks derived from modern language codebases. This guide covers all four, with enough technical depth to implement a COBOL MI program and enough practical guidance to use it for modernization decisions.

A final point before the mechanics: The Maintainability Index tries to give a holistic view of the relative maintenance burden for different sections of a project by blending together a series of different metrics. That holistic view is valuable for COBOL portfolios precisely because no single metric captures the full picture. MI is the starting point, not the complete story, but the right place to begin.

Why Maintainability Measurement Matters More for COBOL Than for Modern Languages

Measuring maintainability in a Java or Python codebase that is two years old, well-tested, and maintained by the team that wrote it provides useful information but is rarely urgent. The code is legible to its authors. The logic is documented or derivable from tests. Change cost is bounded by the team’s familiarity.

COBOL portfolios in regulated industries are different in three ways that make quantitative maintainability measurement not a quality practice but an operational necessity.

The knowledge gap. Most COBOL contains business logic never formally documented. Batch jobs written decades ago encode rules nobody remembers. The developers who can read the code fluently and estimate change cost accurately are retiring. The developers who remain have partial familiarity with parts of the portfolio. Without quantitative metrics, change cost estimation depends entirely on which developer you ask, and the variability in those estimates is high enough to make project planning unreliable.

The scale problem. A typical COBOL portfolio contains thousands of programs, many of which have not been touched in years. No team can manually assess thousands of programs before a modernization program begins. Metrics that can be computed automatically across the entire portfolio in hours replace weeks of manual review.

The business case requirement. Modernization programs require investment justification. Executives who approve multi-million-dollar modernization budgets want quantitative evidence that the investment is warranted. MI scores, technical debt ratios derived from MI, and change cost estimates that reference MI thresholds provide that evidence in a form that can be presented to non-technical stakeholders.

The MI Formula and Its COBOL-Specific Components

The most commonly used formula for calculating Maintainability Index is:

MI = 171 - 5.2 × ln(Halstead Volume) - 0.23 × (Cyclomatic Complexity) - 16.2 × ln(Lines of Code)

Microsoft’s bounded variant, used by most commercial tools, maps this to a 0–100 scale:

MI (bounded) = max(0, (171 - 5.2 × ln(HV) - 0.23 × CC - 16.2 × ln(LOC)) × 100 / 171)

Each component has specific COBOL-relevant considerations.

Lines of Code in COBOL

COBOL source files contain four divisions: IDENTIFICATION, ENVIRONMENT, DATA, and PROCEDURE. The IDENTIFICATION DIVISION identifies the program. The ENVIRONMENT DIVISION describes its runtime environment. The DATA DIVISION defines its data structures. Only the PROCEDURE DIVISION contains executable statements.

The measurement question: should LOC count all lines across all four divisions, or only PROCEDURE DIVISION statements?

For MI purposes, counting all lines (including data declarations) inflates LOC significantly without corresponding increases in execution complexity. A COBOL program with 400 DATA DIVISION lines defining record layouts and a 100-line PROCEDURE DIVISION has different maintainability characteristics from a program with 100 DATA DIVISION lines and a 400-line PROCEDURE DIVISION, but raw LOC treats them identically.

Best practice: For COBOL MI calculation, use PROCEDURE DIVISION statement count (excluding blank lines, comment lines, and division/section/paragraph headers) rather than total source lines. This produces LOC values that more closely correspond to executable complexity.

The COPY member problem: COPY statements include external source members at compile time. A COPY statement that expands to 200 lines of data definitions contributes one line to the source file but 200 lines to the compiled program. Some tools count logical LOC (post-copy expansion); others count physical source lines. The difference can be an order of magnitude for programs with heavy COPY usage.

Watch out: If your MI tool counts physical source lines, programs with extensive COPY usage will appear smaller and more maintainable than they actually are. Always verify whether LOC in your tool is pre- or post-copy expansion.

Cyclomatic Complexity in COBOL

Cyclomatic Complexity is a code quality metric that measures the understandability and maintainability of code by measuring the number of independent paths through that code. In COBOL, the decision structures that create independent paths include:

COBOL ConstructCyclomatic Complexity Impact
IF ... END-IF+1 per IF
IF ... ELSE ... END-IF+1 per IF (ELSE does not add another path)
EVALUATE ... WHEN+1 per WHEN clause
PERFORM UNTIL condition+1 per UNTIL condition
PERFORM VARYING ... WITH TEST BEFORE/AFTER+1 per VARYING
AT END clause on READ+1
ON EXCEPTION / NOT ON EXCEPTION+1 per exception handler
ON OVERFLOW / NOT ON OVERFLOW+1 per overflow handler
ON SIZE ERROR+1 per size error handler

The 88-level blind spot: COBOL’s 88-level condition names create logical conditions that appear in IF and EVALUATE statements but are defined in the DATA DIVISION. A program with twenty 88-level conditions, each referenced in multiple decision structures, has significantly more behavioral complexity than the PROCEDURE DIVISION’s statement count suggests. Cyclomatic Complexity counts the decision points but cannot capture the semantic relationships between 88-level names and the logic that tests them.

PERFORM THRU implicit complexity: PERFORM SECTION-A THRU SECTION-Z executes all paragraphs between SECTION-A and SECTION-Z. The number of paragraphs, and the decision structures within them, are all part of the effective complexity of the PERFORM statement, but CC calculated at the statement level treats PERFORM THRU as a single path regardless of what lies between.

Halstead Volume in COBOL

Halstead Volume is a measure of the program’s size and complexity based on the number of operators and operands. In COBOL:

Operators are COBOL verbs and keywords: MOVE, ADD, SUBTRACT, MULTIPLY, DIVIDE, COMPUTE, IF, PERFORM, READ, WRITE, OPEN, CLOSE, CALL, GO TO, EVALUATE, WHEN, and so on.

Operands are data names, literals, and figurative constants: data items defined in the DATA DIVISION, numeric and string literals, and COBOL figurative constants (SPACES, ZEROS, HIGH-VALUES, LOW-VALUES).

The verbosity factor: COBOL is significantly more verbose than modern languages for equivalent logic. A Java expression total = quantity * unitPrice * (1 - discount) is one line with four operators and four operands. The COBOL equivalent:

cobol

       COMPUTE WS-TOTAL = WS-QUANTITY * WS-UNIT-PRICE
                        * (1 - WS-DISCOUNT)

This is roughly equivalent in operators and operands, but consider a more complex calculation that in Java might use three lines. In COBOL it may require five or more lines due to the lack of expression chaining and the requirement to use intermediate working storage fields. The Halstead Volume will be correspondingly higher for COBOL than for equivalent Java simply because COBOL expresses the same computation with more language tokens.

The practical consequence: COBOL programs will have higher Halstead Volumes than equivalent-logic modern language programs. Higher Halstead Volume reduces MI. COBOL programs will therefore systematically score lower on MI than equivalent-complexity modern language programs, not because they are harder to maintain but because COBOL is syntactically more verbose.

Where Standard MI Falls Short for COBOL: Four Blind Spots

Even calculated correctly, the standard MI formula misses four dimensions of COBOL maintainability that have significant impact on real-world change cost.

1. COPY Member Coupling

A COBOL copybook included by 300 programs is a maintenance dependency that affects all 300 programs when any change is made to it. This coupling does not appear in any component of the MI formula. A program that includes twenty copybooks has 300 implicit dependencies that MI treats as equivalent to a program with no copybooks.

Supplementary metric: Copy Member Dependency Count, the number of unique COPY statements in a program’s DATA DIVISION. Programs with high COPY coupling require impact analysis before any change to understand which other programs share the same copybook definitions.

2. Fan-In (Called-By Count)

A COBOL subprogram called by 150 other programs is a high-risk change target regardless of its MI score. A highly maintainable subprogram (MI = 85) that is called by 150 programs is harder to change safely than a poorly-maintainable utility (MI = 45) that is called by nobody. The MI formula does not account for how widely used a program is.

Supplementary metric: Fan-In, the number of distinct programs that call a given program via CALL or dynamic dispatch. Fan-in is the primary driver of change risk for subprograms independent of their internal complexity.

3. JCL Dependency Depth

A COBOL program invoked by a JCL job that has fifteen downstream dependent jobs, jobs that run after it and depend on its output, carries operational risk that is entirely outside the scope of MI. A program with MI = 55 that runs standalone is less risky to modify than a program with MI = 80 that sits at the center of a complex batch dependency chain.

Supplementary metric: JCL Dependency Depth, the depth of the downstream dependency chain in the JCL job network. Programs with high JCL dependency depth require broader testing scope for any change, regardless of their internal MI score.

4. Dead Code Inflation

Dead paragraphs and sections, COBOL code that is defined but never called by any execution path, inflate LOC and Halstead Volume without contributing to the maintenance burden of live code. A program with 600 lines of dead code and 200 lines of live code has an MI that penalizes it for the dead code, even though the dead code is irrelevant to change cost.

Supplementary metric: Dead Code Percentage, the proportion of PROCEDURE DIVISION statements that are unreachable from any production execution path. High dead code percentages indicate that the MI-calculated LOC and Halstead Volume are significantly inflated.

A Complete COBOL Metrics Suite

No single metric captures COBOL maintainability. The following suite, used together, provides a complete picture:

MetricWhat It MeasuresCOBOL-Specific NotePrimary Use
Maintainability IndexOverall ease of maintenance (composite)Apply to PROCEDURE DIVISION statements; verify COPY handlingBaseline quality score; portfolio ranking
Cyclomatic ComplexityNumber of independent execution pathsInclude EVALUATE WHEN, PERFORM UNTIL, AT END, ON EXCEPTIONChange effort per program; test case count estimate
Halstead VolumeComputational load (operators + operands)Expect higher values than equivalent modern language programsPart of MI; cross-program comparison within COBOL portfolio
COPY Member CountDependency coupling through shared definitionsPrograms with >15 COPY members require impact analysis before any changeChange risk classification
Fan-In (Called-By)How many programs call this onePrimary driver of change risk for subprogramsMigration sequencing; change authorization threshold
Dead Code %Unreachable procedure code percentageInflate LOC/HV if not excluded; exclude from conversion scopeScope reduction for modernization
JCL Dependency DepthDownstream batch job chain depthNot computable from COBOL source alone; requires JCL analysisOperational change risk; testing scope
Nested PERFORM DepthMaximum nesting level of PERFORM callsDeep nesting indicates structural complexity not captured by CCRefactoring priority

Threshold Calibration for COBOL

Standard MI thresholds are derived from modern language codebases and do not apply directly to COBOL. The table below compares standard thresholds with COBOL-appropriate equivalents and explains the adjustment rationale.

Score RangeStandard InterpretationCOBOL InterpretationRationale
85–100Highly maintainableHighly maintainable (consistent)Best COBOL programs score in this range, clean structure, appropriate size
65–84Moderately maintainableModerately maintainable, review COPY coupling and fan-inStandard threshold holds, but supplementary metrics matter more here
50–64Poor, refactoring neededMarginal, assess in contextMany well-structured COBOL programs score here due to verbosity alone; use CC and fan-in to distinguish real problems from syntax artifacts
25–49Very poorPoor, likely high CC and/or excessive LOCPrograms in this range reliably indicate structural problems, not just COBOL verbosity
0–24Critical, major refactoringCritical, highest priority for remediation or retirementConsistent with standard interpretation

Key calibration guidance: Run MI across your entire COBOL portfolio before setting program-specific thresholds. Calculate the portfolio median and interquartile range. Set your “attention required” threshold at the 25th percentile of your own portfolio, programs in the bottom quartile of your specific codebase, not programs that score below a threshold derived from Java programs. This approach is self-calibrating and accounts for the systematic COBOL verbosity effect.

Using MI for Modernization Decisions

MI scores become most valuable when they inform specific operational decisions. Here are the primary applications.

Migration wave sequencing. Programs with high MI scores (well-maintained, low complexity) are the best candidates for early migration waves. They are easier to validate, less likely to contain undocumented edge cases, and carry lower risk of producing unexpected behavior in the migrated environment. Programs with low MI scores should migrate in later waves, after the team has built experience and confidence, and after thorough business logic extraction.

Maintenance prioritization. Programs with MI below the 25th percentile that are also high fan-in (called by many programs) or high JCL dependency depth represent the highest-risk combination: structurally complex programs that many other programs depend on. These are the programs most likely to produce change-related defects and most expensive to remediate when they do. They should be the first targets of a technical debt reduction program.

Build-vs-buy decisions. When evaluating whether to maintain a COBOL program long-term or replace it with a SaaS or modern alternative, the MI score and change cost history provide the quantitative basis for the build-vs-buy calculation. A program with MI = 30, modified fifteen times in the last three years, with each modification taking significantly longer than estimated, has a documented maintenance cost that can be compared against the cost of replacement.

Change authorization thresholds. Some organizations use MI scores to determine the level of change authorization required. Programs below a certain MI threshold require more rigorous review, independent testing, and additional sign-off before production deployment. This creates a quality-aware change control process without requiring manual assessment of every change.

The one thing MI cannot do: predict the business impact of a change. A program with MI = 85 that performs regulatory capital calculations requires at least as much testing and validation as a program with MI = 40 performing a low-stakes reporting function. MI measures change effort, not change consequence. Both dimensions are required for a complete risk assessment.

How SMART TS XL Establishes and Tracks COBOL Maintainability Metrics

Computing MI for a single COBOL program is straightforward. Computing it accurately for a portfolio of thousands of programs, accounting for COPY expansion, identifying dead code, and supplementing MI with the additional metrics it misses, requires automated analysis at scale.

SMART TS XL’s static code analysis computes the full COBOL metrics suite described in this guide across the entire portfolio simultaneously. MI is calculated using PROCEDURE DIVISION statement counts rather than total source lines, with COPY expansion performed before analysis to ensure that shared data definitions are correctly attributed. Cyclomatic Complexity accounts for EVALUATE WHEN clauses, PERFORM UNTIL conditions, and exception handler branches, not just IF statements. Halstead Volume is computed from COBOL verbs and data operands in the PROCEDURE DIVISION.

Crucially, SMART TS XL supplements MI with the metrics that the formula misses. The application dependency mapping produces the fan-in values, called-by counts, for every program in the portfolio, identifying high-risk programs regardless of their MI score. The JCL expansion capability provides the JCL dependency depth for every program, connecting the COBOL-level MI analysis to the operational risk context that only JCL analysis can reveal.

Dead code identification from the impact analysis capability flags paragraphs and sections with no inbound execution paths, enabling the exclusion of dead code from MI calculation and providing the dead code percentage metric that determines whether a program’s low MI score reflects genuine complexity or inflated LOC.

The enterprise search capability makes the complete metrics dataset queryable: find all programs with MI below 40 and fan-in above 20, sorted by JCL dependency depth, the highest-priority remediation targets in the portfolio, in a single query across millions of lines of COBOL. This queryable metrics inventory is the foundation for the maintenance prioritization, migration sequencing, and change authorization applications described above.

Finally, MI tracked over time, recomputed after each significant change cycle, shows whether the program is improving or degrading. SMART TS XL’s analysis is run on current source rather than cached snapshots, ensuring that the metrics reflect the actual state of the codebase at the time of each analysis rather than a point-in-time assessment that drifts out of date.

Metrics That Match the Language

The Maintainability Index is a valid and valuable metric for COBOL portfolios, but only when applied with an understanding of how COBOL’s syntactic characteristics interact with its components. Applying generic thresholds to COBOL programs produces misleading results. Supplementing MI with the metrics it misses, COPY coupling, fan-in, JCL dependency depth, dead code percentage, produces a picture that corresponds to what developers actually experience when working in a COBOL portfolio.

The organizations that use these metrics effectively are the ones that treat them as a starting point for informed conversation, not as a final verdict on program quality. An MI score is a signal. The signal is worth following, it consistently points toward the programs that are expensive to change, risky to modify, and worth addressing before modernization begins. What MI cannot do is replace the judgment of a developer who reads the code, or substitute for the structural analysis that reveals the dependencies and business logic that no single metric can capture.