Cyclomatic complexity quantifies structural complexity by counting decision points in your code. Each decision point creates a new execution path that potentially needs testing.
The core principle: more decision points = more paths to test = higher complexity.
Stellarion calculates cyclomatic complexity using AST (Abstract Syntax Tree) traversal, counting:
| Construct | Increment |
|---|---|
if statement | +1 |
else if | +1 |
for loop | +1 |
while loop | +1 |
do-while loop | +1 |
switch case | +1 per case |
catch block | +1 |
&& operator | +1 |
| ` | |
Ternary ?: | +1 |
The base complexity is 1 (representing the default path through the function).
Formula: CC = (decision points) + 1
Or using graph theory: CC = E - N + 2P where E = edges, N = nodes, P = connected components.
Stellarion classifies cyclomatic complexity using these thresholds:
| Score | Severity | Color | Assessment |
|---|---|---|---|
| 1-10 | Low | Green | Simple, testable, maintainable |
| 11-15 | Moderate | Yellow | Acceptable complexity |
| 16-20 | High | Orange | Consider refactoring |
| 21-30 | High | Orange | Refactoring recommended |
| >30 | Critical | Red | Immediate refactoring required |
Cyclomatic complexity directly correlates with minimum test cases needed. For a function with CC=15, you need at least 15 test cases for full path coverage.
Stellarion recommendation: Create CC × 1.5 test cases to ensure adequate coverage including edge cases.
Functions with high CC are:
High CC functions require more review time and are more likely to have defects slip through review.
Break large functions into smaller, focused units:
# Before (CC=12)
def process_order(order):
if order.is_valid:
if order.has_items:
for item in order.items:
if item.in_stock:
# ... 20 more lines
else:
# ... handle out of stock
# After (CC=3 each)
def process_order(order):
if not order.is_valid:
return handle_invalid_order(order)
if not order.has_items:
return handle_empty_order(order)
return process_items(order.items)
Use the Strategy pattern or lookup tables:
// Before (CC=5)
function getDiscount(type) {
if (type === 'gold') return 0.2;
if (type === 'silver') return 0.1;
if (type === 'bronze') return 0.05;
return 0;
}
// After (CC=1)
const discounts = { gold: 0.2, silver: 0.1, bronze: 0.05 };
function getDiscount(type) {
return discounts[type] || 0;
}
Apply De Morgan's laws and extract named conditions.
Replace nested conditions with early returns.
Stellarion recommends maintaining test coverage proportional to complexity:
CC × 5% with minimum 80%For the complete metrics reference, see Stellarion Quality Metrics.
Cognitive Complexity
Cognitive complexity measures how difficult code is for a human to understand. Unlike cyclomatic complexity which counts execution paths, cognitive complexity focuses on the mental effort required to read and comprehend code.
Maintainability Index
The Maintainability Index (MI) is a composite metric that combines multiple code characteristics into a single score representing how maintainable your code is. Originally developed by Oman and Hagemeister in 1991, it provides a holistic view of code health on a 0-100 scale.