--- name: cognitive-load-reviewer description: Analyze and reduce cognitive load in code by identifying complex conditionals, deep nesting, shallow modules, excessive abstractions, and architectural over-engineering. Use when reviewing code quality, refactoring for maintainability, or simplifying systems. Keywords: cognitive load, complexity, refactor, simplify, maintainability, readability, mental overhead, abstraction, architecture review --- # Cognitive Load Reviewer Identifies and reduces extraneous cognitive load in software systems following evidence-based principles. ## Core Principle **Working Memory Limit**: Humans can hold ~4 chunks of information simultaneously. Code exceeding this threshold creates mental fatigue and slows development. **Goal**: Reduce *extraneous* cognitive load (caused by poor design) while accepting *intrinsic* load (inherent domain complexity). ## Analysis Framework ### 1. Complex Conditionals **Look for:** - Nested boolean expressions: `if val > X && (a || b) && (c && !d)` - Multiple conditions without intermediate variables - Logic requiring mental simulation to understand **Fix:** ```rust // ❌ High cognitive load if val > constant && (cond2 || cond3) && (cond4 && !cond5) { // ... } // ✅ Externalized mental bookkeeping let exceeds_threshold = val > constant; let has_valid_mode = cond2 || cond3; let is_enabled = cond4 && !cond5; if exceeds_threshold && has_valid_mode && is_enabled { // ... } ``` ### 2. Deep Nesting **Look for:** - Multiple levels of indentation (>3 levels) - Nested if/match statements - Accumulated context requirements **Fix:** ```rust // ❌ Nested context tracking fn process(data: Option) -> Result { if let Some(data) = data { if data.is_valid() { if let Some(result) = data.compute() { return Ok(result); } } } Err(Error::Invalid) } // ✅ Early returns focus on happy path fn process(data: Option) -> Result { let data = data.ok_or(Error::Missing)?; if !data.is_valid() { return Err(Error::Invalid); } data.compute().ok_or(Error::ComputeFailed) } ``` ### 3. Shallow vs. Deep Modules **Identify shallow modules:** - Complex interface with minimal functionality - Many small functions/methods requiring multiple mental models - High coupling between components **Prefer deep modules:** - Simple interface hiding complex implementation - Unix I/O principle: 5 basic calls, 100K+ lines internal complexity - Single entry point with clear contract **Example:** ```rust // ❌ Shallow - many small pieces struct UserValidator; struct PasswordHasher; struct SessionCreator; struct TokenGenerator; // ... requires understanding 4+ components // ✅ Deep - simple interface, complex internals struct AuthService { pub fn authenticate(&self, credentials: Credentials) -> Result // Hides validation, hashing, session creation internally } ``` ### 4. Abstraction Layers **Red flags:** - Hexagonal/Onion architecture with 5+ layers - Repository patterns abstracting simple queries - Domain/Application/Infrastructure separation without clear benefit - "MetricsProviderFactoryFactory" naming patterns **Reality check:** - Can newcomers contribute within hours or days? - Does debugging require tracing through multiple layers? - Are abstraction layers solving real extension points or architectural purity? **Principle:** Add abstraction only for justified extension points, not preemptive flexibility. ### 5. DRY Abuse **Look for:** - Shared code between unrelated domains - Premature abstractions creating tight coupling - "Generic" utilities requiring mental mapping **Guideline:** ```rust // ✅ "A little copying is better than a little dependency" // Duplicate 5-10 lines if it maintains clarity and independence // Abstract only when 3+ use cases demonstrate clear pattern ``` ### 6. Microservices Over-Granularity **Warning signs:** - Changes require modifying 4+ services - Distributed monolith patterns - More services than team members **Case study:** 5 developers, 17 microservices → 10 months behind schedule **Principle:** Defer network boundaries until logical system boundaries are clear. ### 7. Framework Magic **Look for:** - Business logic embedded in framework code - Annotations/macros hiding control flow - "Magic" requiring framework internals knowledge before contributing **Fix:** ```rust // ❌ Framework-coupled business logic #[framework::magic_handler] async fn process_order(ctx: FrameworkContext) -> FrameworkResponse { // Business logic intertwined with framework } // ✅ Framework as library, business logic separate async fn process_order(order: Order) -> Result { // Pure business logic, framework-agnostic } // Adapter layer handles framework integration ``` ### 8. Self-Describing Values **Look for:** - Numeric error codes requiring mental mappings - Boolean flags without semantic names - Magic numbers without constants **Fix:** ```rust // ❌ Requires memorization return Err(401); // ✅ Self-describing return Err(AuthError::JwtExpired); // ❌ Magic number if status == 418 { ... } // ✅ Named constant const TEAPOT_STATUS: u16 = 418; if status == TEAPOT_STATUS { ... } ``` ### 9. Inheritance Hierarchies **Look for:** - Multiple inheritance levels (>2) - Vertical cognitive chains requiring class-hopping - Overridden behavior modifications **Prefer:** - Composition over inheritance - Trait/interface implementations without deep hierarchies - Flat structures with explicit dependencies ## Analysis Process ### Step 1: Identify Cognitive Hotspots Scan code for: - Functions >50 lines - Nesting depth >3 levels - Complex boolean logic - Multiple abstraction layers - Module coupling patterns ### Step 2: Measure Mental Overhead Ask: - How many facts must I hold in memory? - Can I understand this without context-switching? - Would a newcomer understand this in <5 minutes? - Does this require memorizing mappings/conventions? ### Step 3: Categorize Load Type - **Intrinsic**: Domain complexity (accept it) - **Extraneous**: Design choices (fix it) ### Step 4: Recommend Improvements Prioritize: 1. **High impact, low effort**: Extract intermediate variables, early returns 2. **Medium impact**: Simplify module boundaries, reduce abstractions 3. **Strategic**: Architecture simplification, framework decoupling ## Output Format Present findings as: ### 🧠 Cognitive Load Analysis **High Load Areas** (>4 mental chunks required) - `crates/parser/src/query.rs:145` - Complex conditional with 6 boolean clauses - `crates/storage/src/engine.rs:89` - 5 levels of nesting, difficult to track state **Shallow Module Patterns** (complex interface, minimal functionality) - `StorageAdapter` + `QueryExecutor` + `ResultMapper` could merge into single `QueryEngine` **Excessive Abstraction** - Repository pattern adds indirection without extension points - Consider direct SQL calls via jOOQ-style query builder **Improvement Priorities** 1. **Extract intermediate variables** in `query.rs:145` ```rust let has_valid_columns = !columns.is_empty() && columns.iter().all(|c| c.is_valid()); let within_bounds = offset >= 0 && limit <= MAX_LIMIT; if has_valid_columns && within_bounds { ... } ``` 2. **Flatten nesting** in `engine.rs:89` using early returns 3. **Merge shallow modules** to create deeper interface with simpler mental model ## Onboarding Metric **Critical test:** Can a new developer contribute within 1-2 days? If newcomers struggle >40 consecutive minutes, cognitive load needs reduction. ## Project Integration Reference `CLAUDE.md` principles: - Incremental development reduces cognitive overhead - TDD externalizes requirements into tests - Small commits maintain reviewability - Parallel sub-agents distribute analysis cognitive load ## Success Examples - Instagram: 14M users with 3 engineers (simple architecture) - Unix I/O: Deep module pattern (5 calls, 100K+ lines hidden) - Raft consensus: Designed explicitly for understandability ## Anti-Pattern Summary ❌ Overly granular module decomposition ❌ Excessive architectural layers without benefit ❌ Numeric codes requiring memorization ❌ Framework-embedded business logic ❌ Premature DRY abstractions ❌ Deep inheritance chains ❌ Nested conditionals without intermediate variables ❌ Shallow modules forcing multi-component mental models ## Remember **"The best components provide powerful functionality yet have a simple interface."** Optimize for reducing the mental effort required to understand and modify code.