Skip to main content

Cyclomatic Complexity (CYCLO)

v1.0.0
short name: CYCLO
effort: 10m
default threshold: 20

Cyclomatic complexity is a quantitative metric that measures the number of linearly independent paths through a block of code. The metric value gets increased each time the control flow of a function/method/constructor splits resulting in a new conditional branch.

The following statements and expressions affect the metric value:

  • if (statement and expression), catch, do, while, for (statement and expression)
  • conditional expressions (? ... : ...)
  • case in a switch statement or expression (default or last case does not count)
  • null-aware operators (?[], ?., ?.., ...?, {?key: value}, {key: ?value})
  • && and || in binary expressions or patterns
  • ?? and ??=

The base complexity of a function/method/constructor is 1.

note

This metric is not calculated for abstract methods/getters/setters.

To get real-time analysis for this metric, enable the avoid-high-cyclomatic-complexity rule.

Why Be Cautious

High Cyclomatic Complexity can lead to:

  • Difficulty in Testing: More independent paths require more test cases.
  • Reduced Readability: Complex code is harder for others to read and understand.
  • Error-Proneness: Complex functions are more likely to contain errors due to multiple paths and logic branches.

How to Address High Cyclomatic Complexity?

First, review the code for potential simplifications. For example, some conditions may be excessive (covered by other conditions) or unnecessary.

But the general rule is to split complex declaration into several smaller ones as it both improves readability and allows testing them separately preventing two most significant issues.

Config Example

analysis_options.yaml
dcm:
metrics:
cyclomatic-complexity:
threshold: 20

To set multiple threshold or other common config options, refer to the Configuring Metrics page.

Example

info

To view what contributes to the metric value, generate an HTML report.

❌ Bad: High Cyclomatic Complexity

// CYCLO: 10
void processOrder(Order order) {
if (order.isPaid) {
if (order.hasStock) {
if (order.isEligibleForDiscount) {
applyDiscount(order);
}
if (order.requiresShipping) {
if (order.isInternational) {
calculateInternationalShipping(order);
} else {
calculateDomesticShipping(order);
}

switch (order.shipping.status) {
case .pending:
...

case .processed:
...

case .failed:
...

case _: // not counted
}
} else if (order.pickupLocation != null) {
arrangePickup(order);
}
} else {
throw Exception('Out of stock');
}
} else {
logPaymentPending(order);
}
}

✅ Good: Low Cyclomatic Complexity

// CYCLO: 3
void processOrder(Order order) {
if (!order.isPaid) {
logPaymentPending(order);
return;
}
if (!order.hasStock) {
throw Exception('Out of stock');
}

applyDiscountIfEligible(order);
processShipping(order);
}

// CYCLO: 2
void applyDiscountIfEligible(Order order) {
if (order.isEligibleForDiscount) {
applyDiscount(order);
}
}

// CYCLO: 4
void processShipping(Order order) {
if (order.requiresShipping) {
if (order.isInternational) {
calculateInternationalShipping(order);
} else {
calculateDomesticShipping(order);
}
} else if (order.pickupLocation != null) {
arrangePickup(order);
}
}