Cyclomatic Complexity
debt(d3/e5/b5/t5)
Closest to 'default linter catches the common case' (d3). The term's detection_hints lists phpmd, phpcs, phpmetrics, phploc as tools that automatically detect high cyclomatic complexity. PHPMD is commonly configured in CI pipelines and reports CC >10 by default, making this a standard lint-level catch rather than requiring specialist SAST tools.
Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix says to 'extract decisions into separate methods,' but as common_mistakes notes, 'extracting private methods but keeping the same logic' just shifts the score. Genuine remediation requires rethinking the branching logic, often involving strategy patterns, polymorphism, or restructuring conditionals — a significant refactor within the component, not a one-line fix.
Closest to 'persistent productivity tax' (b5). Cyclomatic complexity applies across all contexts (web, cli, queue-worker) per applies_to. High-complexity functions slow down multiple work streams: testing becomes harder (each branch needs coverage), debugging takes longer, and onboarding new developers suffers. However, it doesn't define system architecture (b7-b9) — it's a function-level concern that accumulates into a steady tax rather than a gravitational force.
Closest to 'notable trap (a documented gotcha most devs eventually learn)' (t5). The misconception field directly states the trap: developers believe 'cyclomatic complexity below 10 means a function is simple enough,' but CC is a guideline, not a guarantee. Common_mistakes also highlights confusion with cognitive complexity. These are well-known gotchas in the static analysis community that most developers learn, but they still catch intermediate developers who treat the metric as absolute.
Also Known As
TL;DR
Explanation
Defined by Thomas McCabe in 1976, cyclomatic complexity measures the number of independent paths through a piece of code. Each decision point (if, elseif, for, while, foreach, case, catch, ||, &&, ?:) adds 1 to the base score of 1. A score of 1–5 is simple, 6–10 is moderate, 11–20 is complex, 20+ is very high risk. High cyclomatic complexity correlates with higher defect density and lower testability — you need at least one test per path to achieve full branch coverage.
Common Misconception
Why It Matters
Common Mistakes
- Not measuring cyclomatic complexity as part of CI — it only gets addressed when someone notices, not systematically.
- Reducing complexity by extracting private methods but keeping the same logic — the extracted methods just shift the score.
- Targeting zero complexity — some decision logic is inherently complex; the goal is appropriate decomposition.
- Confusing cyclomatic complexity with cognitive complexity — cyclomatic counts branches, cognitive accounts for nesting depth.
Code Examples
// CC = 8 (one path per branch)
function classify(int $score): string {
if ($score >= 90) {
return 'A';
} elseif ($score >= 80) {
return 'B';
} elseif ($score >= 70) {
return 'C';
} elseif ($score >= 60) {
return 'D';
} else {
return 'F';
}
}
// CC = 2 — data-driven, trivially testable
function classify(int $score): string {
return match(true) {
$score >= 90 => 'A',
$score >= 80 => 'B',
$score >= 70 => 'C',
$score >= 60 => 'D',
default => 'F',
};
}