# Cognitive Complexity

> Cognitive complexity is a metric proposed to compensate for the shortcomings of cyclomatic complexity.

Cognitive complexity is a metric proposed to compensate for the shortcomings of [cyclomatic complexity](https://wiki.g15e.com/pages/Cyclomatic%20complexity.txt).

## Shortcomings of cyclomatic complexity

Cyclomatic complexity has the advantage of being simple to calculate and explain, but it also has several drawbacks.[^1]

- There are often gaps between the cyclomatic complexity score and actual cognitive complexity.
- Cyclomatic complexity does not take into account syntax that came into widespread use after 1976, when cyclomatic complexity was first proposed, such as <lambda expressions> or `try-catch`. (The language used as an example in the original paper[^2] was <FORTRAN>.)
- Because the base score of cyclomatic complexity is 1, if a class has three methods, then even if none of those methods has any branches, the cyclomatic complexity of the class as a whole becomes 3.

Because of the above issues, cyclomatic complexity is good for measuring testability, but somewhat lacking for measuring maintainability. Cognitive complexity addresses these problems.

## Calculating cognitive complexity

- It increases when a branch occurs in the linear flow read from left to right and top to bottom[^3]
- If it is a nested branch, it increases additionally[^3]
- Even if multiple variables are used within a conditional, if they are continuously connected by the same logical operator, they are treated as one chunk (e.g., `a && b && c` is one chunk, and `a && b || c` is two chunks)[^3]
- Branches that do not reduce understandability, such as <optional chaining>, are ignored[^3]

## Heuristics for mentally calculating cognitive complexity

Compared with [cyclomatic complexity](https://wiki.g15e.com/pages/Cyclomatic%20complexity.txt), which simplifies the control structure of code into a <graph structure> and then counts paths, cognitive complexity's calculation method is relatively messy (see the white paper[^1]). Given that its purpose is to take actual cognitive load into account, that is unavoidable. If you are using a tool that automatically calculates cognitive complexity, it does not matter, but if you are doing a <code review> or trying to calculate complexity directly in your head, then trying to apply cognitive complexity too literally would probably have larger side effects instead. In that kind of situation, it is useful enough to think of [cyclomatic complexity](https://wiki.g15e.com/pages/Cyclomatic%20complexity.txt) as improved only minimally, as follows.

- Make the default value 0. In other words, if the flow is linear, calculate it as 0 rather than 1.
- Give weight to nested branches.

Even with just those two changes, you can improve [cyclomatic complexity](https://wiki.g15e.com/pages/Cyclomatic%20complexity.txt) in quite a lot of situations.

## Tools

- [eslint-plugin-sonarjs](https://www.npmjs.com/package/eslint-plugin-sonarjs): SonarJS rules for <ESLint>

## See also

- [SonarSource Rule Specifications S3776: Cognitive Complexity of functions should not be too high](https://sonarsource.github.io/rspec/#/rspec/S3776)

## Footnotes

[^1]: [Cognitive complexity: a new way of measuring understandability](https://wiki.g15e.com/pages/Cognitive%20complexity%20-%20a%20new%20way%20of%20measuring%20understandability.txt)
[^2]: [A complexity measure](https://wiki.g15e.com/pages/A%20complexity%20measure.txt)
[^3]: [Cognitive Complexity, Because Testability != Understandability | Sonar](https://www.sonarsource.com/blog/cognitive-complexity-because-testability-understandability/)