--- id: wiki-2026-0508-cyclomatic-complexity title: Cyclomatic Complexity category: 10_Wiki/Topics status: verified canonical_id: self aliases: [McCabe Complexity, Cyclomatic Number, 순환 복잡도] duplicate_of: none source_trust_level: A confidence_score: 0.92 verification_status: applied tags: [code-quality, metrics, static-analysis, mccabe] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: python framework: ruff --- # Cyclomatic Complexity ## 매 한 줄 > **"매 function 의 linearly independent path 수"**. Thomas McCabe (1976) 가 정의. 매 control-flow graph 매 `M = E − N + 2P` (edges − nodes + 2×components). 2026 현재 ruff, eslint, SonarQube 매 default 로 측정; high CC ↔ test difficulty + bug rate correlation 매 empirical. ## 매 핵심 ### 매 계산 - 각 decision point (if, for, while, case, &&, ||, ternary, catch) 마다 +1. - Base 1 (single path) + decisions. - Function 1 → straight-line. - Function 10+ → moderate. - Function 20+ → complex, refactor 권장. - Function 50+ → 매 unmaintainable. ### 매 의미 - **Test path 수** lower bound. - **Reading difficulty** proxy. - **Bug density correlation** — 매 empirical study. - **NOT** measure of correctness, performance, design quality. ### 매 응용 1. CI gate — `max-complexity: 10` lint rule. 2. Code review — high-CC function 매 split 요청. 3. Refactoring target prioritization. 4. Legacy modernization metric. ## 💻 패턴 ### CC 계산 example (Python) ```python def classify(score): # base 1 if score >= 90: # +1 return 'A' elif score >= 80: # +1 return 'B' elif score >= 70: # +1 return 'C' else: return 'F' # CC = 4 ``` ### Lint config (ruff, 2026) ```toml # pyproject.toml [tool.ruff.lint] select = ["C90"] # mccabe [tool.ruff.lint.mccabe] max-complexity = 10 ``` ### ESLint ```json { "rules": { "complexity": ["error", { "max": 10 }] } } ``` ### Refactor: replace conditional with polymorphism ```typescript // before — CC 5 function area(shape: Shape): number { if (shape.kind === 'circle') return Math.PI * shape.r ** 2; if (shape.kind === 'square') return shape.s ** 2; if (shape.kind === 'rect') return shape.w * shape.h; if (shape.kind === 'triangle') return 0.5 * shape.b * shape.h; throw new Error('unknown'); } // after — CC 1 per class abstract class Shape { abstract area(): number; } class Circle extends Shape { area() { return Math.PI * this.r ** 2; } } class Square extends Shape { area() { return this.s ** 2; } } ``` ### Refactor: guard clauses (early return) ```python # before — CC 4 def process(user): if user is not None: if user.active: if user.has_permission: do_work(user) # after — CC 4 still, but readability ↑ def process(user): if user is None: return if not user.active: return if not user.has_permission: return do_work(user) ``` ### Refactor: table dispatch ```python # before — CC 6 def handle(event_type, payload): if event_type == 'created': return on_created(payload) elif event_type == 'updated': return on_updated(payload) elif event_type == 'deleted': return on_deleted(payload) # ... # after — CC 2 HANDLERS = {'created': on_created, 'updated': on_updated, 'deleted': on_deleted} def handle(event_type, payload): handler = HANDLERS.get(event_type) if not handler: raise ValueError(event_type) return handler(payload) ``` ### radon (Python CLI) ```bash $ radon cc -s -a app/ app/service.py F 42:0 process_order - C (12) F 88:0 validate - A (3) Average complexity: B (6.2) ``` ## 매 결정 기준 | 상황 | Approach | |---|---| | New code | CC ≤ 10 hard limit | | Legacy refactor | CC > 15 → split 우선 | | Pure data transform | higher CC OK if linear (case/match) | | State machine | use explicit FSM library | **기본값**: max-complexity 10 in lint config; warn at 8. ## 🔗 Graph - 부모: [[Static Analysis]] - 응용: [[Refactoring_Best_Practices|Refactoring]] · [[Code Review]] · [[CI Gates]] - Adjacent: [[Test Coverage]] · [[SOLID]] (Single Responsibility) ## 🤖 LLM 활용 **언제**: high-CC function 매 refactor 제안 (split, polymorphism, table dispatch). **언제 X**: pure metric calculation (deterministic tool 가 더 빠름). ## ❌ 안티패턴 - **CC 만 보고 quality 판단**: linear case dispatch 매 high CC 지만 매 simple. - **Hard limit 무조건 enforcement**: 매 split 의 split 매 fragmentation. - **CC ↓ 위해 boolean parameter 추가**: flag argument anti-pattern. - **Cognitive complexity 무시**: 매 nesting depth, recursion 매 더 중요할 수도. ## 🧪 검증 / 중복 - Verified (McCabe 1976 *A Complexity Measure*, ruff/SonarQube docs 2026). - 신뢰도 A. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — full content with refactoring patterns |