Skip to main content

Core analyzer

Maintainability Index

Composite 0-100 score (Oman & Hagemeister) combining cyclomatic complexity, Halstead volume, and lines of code.

technical-debt core-maintainability

Maintainability Index

Composite 0-100 score (Oman & Hagemeister) combining cyclomatic complexity, Halstead volume, and lines of code.

The Maintainability Index, formalized by Oman & Hagemeister (1992) and standardized through Microsoft Visual Studio's Code Metrics, captures three independent drivers of maintenance cost in one number: control-flow complexity (cyclomatic), expression density (Halstead volume), and sheer file size (lines of code).

The formula MI = 171 − 5.2×ln(V) − 0.23×CC − 16.2×ln(LOC), scaled to 0-100, weighs LOC most heavily — large files are the most predictable drag on maintainability — followed by volume, then complexity. The composite is more stable than any individual metric: a file can game cyclomatic complexity by inlining branches, but the volume and LOC terms will still penalize the resulting density.

Severity guide

info
Rating A or B (>65). File is maintainable with normal review effort.
warning
Rating C or D (10-65). Changes carry meaningful risk; proactive refactoring recommended.
critical
Rating F (<10). File is at the most difficult end of the maintainability spectrum; immediate decomposition advised.

Examples

Before

// 600 LOC file with 15 cyclomatic and dense expressions throughout
export function orchestrate(input, opts, ctx) {
  // ... many nested branches and inline transformations
}

After

// Decomposed into focused modules
// orchestrate.ts (80 LOC, cyclomatic 5)
// parse-input.ts (60 LOC, cyclomatic 3)
// apply-transformations.ts (80 LOC, cyclomatic 4)
// format-output.ts (40 LOC, cyclomatic 2)

Splitting a single large file into focused modules reduces each module's LOC and complexity components below their penalty thresholds, lifting the overall MI score from F into B or A territory.

Remediation

Identify the dominant penalty component (volume, complexity, or LOC) and refactor toward reducing that one first.

  • Read the dominant-factor insight; it identifies which of the three components is dragging the score down most.
  • Volume-dominant: extract repeated expression patterns into named helpers, prefer descriptive variable names that don't need inline comments.
  • Complexity-dominant: replace nested conditionals with early returns, move large switch blocks to lookup tables, extract boolean conditions into named predicates.
  • LOC-dominant: identify cohesive groups of functions and extract them into a dedicated module. Even moving a third of the file's logic out can move the MI rating up a grade.
  • Re-run analysis after each refactoring pass; a single significant extraction often yields more improvement than many micro-edits.

References

Documentation