Skip to content
Sponsor: NimblePros Software architecture, modernization, and training for high-performing development teams. Work with us.
Cyclomatic Complexity

Cyclomatic Complexity

Cyclomatic complexity is a software metric introduced by Thomas J. McCabe in 1976 that counts the number of linearly independent paths through a method or function. It provides an objective, numerical measure of how complex a piece of code is from a control-flow perspective.

The metric is calculated from the control-flow graph of a program. For most purposes, a practical rule of thumb is:

Cyclomatic complexity = number of decision points + 1

Decision points include if, else if, while, for, foreach, case, catch, &&, ||, and the ternary operator ?:. Each one adds one to the count.

Cyclomatic Complexity = E − N + 2P

Where E is the number of edges, N is the number of nodes, and P is the number of connected components in the control-flow graph. For a single method, this simplifies to counting decision points plus one.

Interpreting the Score

Score Interpretation
1–5 Simple, easy to test
6–10 Moderate complexity, manageable
11–20 High complexity — consider refactoring
21+ Very high — difficult to test and maintain

These thresholds are guidelines, not hard rules. A score of 10 in a well-structured parser may be entirely acceptable; a score of 6 in a domain service might signal a design problem.

Why Cyclomatic Complexity Matters

Testability

Each independent path through a method is a scenario that ideally has at least one test. A method with a cyclomatic complexity of 12 has at least 12 independent paths, requiring at minimum 12 test cases for full branch coverage. High cyclomatic complexity is directly correlated with test effort.

Fault Density

Empirical research has consistently shown that modules with higher cyclomatic complexity have higher defect rates. More decision points mean more opportunities for an incorrect branch, a missing edge case, or a logic error.

Maintainability

A developer reading a method with many branches must hold all the branching conditions in working memory to reason about the method’s behavior. High cyclomatic complexity increases cognitive load and makes the code harder to modify safely.

Cyclomatic vs. Cognitive Complexity

Cyclomatic complexity counts paths — it is a structural, mathematical measure. Cognitive complexity measures mental effort — it penalizes nesting and non-linear control flow more heavily than flat chains of conditions. A method can have high cyclomatic complexity without being especially hard to read (a long but flat switch statement), or moderate cyclomatic complexity while being very hard to follow (deeply nested conditions).

Both metrics are useful. Cyclomatic complexity is a strong predictor of testing effort; cognitive complexity is a better predictor of readability difficulty. Together they provide a more complete picture of the Conditional Complexity code smell.

Reducing Cyclomatic Complexity

The primary goal is to reduce the number of decision points in a single method:

  • Extract Method — break a complex method into smaller, focused methods, each with its own lower complexity score.
  • Replace Conditional with Polymorphism — move branches into separate classes (Strategy, State) so each class has a simple, single-path implementation.
  • Guard Clauses — handle edge cases early and return, flattening nested conditions and reducing nesting depth.
  • Replace nested conditionals with table-driven logic — map inputs to outputs using a dictionary or data structure instead of branching code.

Tooling

Cyclomatic complexity can be measured automatically:

  • .NET / C#: Visual Studio Code Metrics, NDepend, or the nmbls cc command
  • JavaScript / TypeScript: ESLint with the complexity rule
  • Java: Checkstyle, PMD, SonarQube
  • Python: radon, flake8-cognitive-complexity

References