Cognitive Complexity
debt(d3/e5/b5/t5)
Closest to 'default linter catches the common case' (d3). Tools like phpmd, phpcs, sonarqube, and phpstan (all listed in detection_hints.tools) can calculate cognitive complexity automatically with standard rulesets. SonarQube specifically pioneered this metric. Detection is straightforward and commonly configured in CI pipelines.
Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix describes extracting nested ifs into guard clauses, extracting loops into named methods, and simplifying boolean conditions — this typically requires restructuring function internals and often creating new helper methods. Common mistakes note that naive splits just move complexity rather than reduce it, indicating non-trivial refactoring work.
Closest to 'persistent productivity tax' (b5). This applies across all contexts (web, cli, queue-worker) and affects ongoing code review and maintenance decisions. High cognitive complexity creates a persistent drag on understanding and modifying code, but it doesn't define the system's architecture — it's a quality characteristic that can be addressed incrementally without rewrites.
Closest to 'notable trap' (t5). The misconception explicitly states that developers conflate cognitive complexity with cyclomatic complexity, assuming they're interchangeable when they measure different things. This is a documented gotcha that most developers eventually learn — nested conditions score higher than equivalent flat ones, which surprises those who only know cyclomatic complexity.
Also Known As
TL;DR
Explanation
Introduced by SonarSource, cognitive complexity scores how hard code is to understand — not just how many paths it has. Structural elements add to the score based on nesting depth: a deeply nested if costs more than a top-level one. Breaks in linear flow (goto, break with label, recursion) also add penalties. Unlike cyclomatic complexity, it is designed to correlate with human comprehension difficulty rather than test case count.
Common Misconception
Why It Matters
Common Mistakes
- Reducing cyclomatic complexity (branch count) while ignoring nesting depth — both matter for readability.
- Splitting a high-complexity function into many small private methods in the same class — you move complexity, not reduce it.
- Targeting a specific score number without understanding which constructs drive it — nested loops and early breaks are the main culprits.
- Ignoring complexity in test code — complex tests are hard to maintain and give false confidence.
Code Examples
// High cognitive complexity — 4 levels of nesting
function process($items, $user) {
if ($user) {
foreach ($items as $item) {
if ($item->active) {
if ($user->canView($item)) {
if ($item->type === 'special') { handleSpecial($item); }
}
}
}
}
}
// Lower complexity — early returns + extracted helpers
function process($items, $user): void {
if (!$user) return;
foreach ($items as $item) { $this->processItem($item, $user); }
}
private function processItem($item, $user): void {
if (!$item->active || !$user->canView($item)) return;
if ($item->type === 'special') handleSpecial($item);
}