Keep Cognitive Complexity Low with PHPStan

It seems specialized PHPStan packages are fun and easy to use. I made one to keep code readable and avoid piling up legacy code nobody wants to touch.

Why is cognitive complexity such a powerful predictor of readable or unreadable code?

What is cognitive complexity? It's the amount of information we have to hold in our heads simultaneously to understand the code. The more indents, continue, break, nested foreach, and if/else branches, the harder is code to read.

Let's jump right to an example. We are in the middle of the holidays and want to share our Christmas spirit with the world. Let's write a simple script to do that:

echo 'I got ' . get_words_from_number(100) . ' gifts for Christmas!';

We're interested in the body of get_words_from_number(). We measure the complexity line by line:

function get_words_from_number(int $number): string
{
    $amountInWords = '';

    if ($number === 1) {            // + 1
        $amountInWords = 'one';
    } elseif ($number === 2) {      // + 1
        $amountInWords = 'couple';
    } elseif ($number === 3) {      // + 1
        $amountInWords = 'a few';
    } else {                        // + 1
        $amountInWords = 'a lot';
    }

    return $amountInWords;
}

This code has cognitive complexity of 4. It's a pretty bumpy ride to understand it, right?


How can we make it lower, so it's easier to understand?

We should use the following:


function get_words_from_number(int $number): string
{
    return match ($number) { // +1
        1 => 'one',
        2 => 'a couple',
        3 => 'a few',
        default => 'lots',
    };
}

3 Steps to Keep Cognitive Complexity Low with PHPStan

  1. Install the TomasVotruba/cognitive-complexity package
composer require tomasvotruba/cognitive-complexity --dev

Not a phpstan/extension-installer user yet? Add it now to enjoy the easy install without copying config paths.


  1. Setup PHPStan configuration:
# phpstan.neon
parameters:
    cognitive_complexity:
        class: 50
        function: 8

  1. Run PHPStan:
vendor/bin/phpstan

Does PHPStan report 1000 cases? No worries, no project ever passed it on the first run. Keep yourself calm, make the value higher and re-run:

 # phpstan.neon
 parameters:
     cognitive_complexity:
-        class: 50
+        class: 70
-        function: 8
+        function: 15

Are there just 5 cases? Fix those to make CI pass again!


2 Areas where Cognitive Complexity Rocks

This package turned out to be very helpful in 2 phases:

At first, it helps to lower the hard spots. In sum, this turn the codebase into a senior codebase, it's easier to understand for fresh developer on the project and grow further.


Second, it gives quick feedback on the code review. If you get the following error:

"the 'simpleFetch()` method cognitive complexity is over 30, make it simpler"

You know you can be more creative and improve it for better readability.


Happy coding!




Do you learn from my contents or use open-souce packages like Rector every day?
Consider supporting it on GitHub Sponsors. I'd really appreciate it!