phanalist

E0030: The “Logic Density” Rule (Cyclomatic Complexity Density)

Complexity Density measures how much decision-making is packed into each line of code. It’s the ratio of a method’s cyclomatic complexity to its length in lines.

A method with complexity 10 in 100 lines (density 0.10) is long but straightforward. A method with complexity 5 in 10 lines (density 0.50) is short but extremely dense — every line is a decision.

How the rule works

For each concrete method, we compute density = (1 + total_branches) / body_lines. Branches include if, elseif, case, catch, and loops (for, foreach, while, do-while). If the density exceeds the threshold (default 0.30), the method’s logic is too tightly packed.


❌ The “Dense” Example

Short but impossible to follow — every line branches.

public function resolve($a, $b, $c): int
{
    if ($a) { if ($b) { return 1; } else { if ($c) { return 2; } } }
    if ($a && $b || $c) { return 3; }
    if (!$a) { return 4; }
    return 0;
}

✅ The “Readable” Example

Same logic, but spread out so each branch has room to breathe.

public function resolve($a, $b, $c): int
{
    if ($a && $b) {
        return 1;
    }
    if ($a && $c) {
        return 2;
    }
    if ($a || $c) {
        return 3;
    }
    if (!$a) {
        return 4;
    }
    return 0;
}

Configuration

rules:
  E0030:
    max_density: 0.3

The Junior’s Rule of Thumb:

If Phanalist flags a method for high complexity density, your code is too clever per line. Don’t try to write the shortest code — write the most readable code. Spread branches across lines and use early returns.