Files
gh-cubical6-melly/skills/c4model-c4/complexity-metrics.md
2025-11-29 18:17:07 +08:00

7.8 KiB

Complexity Metrics Methodology

This guide provides methodology for calculating and documenting code complexity metrics at the C4 Code level.


Metrics Overview

Metric Description Threshold
Lines of Code (LOC) Actual code lines Warning: >30, Critical: >50
Cyclomatic Complexity Decision paths Warning: >6, Critical: >10
Cognitive Complexity Mental effort Warning: >10, Critical: >20
Parameter Count Function parameters Warning: >3, Critical: >5
Nesting Depth Max nesting level Warning: >3, Critical: >5

Lines of Code (LOC)

Definition

Count of actual code lines excluding:

  • Blank lines
  • Comments
  • Import statements (debatable)

Calculation

// Example function - LOC = 8
function processOrder(order: Order): ProcessedOrder {
  const validated = validateOrder(order);  // 1
  if (!validated) {                        // 2
    throw new Error('Invalid order');      // 3
  }                                        // 4
  const enriched = enrichOrder(validated); // 5
  const processed = applyRules(enriched);  // 6
  logOrder(processed);                     // 7
  return processed;                        // 8
}

Thresholds

Range Rating Action
1-30 Good No action needed
31-50 Warning Consider extracting methods
>50 Critical Must refactor

Cyclomatic Complexity

Definition

Number of linearly independent paths through code. Calculated as:

  • Start with 1
  • Add 1 for each: if, else if, case, for, while, do, catch, &&, ||, ?:

Calculation Example

function processPayment(payment: Payment): Result {  // CC = 1 (base)
  if (payment.amount <= 0) {                         // CC = 2
    return { error: 'Invalid amount' };
  }

  if (payment.type === 'credit') {                   // CC = 3
    if (payment.amount > 10000) {                    // CC = 4
      return { error: 'Amount exceeds limit' };
    }
    return processCreditCard(payment);
  } else if (payment.type === 'debit') {             // CC = 5
    return processDebitCard(payment);
  } else if (payment.type === 'crypto') {            // CC = 6
    return processCrypto(payment);
  }

  return { error: 'Unknown payment type' };
}
// Total Cyclomatic Complexity = 6

Decision Points

Construct Adds
if +1
else if +1
case (switch) +1 per case
for +1
while +1
do...while +1
catch +1
&& +1
`
?: (ternary) +1
?. (optional chain) +1
?? (nullish coalesce) +1

Thresholds

Range Rating Interpretation
1-6 Good Simple, easy to test
7-10 Warning Moderate complexity
11-20 High Difficult to test
>20 Critical Untestable, must refactor

Cognitive Complexity

Definition

A metric that measures the mental effort required to understand code. Unlike cyclomatic complexity, it:

  • Penalizes nesting
  • Ignores shorthand structures
  • Focuses on readability

Calculation Rules

  1. Increment for each:

    • if, else if, else
    • switch
    • for, foreach, while, do
    • catch
    • break/continue to label
    • Sequences of logical operators
  2. Nesting penalty:

    • Add +1 for each level of nesting when incrementing

Example

function example(arr: number[], target: number): number {
  // Base: 0
  for (const item of arr) {              // +1 (increment)
    if (item === target) {               // +2 (increment + 1 nesting)
      return item;
    } else if (item > target) {          // +2 (increment + 1 nesting)
      if (item % 2 === 0) {              // +3 (increment + 2 nesting)
        return item * 2;
      }
    }
  }
  return -1;
}
// Total Cognitive Complexity = 8

Thresholds

Range Rating Action
0-10 Good Understandable
11-20 Warning Getting complex
>20 Critical Hard to understand

Parameter Count

Definition

Number of parameters a function accepts.

Guidelines

Count Rating Recommendation
0-3 Good Ideal range
4-5 Warning Consider parameter object
>5 Critical Use parameter object

Refactoring Example

// Before: 6 parameters (Critical)
function createUser(
  name: string,
  email: string,
  age: number,
  address: string,
  phone: string,
  role: string
) { }

// After: 1 parameter object (Good)
interface CreateUserInput {
  name: string;
  email: string;
  age: number;
  address: string;
  phone: string;
  role: string;
}

function createUser(input: CreateUserInput) { }

Nesting Depth

Definition

Maximum depth of nested control structures.

Calculation

function process(data: Data): Result {
  if (data.valid) {                    // Depth 1
    for (const item of data.items) {   // Depth 2
      if (item.active) {               // Depth 3
        try {                          // Depth 4
          if (item.type === 'A') {     // Depth 5 (Critical!)
            // ...
          }
        } catch (e) {
          // ...
        }
      }
    }
  }
  return result;
}
// Maximum Nesting Depth = 5

Thresholds

Depth Rating Action
0-3 Good Easy to follow
4-5 Warning Consider extracting
>5 Critical Must refactor

Refactoring Techniques

  1. Early returns (guard clauses)
// Before
function process(data) {
  if (data) {
    if (data.valid) {
      // actual logic
    }
  }
}

// After
function process(data) {
  if (!data) return;
  if (!data.valid) return;
  // actual logic
}
  1. Extract nested logic
// Before
for (const item of items) {
  if (item.active) {
    if (item.valid) {
      // complex logic
    }
  }
}

// After
function processItem(item) {
  if (!item.active || !item.valid) return;
  // complex logic
}

for (const item of items) {
  processItem(item);
}

Metrics JSON Structure

{
  "metrics": {
    "lines_of_code": 45,
    "cyclomatic_complexity": 8,
    "cognitive_complexity": 15,
    "parameter_count": 3,
    "nesting_depth": 4
  }
}

Threshold Summary Table

Metric Good Warning Critical
LOC 1-30 31-50 >50
Cyclomatic 1-6 7-10 >10
Cognitive 0-10 11-20 >20
Parameters 0-3 4-5 >5
Nesting 0-3 4-5 >5

Observation Examples

High Complexity Warning

{
  "id": "obs-auth-service-complexity-01",
  "category": "complexity",
  "severity": "warning",
  "description": "Cyclomatic complexity of 8 exceeds recommended threshold of 6. Consider extracting authentication steps into separate methods.",
  "evidence": [
    {
      "location": "src/services/auth.ts:45-120",
      "type": "metric"
    }
  ],
  "tags": ["complexity", "refactoring-candidate"]
}

Critical Nesting

{
  "id": "obs-order-processor-nesting-01",
  "category": "complexity",
  "severity": "critical",
  "description": "Maximum nesting depth of 6 makes code difficult to understand. Extract nested logic into helper functions.",
  "evidence": [
    {
      "location": "src/services/order.ts:78-150",
      "type": "code",
      "snippet": "if (order.valid) { for (...) { if (...) { try { if (...) {"
    }
  ],
  "tags": ["nesting", "refactoring-required"]
}

Best Practices

DO:

  • Calculate all five metrics for functions/methods
  • Flag any metric exceeding warning threshold
  • Provide specific refactoring suggestions
  • Include evidence with line numbers

DON'T:

  • Skip metrics for simple functions
  • Ignore nesting depth
  • Accept critical thresholds without observation
  • Forget to suggest refactoring approaches