Cognitive Complexity

Campbell (SonarSource), 2016/2018: a complexity metric weighted for human comprehension instead of path count. Fixes Cyclomatic Complexity’s blind spot — it penalizes what actually makes code hard to read: nesting, breaks in linear flow, and recursion, while not inflating uniform structures like flat switch chains.

The three rules (from the paper)

  1. Penalize constructs that break the linear read: loops, conditionals, jumps (break/continue/goto), catches, sequences of logical operators, recursion (each +1, recursion +3 in some formulations).
  2. Penalize nesting: a nested if costs more than a top-level one (+ the nesting level), because the reader must hold the outer context in mind. else if/else add nothing new — the condition is already established.
  3. Don’t penalize the flat, linear, predictable: a long switch with many cases reads as a lookup table, so cases beyond the first add little or nothing. Inverted if-guards that reduce nesting (early return) are cheap — the metric rewards the flattening idiom.

Net effect: two functions with identical cyclomatic scores can differ 2–3× in cognitive score — the nested one high, the switch one low. That matches how they feel, which is the whole point.

What it’s for

  • Maintainability gating where humans (or LLMs) read the code: SonarQube’s default gate ≈ 15 per function. It’s a readability proxy — imperfect (it can’t see naming, domain density, or comment debt) but structural and objective.
  • The agent twist: code is now read by models most of the time — in context windows. Flatter, less-nested code is both easier for humans and cheaper for LLMs to hold (Dipping my toes into clojure’s brevity-is-context argument generalizes: low cognitive complexity = less structural bookkeeping per token).

Measurement

cccc (OSS) computes it (full SonarSource/Campbell ruleset) alongside cyclomatic in one Rust binary across 20+ languages. Staltz’s recipe: max-cognitize 40 as the gate, wired into AGENTS.md so agents self-validate — a deterministic readability budget for the ultracode-refactor loop.

Vault kin