Claude-skill-registry hammer-dependency-analyzer
Verify dependency structure and architecture health for SDL3 HammerEngine. Detects circular dependencies, excessive coupling, layer violations, header bloat, and provides dependency graph visualization. Ensures adherence to layered architecture (Core→Managers→States→Entities). Use monthly, after major refactors, or when investigating compile time issues.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/hammer-dependency-analyzer" ~/.claude/skills/majiayu000-claude-skill-registry-hammer-dependency-analyzer && rm -rf "$T"
skills/data/hammer-dependency-analyzer/SKILL.mdHammerEngine Dependency Analyzer
Comprehensive dependency structure analysis for SDL3 HammerEngine. Verifies architectural integrity, detects circular dependencies, identifies coupling issues, and maintains clean layered design.
Purpose
HammerEngine follows a layered architecture pattern:
Core (ThreadSystem, Logger, GameLoop) ↓ Managers (AIManager, CollisionManager, etc.) ↓ States (GameState, MenuState, etc.) ↓ Entities (Entity classes, Components) ↓ Utils (Vector2D, Math helpers)
This Skill ensures:
- Circular Dependency Detection - Prevent include cycles that break compilation
- Coupling Analysis - Maintain loose coupling between managers
- Layer Violation Detection - Enforce one-way dependencies (no upward dependencies)
- Header Bloat Identification - Find unnecessary includes slowing compilation
- Forward Declaration Opportunities - Reduce compilation dependencies
- Dependency Graph Visualization - Understand system relationships
- Compile Time Impact Analysis - Estimate compilation cost per component
- Architecture Health Scoring - Quantify overall design quality
Architecture Rules (from CLAUDE.md)
Layer Rules
1. Core Layer (
src/core/, include/core/)
- Can depend on: Nothing (foundation layer)
- Used by: Everything
- Components: ThreadSystem, Logger, GameLoop, GameEngine
2. Managers Layer (
src/managers/, include/managers/)
- Can depend on: Core, Utils
- Cannot depend on: States, Entities (except via interfaces)
- Coupling: Managers should be loosely coupled, communicate via GameEngine
- Components: AIManager, CollisionManager, PathfinderManager, EventManager, etc.
3. States Layer (
src/gameStates/, include/gameStates/)
- Can depend on: Core, Managers, Utils
- Cannot depend on: Other States (no cross-state dependencies)
- Components: GameState, MainMenuState, PlayingState, PauseState, etc.
4. Entities Layer (
src/entities/, include/entities/)
- Can depend on: Core, Utils
- Should avoid: Direct manager dependencies (use interfaces/callbacks)
- Components: Entity, Component classes
5. Utils Layer (
src/utils/, include/utils/)
- Can depend on: Nothing (pure utility functions)
- Used by: Everything
- Components: Vector2D, Math, JsonReader
Coupling Rules
Important: Game Engine Functional Coupling
Game engines have necessary functional dependencies between managers. The following patterns are CORRECT and expected:
✅ Functional Game System Dependencies (GOOD):
- AIManager → CollisionManager (AI needs collision queries for obstacle avoidance, LOS)
- AIManager → PathfinderManager (AI needs pathfinding for navigation)
- CollisionManager → WorldManager (collision needs world geometry/tile data)
- Managers → EventManager (event-driven notifications are good architecture)
- UIManager → FontManager (UI needs fonts to render text)
- WorldManager → ResourceManager (world needs tile/sprite resources)
- ResourceFactory → ResourceTemplateManager (factory pattern requires templates)
Manager-to-Manager Rules:
- ✅ GOOD: Functional dependencies for game systems
- ✅ GOOD: Event-based communication between managers
- 🔴 FORBIDDEN: Circular Manager dependencies (breaks compilation)
- 🔴 FORBIDDEN: Managers depending on States (violates layer boundaries)
What Actually Matters:
- Circular dependencies: 🔴 ALWAYS BAD (breaks compilation)
- Layer violations: 🔴 ALWAYS BAD (breaks architecture)
- Tight coupling: ✅ OFTEN NECESSARY for game systems to work together
- High reference counts: ✅ EXPECTED when systems interact functionally
State-to-Manager:
- ✅ GOOD: PlayingState → AIManager (states use managers)
- 🔴 FORBIDDEN: AIManager → PlayingState (managers don't know about states)
Header Inclusion:
- ✅ GOOD: Forward declarations in headers, include in .cpp
- ⚠️ WARNING: Including heavy headers in .hpp (ripple effect)
- 🔴 FORBIDDEN: Circular includes (breaks compilation)
Analysis Modes
Mode 1: Quick Dependency Check (2-3 minutes)
- Scan for circular dependencies only
- Quick validation before commits
- Use when: Daily development, pre-commit
Mode 2: Coupling Analysis (5-10 minutes)
- Analyze manager-to-manager coupling
- Identify high fan-out components
- Measure coupling strength
- Use when: Adding new managers, refactoring
Mode 3: Full Architecture Audit (15-20 minutes)
- Complete dependency graph
- Layer violation detection
- Header bloat analysis
- Forward declaration opportunities
- Compile time impact estimation
- Use when: Monthly audits, major refactors, release prep
Mode 4: Specific Component Analysis (3-5 minutes)
- Analyze single component's dependencies
- Show what it depends on and what depends on it
- Use when: Investigating specific coupling issues
Step 1: Gather User Input
Use AskUserQuestion to determine analysis scope:
Question 1: Analysis Mode
- Header: "Mode"
- Question: "What type of dependency analysis do you want?"
- Options:
- "Quick Circular Check" (2-3 min, daily use)
- "Coupling Analysis" (5-10 min, manager refactoring)
- "Full Architecture Audit" (15-20 min, comprehensive)
- "Specific Component" (3-5 min, targeted analysis)
- multiSelect: false
Question 2: Scope (if Mode = Specific Component)
- Header: "Component"
- Question: "Which component should be analyzed?"
- Options:
- "AIManager"
- "CollisionManager"
- "PathfinderManager"
- "EventManager"
- "Custom (specify)"
- multiSelect: false
- Only show if Mode = "Specific Component"
Question 3: Output Format
- Header: "Format"
- Question: "Preferred output format?"
- Options:
- "Markdown Report" (default, saved to docs/)
- "ASCII Tree" (console visualization)
- "Both" (report + console tree)
- multiSelect: false
Step 2: Scan Include Dependencies
2a. Find All Header Files
echo "=== Scanning Include Dependencies ===" # Find all headers INCLUDE_HEADERS=$(find include/ -name "*.hpp" -type f) SRC_HEADERS=$(find src/ -name "*.hpp" -type f) ALL_HEADERS=$(echo "$INCLUDE_HEADERS $SRC_HEADERS" | tr ' ' '\n' | sort -u) HEADER_COUNT=$(echo "$ALL_HEADERS" | wc -l) echo "Total headers found: $HEADER_COUNT"
2b. Extract Include Directives
OUTPUT_DIR="test_results/dependency_analysis" mkdir -p "$OUTPUT_DIR" DEPENDENCY_FILE="$OUTPUT_DIR/dependencies_raw.txt" > "$DEPENDENCY_FILE" # Clear file echo "Extracting #include directives..." for HEADER in $ALL_HEADERS; do # Extract local includes only (not system includes) LOCAL_INCLUDES=$(grep '^#include "' "$HEADER" | sed 's/#include "\(.*\)"/\1/' | tr -d '\r') if [ ! -z "$LOCAL_INCLUDES" ]; then echo "=== $HEADER ===" >> "$DEPENDENCY_FILE" echo "$LOCAL_INCLUDES" >> "$DEPENDENCY_FILE" echo "" >> "$DEPENDENCY_FILE" fi done echo "Dependencies extracted to: $DEPENDENCY_FILE"
2c. Build Dependency Graph
Graph Structure (Adjacency List):
# Create adjacency list representation GRAPH_FILE="$OUTPUT_DIR/dependency_graph.txt" > "$GRAPH_FILE" echo "Building dependency graph..." for HEADER in $ALL_HEADERS; do # Get just the filename (without path) HEADER_NAME=$(basename "$HEADER") # Get all includes from this header INCLUDES=$(grep '^#include "' "$HEADER" | sed 's/#include "\(.*\)"/\1/' | xargs -n1 basename 2>/dev/null) # Write to graph file: source -> dependencies if [ ! -z "$INCLUDES" ]; then for INCLUDE in $INCLUDES; do echo "$HEADER_NAME -> $INCLUDE" >> "$GRAPH_FILE" done fi done echo "Dependency graph built: $GRAPH_FILE"
Step 3: Analyze Dependencies by Mode
Mode 1: Quick Circular Check
3a. Detect Circular Dependencies (DFS)
echo "=== Circular Dependency Detection ===" # Create Python script for cycle detection (more reliable than bash) cat > "$OUTPUT_DIR/detect_cycles.py" <<'PYTHON_SCRIPT' #!/usr/bin/env python3 import sys from collections import defaultdict def read_graph(graph_file): """Read dependency graph from file.""" graph = defaultdict(list) with open(graph_file, 'r') as f: for line in f: if '->' in line: source, target = line.strip().split(' -> ') graph[source].append(target) return graph def find_cycles_dfs(graph): """Find all cycles using DFS with recursion stack.""" visited = set() rec_stack = set() cycles = [] def dfs(node, path): visited.add(node) rec_stack.add(node) path.append(node) for neighbor in graph.get(node, []): if neighbor not in visited: dfs(neighbor, path.copy()) elif neighbor in rec_stack: # Found a cycle cycle_start = path.index(neighbor) cycle = path[cycle_start:] + [neighbor] cycles.append(cycle) rec_stack.remove(node) for node in graph: if node not in visited: dfs(node, []) return cycles def main(): if len(sys.argv) != 2: print("Usage: detect_cycles.py <graph_file>") sys.exit(1) graph_file = sys.argv[1] graph = read_graph(graph_file) print(f"Analyzing {len(graph)} nodes...") cycles = find_cycles_dfs(graph) if not cycles: print("✅ NO CIRCULAR DEPENDENCIES DETECTED") sys.exit(0) else: print(f"🔴 FOUND {len(cycles)} CIRCULAR DEPENDENCIES:") print() for i, cycle in enumerate(cycles, 1): print(f"Cycle {i}:") print(" " + " -> ".join(cycle)) print() sys.exit(1) if __name__ == '__main__': main() PYTHON_SCRIPT chmod +x "$OUTPUT_DIR/detect_cycles.py" # Run cycle detection python3 "$OUTPUT_DIR/detect_cycles.py" "$GRAPH_FILE" CYCLE_STATUS=$? if [ $CYCLE_STATUS -ne 0 ]; then echo "" echo "🔴 CIRCULAR DEPENDENCIES BLOCK COMPILATION" echo "Action: Break cycles using forward declarations or interface extraction" fi
3b. Suggest Fixes for Circular Dependencies
If cycles detected:
echo "" echo "=== Circular Dependency Fix Suggestions ===" # Read cycles from previous output # For each cycle, suggest: # 1. Forward declaration approach # 2. Interface extraction # 3. Dependency inversion # Example output: cat <<EOF Cycle: AIManager.hpp -> PathfinderManager.hpp -> AIManager.hpp Suggested Fixes: 1. Forward Declaration (RECOMMENDED): In AIManager.hpp: Remove: #include "PathfinderManager.hpp" Add: class PathfinderManager; // Forward declaration In AIManager.cpp: Add: #include "PathfinderManager.hpp" 2. Interface Extraction: Create IPathfinder.hpp with pure virtual interface AIManager depends on IPathfinder (no circular dependency) PathfinderManager implements IPathfinder 3. Dependency Inversion: Both managers depend on abstract interface GameEngine wires concrete implementations EOF
Mode 2: Coupling Analysis
3a. Calculate Coupling Metrics
Fan-Out (Efferent Coupling):
echo "=== Coupling Analysis ===" # For each component, count how many others it depends on echo "Fan-Out (Efferent Coupling - what this component depends on):" echo "" while IFS= read -r HEADER; do HEADER_NAME=$(basename "$HEADER") FAN_OUT=$(grep "^$HEADER_NAME ->" "$GRAPH_FILE" | wc -l) if [ "$FAN_OUT" -gt 0 ]; then # Classify coupling strength if [ "$FAN_OUT" -gt 15 ]; then STATUS="🔴 HIGH" elif [ "$FAN_OUT" -gt 10 ]; then STATUS="⚠️ MEDIUM" elif [ "$FAN_OUT" -gt 5 ]; then STATUS="🟡 MODERATE" else STATUS="✅ LOW" fi echo " $HEADER_NAME: $FAN_OUT dependencies - $STATUS" fi done <<< "$ALL_HEADERS" | sort -t: -k2 -rn | head -20 echo ""
Fan-In (Afferent Coupling):
echo "Fan-In (Afferent Coupling - what depends on this component):" echo "" while IFS= read -r HEADER; do HEADER_NAME=$(basename "$HEADER") FAN_IN=$(grep " -> $HEADER_NAME$" "$GRAPH_FILE" | wc -l) if [ "$FAN_IN" -gt 0 ]; then # High fan-in indicates core/stable component if [ "$FAN_IN" -gt 20 ]; then STATUS="⭐ CORE" elif [ "$FAN_IN" -gt 10 ]; then STATUS="📦 STABLE" elif [ "$FAN_IN" -gt 5 ]; then STATUS="🔧 UTILITY" else STATUS="📄 LEAF" fi echo " $HEADER_NAME: $FAN_IN dependents - $STATUS" fi done <<< "$ALL_HEADERS" | sort -t: -k2 -rn | head -20 echo ""
Instability Metric (I = Fan-Out / (Fan-In + Fan-Out)):
echo "Instability Metric (I = Efferent / (Afferent + Efferent)):" echo " 0.0 = Maximally Stable (hard to change)" echo " 1.0 = Maximally Unstable (easy to change)" echo "" while IFS= read -r HEADER; do HEADER_NAME=$(basename "$HEADER") FAN_OUT=$(grep "^$HEADER_NAME ->" "$GRAPH_FILE" | wc -l) FAN_IN=$(grep " -> $HEADER_NAME$" "$GRAPH_FILE" | wc -l) TOTAL=$((FAN_OUT + FAN_IN)) if [ "$TOTAL" -gt 0 ]; then # Calculate instability (using bc for float arithmetic) INSTABILITY=$(echo "scale=2; $FAN_OUT / $TOTAL" | bc) echo " $HEADER_NAME: I=$INSTABILITY (out=$FAN_OUT, in=$FAN_IN)" fi done <<< "$ALL_HEADERS" | head -20
3b. Manager-to-Manager Coupling
echo "" echo "=== Manager-to-Manager Coupling ===" # Find all manager headers MANAGERS=$(find include/managers -name "*.hpp" -type f 2>/dev/null) if [ -z "$MANAGERS" ]; then echo "No managers found in include/managers/" else # Build coupling matrix echo "Manager Coupling Matrix:" echo "" printf "%-25s" "Manager" # Header row for MGR in $MANAGERS; do MGR_NAME=$(basename "$MGR" .hpp) printf "%-8s" "${MGR_NAME:0:7}" done echo "" # Matrix rows for MGR1 in $MANAGERS; do MGR1_NAME=$(basename "$MGR1" .hpp) printf "%-25s" "$MGR1_NAME" for MGR2 in $MANAGERS; do MGR2_NAME=$(basename "$MGR2" .hpp) # Check if MGR1 includes MGR2 INCLUDES=$(grep -c "#include \"$MGR2_NAME.hpp\"" "$MGR1" 2>/dev/null || echo "0") if [ "$MGR1_NAME" = "$MGR2_NAME" ]; then printf "%-8s" "-" elif [ "$INCLUDES" -gt 0 ]; then printf "%-8s" "✓" else printf "%-8s" " " fi done echo "" done fi echo "" echo "Legend: ✓ = Direct dependency, - = Self, (blank) = No dependency" echo "" echo "Note: Manager-to-manager dependencies are EXPECTED in game engines." echo "Game systems must interact: AI needs collision, world needs events, etc."
3c. Coupling Strength Analysis
echo "" echo "=== Coupling Strength Analysis ===" # Define functional game engine dependencies (these are EXPECTED and CORRECT) # Format: "Manager1->Manager2" (these will NOT be flagged as problems) FUNCTIONAL_DEPS=( "AIManager->CollisionManager" "AIManager->PathfinderManager" "CollisionManager->WorldManager" "CollisionManager->EventManager" "WorldManager->EventManager" "WorldManager->WorldResourceManager" "WorldManager->TextureManager" "UIManager->FontManager" "UIManager->UIConstants" "InputManager->UIManager" "InputManager->FontManager" "PathfinderManager->EventManager" "ParticleManager->EventManager" "ResourceFactory->ResourceTemplateManager" "ResourceTemplateManager->ResourceFactory" "WorldResourceManager->EventManager" ) # Convert array to grep pattern FUNCTIONAL_PATTERN=$(printf "|%s" "${FUNCTIONAL_DEPS[@]}") FUNCTIONAL_PATTERN="${FUNCTIONAL_PATTERN:1}" # Remove leading | # For each manager pair with coupling, analyze strength TIGHT_COUPLING_COUNT=0 FUNCTIONAL_COUPLING_COUNT=0 for MGR1 in $MANAGERS; do MGR1_NAME=$(basename "$MGR1" .hpp) MGR1_CPP="src/managers/${MGR1_NAME}.cpp" if [ -f "$MGR1_CPP" ]; then for MGR2 in $MANAGERS; do MGR2_NAME=$(basename "$MGR2" .hpp) if [ "$MGR1_NAME" != "$MGR2_NAME" ]; then # Count references to MGR2 in MGR1's implementation REF_COUNT=$(grep -c "$MGR2_NAME" "$MGR1_CPP" 2>/dev/null || echo "0") if [ "$REF_COUNT" -gt 10 ]; then COUPLING_PAIR="${MGR1_NAME}->${MGR2_NAME}" # Check if this is a functional dependency if echo "$COUPLING_PAIR" | grep -qE "$FUNCTIONAL_PATTERN"; then echo "✅ FUNCTIONAL: $MGR1_NAME -> $MGR2_NAME ($REF_COUNT references)" echo " Status: Expected game system interaction (correct design)" FUNCTIONAL_COUPLING_COUNT=$((FUNCTIONAL_COUPLING_COUNT + 1)) else echo "🔴 TIGHT: $MGR1_NAME -> $MGR2_NAME ($REF_COUNT references)" echo " Review: Is this coupling necessary for game functionality?" TIGHT_COUPLING_COUNT=$((TIGHT_COUPLING_COUNT + 1)) fi elif [ "$REF_COUNT" -gt 5 ]; then echo "📊 MODERATE: $MGR1_NAME -> $MGR2_NAME ($REF_COUNT references)" fi fi done fi done echo "" echo "Summary:" echo " - Functional coupling (expected): $FUNCTIONAL_COUPLING_COUNT pairs" echo " - Tight coupling (review): $TIGHT_COUPLING_COUNT pairs" echo "" echo "Note: Functional coupling is CORRECT for game engines - systems must interact!"
Mode 3: Full Architecture Audit
3a. Layer Violation Detection
echo "=== Layer Violation Detection ===" # Define layers CORE_HEADERS=$(find include/core src/core -name "*.hpp" 2>/dev/null) MANAGER_HEADERS=$(find include/managers src/managers -name "*.hpp" 2>/dev/null) STATE_HEADERS=$(find include/gameStates src/gameStates -name "*.hpp" 2>/dev/null) ENTITY_HEADERS=$(find include/entities src/entities -name "*.hpp" 2>/dev/null) UTIL_HEADERS=$(find include/utils src/utils -name "*.hpp" 2>/dev/null) # Check Core layer (should not depend on anything) echo "1. Core Layer (should be dependency-free):" for CORE in $CORE_HEADERS; do VIOLATIONS=$(grep '#include "' "$CORE" | grep -v 'core/' | grep -v 'utils/' | wc -l) if [ "$VIOLATIONS" -gt 0 ]; then echo " 🔴 $(basename "$CORE"): includes non-Core/Utils headers" grep '#include "' "$CORE" | grep -v 'core/' | grep -v 'utils/' fi done # Check Manager layer (should not depend on States or Entities) echo "" echo "2. Manager Layer (should not depend on States/Entities):" for MGR in $MANAGER_HEADERS; do STATE_DEPS=$(grep '#include "' "$MGR" | grep -c 'gameStates/' 2>/dev/null || echo "0") ENTITY_DEPS=$(grep '#include "' "$MGR" | grep -c 'entities/' 2>/dev/null || echo "0") if [ "$STATE_DEPS" -gt 0 ] || [ "$ENTITY_DEPS" -gt 0 ]; then echo " 🔴 $(basename "$MGR"): violates layer boundaries" [ "$STATE_DEPS" -gt 0 ] && echo " - Includes State headers (forbidden)" [ "$ENTITY_DEPS" -gt 0 ] && echo " - Includes Entity headers (review needed)" fi done # Check State layer (should not depend on other States) echo "" echo "3. State Layer (states should not depend on each other):" for STATE1 in $STATE_HEADERS; do STATE1_NAME=$(basename "$STATE1") for STATE2 in $STATE_HEADERS; do STATE2_NAME=$(basename "$STATE2") if [ "$STATE1_NAME" != "$STATE2_NAME" ]; then if grep -q "#include \"$STATE2_NAME\"" "$STATE1" 2>/dev/null; then echo " 🔴 $STATE1_NAME -> $STATE2_NAME (cross-state dependency)" fi fi done done # Check Utils layer (should not depend on anything) echo "" echo "4. Utils Layer (should be dependency-free):" for UTIL in $UTIL_HEADERS; do NON_UTIL_DEPS=$(grep '#include "' "$UTIL" | grep -v 'utils/' | wc -l) if [ "$NON_UTIL_DEPS" -gt 0 ]; then echo " ⚠️ $(basename "$UTIL"): includes non-Utils headers" grep '#include "' "$UTIL" | grep -v 'utils/' fi done echo "" echo "Layer Violation Summary:" CORE_VIOLATIONS=$(find include/core src/core -name "*.hpp" -exec grep '#include "' {} \; | grep -v 'core/' | grep -v 'utils/' | wc -l) MANAGER_VIOLATIONS=$(find include/managers src/managers -name "*.hpp" -exec grep '#include "' {} \; | grep 'gameStates/' | wc -l) STATE_VIOLATIONS=0 # Count from previous check UTIL_VIOLATIONS=$(find include/utils src/utils -name "*.hpp" -exec grep '#include "' {} \; | grep -v 'utils/' | wc -l) TOTAL_VIOLATIONS=$((CORE_VIOLATIONS + MANAGER_VIOLATIONS + STATE_VIOLATIONS + UTIL_VIOLATIONS)) if [ "$TOTAL_VIOLATIONS" -eq 0 ]; then echo " ✅ No layer violations detected" else echo " 🔴 $TOTAL_VIOLATIONS layer violations found" fi
3b. Header Bloat Analysis
echo "" echo "=== Header Bloat Analysis ===" # Find headers with excessive includes echo "Headers with High Include Count (potential bloat):" echo "" for HEADER in $ALL_HEADERS; do INCLUDE_COUNT=$(grep -c '^#include "' "$HEADER") if [ "$INCLUDE_COUNT" -gt 15 ]; then echo " 🔴 $(basename "$HEADER"): $INCLUDE_COUNT includes (HIGH - review for bloat)" elif [ "$INCLUDE_COUNT" -gt 10 ]; then echo " ⚠️ $(basename "$HEADER"): $INCLUDE_COUNT includes (MODERATE)" fi done # Find commonly included heavy headers echo "" echo "Frequently Included Headers (ripple effect on compile times):" echo "" # Count how many files include each header while IFS= read -r HEADER; do HEADER_NAME=$(basename "$HEADER") INCLUDE_COUNT=$(grep -r "#include \"$HEADER_NAME\"" include/ src/ 2>/dev/null | wc -l) if [ "$INCLUDE_COUNT" -gt 10 ]; then echo " $HEADER_NAME: included by $INCLUDE_COUNT files" # Check if this header itself has many includes (bloat amplification) HEADER_INCLUDES=$(grep -c '^#include' "$HEADER" 2>/dev/null || echo "0") if [ "$HEADER_INCLUDES" -gt 10 ]; then echo " ⚠️ This header includes $HEADER_INCLUDES files (bloat amplification)" fi fi done <<< "$ALL_HEADERS" | sort -t: -k2 -rn | head -15
3c. Forward Declaration Opportunities
echo "" echo "=== Forward Declaration Opportunities ===" # Find headers that could use forward declarations # Pattern: Header includes another header but only uses pointers/references echo "Analyzing headers for forward declaration opportunities..." echo "" for HEADER in $ALL_HEADERS; do # Get all includes INCLUDES=$(grep '^#include "' "$HEADER" | sed 's/#include "\(.*\.hpp\)"/\1/') for INCLUDE in $INCLUDES; do INCLUDE_BASE=$(basename "$INCLUDE" .hpp) # Check if only used as pointer or reference # Look for: ClassName* or ClassName&, but NOT ClassName object; PTR_REF_ONLY=$(grep -c "${INCLUDE_BASE}[*&]" "$HEADER" 2>/dev/null || echo "0") DIRECT_USE=$(grep -c "${INCLUDE_BASE}[^*&];.*;" "$HEADER" 2>/dev/null || echo "0") if [ "$PTR_REF_ONLY" -gt 0 ] && [ "$DIRECT_USE" -eq 0 ]; then echo " ✨ $(basename "$HEADER"): Can forward-declare $INCLUDE_BASE" echo " Remove: #include \"$INCLUDE\"" echo " Add: class $INCLUDE_BASE; // Forward declaration" echo "" fi done done | head -30 # Limit output echo "Note: Move #include to .cpp file after forward declaration"
3d. Compile Time Impact Estimation
echo "" echo "=== Compile Time Impact Estimation ===" # Estimate compilation cost based on dependency depth echo "Dependency Depth (higher = more recompilation ripple):" echo "" # For each header, calculate max depth to leaf nodes # This is an approximation of compile time impact # Create depth calculation script cat > "$OUTPUT_DIR/calc_depth.py" <<'PYTHON_SCRIPT' #!/usr/bin/env python3 import sys from collections import defaultdict, deque def read_graph(graph_file): graph = defaultdict(list) with open(graph_file, 'r') as f: for line in f: if '->' in line: source, target = line.strip().split(' -> ') graph[source].append(target) return graph def calculate_depth(graph, node, memo=None): """Calculate max dependency depth using DFS with memoization.""" if memo is None: memo = {} if node in memo: return memo[node] if node not in graph or not graph[node]: memo[node] = 0 return 0 max_depth = 0 for neighbor in graph[node]: depth = calculate_depth(graph, neighbor, memo) max_depth = max(max_depth, depth + 1) memo[node] = max_depth return max_depth def main(): if len(sys.argv) != 2: print("Usage: calc_depth.py <graph_file>") sys.exit(1) graph = read_graph(sys.argv[1]) # Calculate depth for all nodes depths = {} for node in graph: depths[node] = calculate_depth(graph, node) # Sort by depth (highest first) sorted_depths = sorted(depths.items(), key=lambda x: x[1], reverse=True) print("Top 20 Headers by Dependency Depth:") print() for node, depth in sorted_depths[:20]: if depth > 10: status = "🔴 VERY HIGH" elif depth > 7: status = "⚠️ HIGH" elif depth > 4: status = "🟡 MODERATE" else: status = "✅ LOW" print(f" {node}: depth={depth} {status}") print() print("Note: High depth = changing this header causes cascading recompilation") if __name__ == '__main__': main() PYTHON_SCRIPT chmod +x "$OUTPUT_DIR/calc_depth.py" python3 "$OUTPUT_DIR/calc_depth.py" "$GRAPH_FILE" # Estimate total compile impact echo "" echo "Estimated Compile Time Impact:" TOTAL_DEPTH=$(python3 "$OUTPUT_DIR/calc_depth.py" "$GRAPH_FILE" 2>/dev/null | grep "depth=" | awk -F'depth=' '{print $2}' | awk '{print $1}' | paste -sd+ | bc) echo " Total dependency depth: $TOTAL_DEPTH" echo " Average per header: $(echo "scale=1; $TOTAL_DEPTH / $HEADER_COUNT" | bc)"
Mode 4: Specific Component Analysis
4a. Single Component Dependency Analysis
# User specified component (e.g., AIManager) COMPONENT="$USER_COMPONENT" COMPONENT_HEADER=$(find include/ src/ -name "${COMPONENT}.hpp" | head -1) if [ -z "$COMPONENT_HEADER" ]; then echo "❌ Component not found: $COMPONENT" exit 1 fi echo "=== Dependency Analysis: $COMPONENT ===" echo "" # What this component depends on (efferent) echo "1. What $COMPONENT depends on (Efferent Dependencies):" echo "" grep '^#include "' "$COMPONENT_HEADER" | sed 's/#include "\(.*\)"/ - \1/' EFFERENT_COUNT=$(grep -c '^#include "' "$COMPONENT_HEADER") echo "" echo " Total: $EFFERENT_COUNT direct dependencies" # What depends on this component (afferent) echo "" echo "2. What depends on $COMPONENT (Afferent Dependencies):" echo "" COMPONENT_NAME=$(basename "$COMPONENT_HEADER") DEPENDENTS=$(grep -r "#include \"$COMPONENT_NAME\"" include/ src/ 2>/dev/null | cut -d: -f1 | sort -u) if [ -z "$DEPENDENTS" ]; then echo " (None - this is a leaf component)" else echo "$DEPENDENTS" | while read DEP; do echo " - $(basename "$DEP")" done fi AFFERENT_COUNT=$(echo "$DEPENDENTS" | wc -l) echo "" echo " Total: $AFFERENT_COUNT dependent files" # Coupling metrics echo "" echo "3. Coupling Metrics:" echo " - Efferent Coupling (Fan-Out): $EFFERENT_COUNT" echo " - Afferent Coupling (Fan-In): $AFFERENT_COUNT" TOTAL=$((EFFERENT_COUNT + AFFERENT_COUNT)) if [ "$TOTAL" -gt 0 ]; then INSTABILITY=$(echo "scale=2; $EFFERENT_COUNT / $TOTAL" | bc) echo " - Instability (I): $INSTABILITY" if (( $(echo "$INSTABILITY > 0.8" | bc -l) )); then echo " → Highly unstable (easy to change, but volatile)" elif (( $(echo "$INSTABILITY < 0.2" | bc -l) )); then echo " → Highly stable (hard to change, but reliable)" else echo " → Balanced stability" fi fi # Layer check echo "" echo "4. Layer Classification:" if echo "$COMPONENT_HEADER" | grep -q "core/"; then echo " - Layer: Core" echo " - Should depend on: Nothing" elif echo "$COMPONENT_HEADER" | grep -q "managers/"; then echo " - Layer: Managers" echo " - Should depend on: Core, Utils" echo " - Should NOT depend on: States, other Managers (loosely coupled)" elif echo "$COMPONENT_HEADER" | grep -q "gameStates/"; then echo " - Layer: States" echo " - Should depend on: Core, Managers, Utils" echo " - Should NOT depend on: Other States" elif echo "$COMPONENT_HEADER" | grep -q "entities/"; then echo " - Layer: Entities" echo " - Should depend on: Core, Utils" elif echo "$COMPONENT_HEADER" | grep -q "utils/"; then echo " - Layer: Utils" echo " - Should depend on: Nothing" fi # Specific issues echo "" echo "5. Potential Issues:" # Check for layer violations VIOLATIONS=0 if echo "$COMPONENT_HEADER" | grep -q "managers/"; then STATE_DEPS=$(grep '#include "' "$COMPONENT_HEADER" | grep -c 'gameStates/' || echo "0") if [ "$STATE_DEPS" -gt 0 ]; then echo " 🔴 Includes State headers (layer violation)" VIOLATIONS=$((VIOLATIONS + 1)) fi fi if [ "$EFFERENT_COUNT" -gt 15 ]; then echo " ⚠️ High efferent coupling ($EFFERENT_COUNT dependencies)" VIOLATIONS=$((VIOLATIONS + 1)) fi # Check for circular dependencies involving this component COMPONENT_BASE=$(basename "$COMPONENT_HEADER") CYCLES=$(python3 "$OUTPUT_DIR/detect_cycles.py" "$GRAPH_FILE" 2>&1 | grep "$COMPONENT_BASE" || echo "") if [ ! -z "$CYCLES" ]; then echo " 🔴 Part of circular dependency" echo "$CYCLES" | sed 's/^/ /' VIOLATIONS=$((VIOLATIONS + 1)) fi if [ "$VIOLATIONS" -eq 0 ]; then echo " ✅ No issues detected" fi
Step 4: Generate Dependency Visualizations
4a. ASCII Dependency Tree
echo "" echo "=== Dependency Tree (ASCII) ===" # Create tree visualization script cat > "$OUTPUT_DIR/make_tree.sh" <<'TREE_SCRIPT' #!/bin/bash # Function to print tree recursively print_tree() { local node=$1 local prefix=$2 local visited=$3 local max_depth=$4 local current_depth=$5 # Prevent infinite loops if echo "$visited" | grep -q "|$node|"; then echo "${prefix}└── $node (circular)" return fi # Max depth limit if [ "$current_depth" -ge "$max_depth" ]; then echo "${prefix}└── $node (...)" return fi echo "${prefix}└── $node" # Get dependencies local deps=$(grep "^$node ->" "$GRAPH_FILE" | cut -d'>' -f2 | tr -d ' ') if [ ! -z "$deps" ]; then local new_visited="${visited}|${node}|" local new_depth=$((current_depth + 1)) echo "$deps" | while read dep; do print_tree "$dep" "${prefix} " "$new_visited" "$max_depth" "$new_depth" done fi } # Entry point GRAPH_FILE="$1" ROOT_NODE="$2" MAX_DEPTH="${3:-5}" print_tree "$ROOT_NODE" "" "" "$MAX_DEPTH" 0 TREE_SCRIPT chmod +x "$OUTPUT_DIR/make_tree.sh" # Generate trees for key components echo "" echo "GameEngine Dependency Tree:" "$OUTPUT_DIR/make_tree.sh" "$GRAPH_FILE" "GameEngine.hpp" 3 echo "" echo "AIManager Dependency Tree:" "$OUTPUT_DIR/make_tree.sh" "$GRAPH_FILE" "AIManager.hpp" 3
4b. Dependency Matrix (for report)
# Generate full dependency matrix for report echo "" echo "Generating dependency matrix for report..." cat > "$OUTPUT_DIR/dependency_matrix.txt" <<EOF # Dependency Matrix Rows depend on Columns (✓ = direct dependency) EOF # Get top 20 most connected headers TOP_HEADERS=$(cat "$GRAPH_FILE" | grep -o '[^ ]*\.hpp' | sort | uniq -c | sort -rn | head -20 | awk '{print $2}') # Print header row printf "%-25s" "Component" echo "$TOP_HEADERS" | while read HEADER; do HEADER_SHORT=$(echo "$HEADER" | cut -d'.' -f1 | cut -c1-7) printf "%-8s" "$HEADER_SHORT" done echo "" # Print matrix rows echo "$TOP_HEADERS" | while read ROW_HEADER; do printf "%-25s" "$(echo "$ROW_HEADER" | cut -d'.' -f1)" echo "$TOP_HEADERS" | while read COL_HEADER; do if [ "$ROW_HEADER" = "$COL_HEADER" ]; then printf "%-8s" "-" else HAS_DEP=$(grep "^$ROW_HEADER -> $COL_HEADER$" "$GRAPH_FILE") if [ ! -z "$HAS_DEP" ]; then printf "%-8s" "✓" else printf "%-8s" " " fi fi done echo "" done >> "$OUTPUT_DIR/dependency_matrix.txt" echo "Dependency matrix saved to: $OUTPUT_DIR/dependency_matrix.txt"
Step 5: Generate Architecture Health Report
Report Structure:
# HammerEngine Dependency Analysis Report **Generated:** YYYY-MM-DD HH:MM:SS **Branch:** <branch> **Commit:** <hash> **Analysis Mode:** <mode> --- ## Executive Summary **Architecture Health Score:** [85/100] (GOOD) **Status:** ✅ HEALTHY / ⚠️ NEEDS ATTENTION / 🔴 CRITICAL ISSUES **Key Findings:** - [Finding 1] - [Finding 2] - [Finding 3] **Overall Assessment:** [2-3 sentence summary] --- ## Dependency Statistics **Codebase Size:** - Total headers analyzed: [N] - Core layer: [N] files - Managers layer: [N] files - States layer: [N] files - Entities layer: [N] files - Utils layer: [N] files **Dependency Metrics:** - Total dependencies: [N] - Average dependencies per file: [X.X] - Max dependencies (single file): [N] - Circular dependencies: [N] 🔴/✅ --- ## Circular Dependencies (CRITICAL) [If none:] ✅ **NO CIRCULAR DEPENDENCIES DETECTED** All include hierarchies are acyclic. Compilation order is deterministic. [If found:] 🔴 **FOUND [N] CIRCULAR DEPENDENCIES** ### Cycle 1: [Component A] ↔ [Component B] **Cycle Path:**
ComponentA.hpp -> ComponentB.hpp -> ComponentA.hpp
**Impact:** Breaks compilation or requires workarounds **Suggested Fix:** 1. **Forward Declaration** (RECOMMENDED) - In ComponentA.hpp, replace `#include "ComponentB.hpp"` with `class ComponentB;` - Move include to ComponentA.cpp 2. **Interface Extraction** - Create IComponentB.hpp with pure virtual interface - ComponentA depends on interface (breaks cycle) [Repeat for each cycle] --- ## Coupling Analysis ### High-Coupling Components (Top 10) | Component | Fan-Out | Fan-In | Instability | Status | |-----------|---------|--------|-------------|--------| | [Component1] | 18 | 5 | 0.78 | 🔴 HIGH | | [Component2] | 15 | 12 | 0.55 | ⚠️ MODERATE | | [Component3] | 8 | 20 | 0.29 | ✅ STABLE | **Legend:** - **Fan-Out:** Number of dependencies (efferent coupling) - **Fan-In:** Number of dependents (afferent coupling) - **Instability:** Fan-Out / (Fan-In + Fan-Out) - 0.0 = Maximally stable (hard to change) - 1.0 = Maximally unstable (easy to change) ### Manager-to-Manager Coupling **Coupling Matrix:** [Include dependency matrix from Step 4b] **Manager Coupling Analysis:** **Important Context:** Game engines have **necessary functional dependencies**. Tight coupling between game systems is often **CORRECT and required** for the engine to function. **Functional Coupling (✅ Expected & Correct):** [List coupling pairs that serve game functionality] - AIManager → CollisionManager (AI obstacle avoidance, LOS checks) - CollisionManager → WorldManager (world geometry queries) - Managers → EventManager (event-driven notifications) - UIManager → FontManager (text rendering) - etc. **Status:** ✅ These dependencies are functionally necessary and represent correct game engine architecture. **Problematic Coupling (🔴 Review Required):** [If any non-functional tight coupling exists] 1. **[Manager1] → [Manager2]** (N references) - Status: 🔴 REVIEW - Reason: Unclear functional necessity - Recommendation: Verify this coupling serves game functionality [If none:] ✅ **NO PROBLEMATIC COUPLING** All tight coupling serves clear game system functionality. --- ## Layer Violations ### Layer Integrity Check **Core Layer** (should depend on nothing): [✅ CLEAN / 🔴 [N] violations] **Managers Layer** (should depend on Core, Utils only): [✅ CLEAN / 🔴 [N] violations] **States Layer** (no cross-state dependencies): [✅ CLEAN / 🔴 [N] violations] **Utils Layer** (should be dependency-free): [✅ CLEAN / 🔴 [N] violations] ### Violation Details [If violations found:] **Violation 1: AIManager includes PlayingState.hpp** - **File:** include/managers/AIManager.hpp:15 - **Issue:** Manager layer depending on State layer - **Impact:** Violates layered architecture, creates tight coupling - **Fix:** Remove include, use interface or event system [Repeat for each violation] [If none:] ✅ **NO LAYER VIOLATIONS** All components respect layered architecture boundaries. --- ## Header Bloat Analysis ### High-Include Headers | Header | #Includes | Status | Dependents | |--------|-----------|--------|-----------| | [Header1] | 22 | 🔴 HIGH | 15 files | | [Header2] | 18 | ⚠️ MODERATE | 8 files | **Bloat Amplification:** Headers with many includes that are widely used cause compilation ripple effects. **Worst Offenders:** 1. **GameEngine.hpp** - 22 includes, used by 15 files - Ripple effect: ~330 transitive includes - Recommendation: Split into GameEngine_fwd.hpp with forward declarations ### Forward Declaration Opportunities [Top 10 opportunities from Step 3c] **Estimated Compile Time Savings:** ~15-25% reduction --- ## Dependency Depth Analysis ### Compile Time Impact | Header | Depth | Impact | Recommendation | |--------|-------|--------|----------------| | [Header1] | 14 | 🔴 VERY HIGH | Reduce dependencies | | [Header2] | 9 | ⚠️ HIGH | Consider splitting | | [Header3] | 6 | 🟡 MODERATE | Monitor | **Total Dependency Depth:** [N] **Average Depth:** [X.X] **High-Depth Components:** Changing these headers causes cascading recompilation: - [List top 5 highest depth headers] **Recommendation:** Use forward declarations and split large headers --- ## Architecture Health Scorecard | Category | Score | Weight | Weighted | Status | |----------|-------|--------|----------|--------| | Circular Dependencies | [X/10] | 30% | [X.X] | 🔴/⚠️/✅ | | Layer Compliance | [X/10] | 25% | [X.X] | 🔴/⚠️/✅ | | Coupling Strength | [X/10] | 20% | [X.X] | 🔴/⚠️/✅ | | Header Bloat | [X/10] | 15% | [X.X] | 🔴/⚠️/✅ | | Dependency Depth | [X/10] | 10% | [X.X] | 🔴/⚠️/✅ | | **TOTAL** | | **100%** | **[XX/100]** | **[GRADE]** | **Grading Scale:** - 90-100: A+ (Excellent architecture) - 80-89: A (Good architecture, minor issues) - 70-79: B (Fair architecture, needs improvement) - 60-69: C (Poor architecture, refactoring required) - Below 60: F (Critical issues, major refactoring needed) --- ## Recommendations ### Critical (Fix Immediately) 1. **Break Circular Dependencies** ([N] found) - Use forward declarations - Extract interfaces - Priority: HIGH, Effort: 2-4 hours 2. **Fix Layer Violations** ([N] found) - Remove inappropriate includes - Use event system for cross-layer communication - Priority: HIGH, Effort: 1-2 hours ### Important (Address Soon) 3. **Review Non-Functional Coupling (if any)** - [Only list coupling that doesn't serve clear game functionality] - Verify: Does this coupling serve a game system requirement? - If yes: Document the functional reason, no change needed - If no: Consider refactoring or event-based communication - Priority: MEDIUM (only if problematic coupling exists) 4. **Optimize High-Include Headers** - Split [Header] into interface and implementation - Add forward declaration headers - Priority: MEDIUM, Effort: 2-3 hours **Note:** Do NOT refactor functional game system dependencies. Coupling between managers is often necessary and correct for game engines. ### Optional (Consider) 5. **Improve Compile Times** - Apply forward declaration opportunities - Split large headers - Expected improvement: 15-25% faster compilation - Priority: LOW, Effort: 3-5 hours --- ## Dependency Visualizations ### GameEngine Dependency Tree [ASCII tree from Step 4a] ### AIManager Dependency Tree [ASCII tree from Step 4a] ### Full Dependency Matrix [Link to or include dependency_matrix.txt] --- ## Comparison with Previous Analysis (if baseline exists) | Metric | Previous | Current | Change | Trend | |--------|----------|---------|--------|-------| | Total Dependencies | [N] | [N] | [+/-N] | 📈/📉/➡️ | | Circular Dependencies | [N] | [N] | [+/-N] | 📈/📉/➡️ | | Layer Violations | [N] | [N] | [+/-N] | 📈/📉/➡️ | | Average Coupling | [X.X] | [X.X] | [+/-X.X] | 📈/📉/➡️ | | Health Score | [XX] | [XX] | [+/-XX] | 📈/📉/➡️ | **Overall Trend:** [Improving/Stable/Degrading] --- ## Action Plan ### Immediate (This Week) - [ ] Break circular dependency: [Cycle description] - [ ] Fix layer violation: [Specific violation] ### Short-term (This Month) - [ ] Reduce coupling between [Component1] and [Component2] - [ ] Split high-include headers: [Header list] - [ ] Apply top 5 forward declaration opportunities ### Long-term (This Quarter) - [ ] Comprehensive header cleanup - [ ] Establish pre-commit dependency checks - [ ] Document architecture patterns --- ## Files Requiring Attention Based on analysis, these files need modification: **High Priority:** - [File1] - Circular dependency - [File2] - Layer violation **Medium Priority:** - [File3] - High coupling - [File4] - Header bloat **Low Priority:** - [File5] - Forward declaration opportunity --- ## Next Steps 1. **Review this report** with team/architect 2. **Prioritize fixes** based on impact and effort 3. **Create tickets** for identified issues 4. **Re-run analysis** after fixes to verify improvements 5. **Schedule regular audits** (monthly recommended) **Re-run Analysis:** ```bash # After fixes, verify improvements [Command to re-invoke skill]
Report Generated By: hammer-dependency-analyzer Skill Report Saved To:
docs/architecture/dependency_analysis_YYYY-MM-DD.md
**Save report:** ```bash REPORT_FILE="docs/architecture/dependency_analysis_$(date +%Y-%m-%d).md" mkdir -p "docs/architecture" cat > "$REPORT_FILE" <<'EOF' [Generated markdown report] EOF echo "✅ Dependency analysis report saved to: $REPORT_FILE"
Step 6: Console Summary
=== HammerEngine Dependency Analysis === Mode: [Mode Name] Files Analyzed: [N] headers Architecture Health: [Score]/100 ([GRADE]) Circular Dependencies: [N] 🔴/✅ Layer Violations: [N] 🔴/✅ High Coupling: [N] components ⚠️ Header Bloat: [N] headers 🔴/⚠️ [If issues:] Status: 🔴 CRITICAL ISSUES / ⚠️ NEEDS ATTENTION Critical Issues: - [Issue 1] - [Issue 2] Recommendations: 1. [Top recommendation] 2. [Second recommendation] [If clean:] Status: ✅ ARCHITECTURE HEALTHY All checks passed: ✅ No circular dependencies ✅ No layer violations ✅ Coupling within acceptable limits ✅ No excessive header bloat Full Report: docs/architecture/dependency_analysis_YYYY-MM-DD.md Next: [Suggested action based on results]
Usage Examples
When the user says:
- "analyze dependencies"
- "check architecture health"
- "find circular dependencies"
- "check manager coupling"
- "analyze AIManager dependencies"
- "audit header dependencies"
Activate this Skill automatically.
Integration with Development Workflow
Use this Skill:
Regular Maintenance
- Monthly audits - Catch architectural drift early
- After major refactors - Verify improvements
- Before releases - Ensure architecture quality
Development Checkpoints
- Adding new manager - Verify coupling is appropriate
- Refactoring existing code - Check impact on dependencies
- Investigating compile times - Identify bloat and depth issues
Problem Investigation
- Circular dependency errors - Find and break cycles
- Slow compilation - Identify high-depth headers
- Tight coupling concerns - Analyze manager interactions
Common Dependency Issues in HammerEngine
Issue 1: Manager Circular Dependencies
Symptom: Compilation errors with forward declaration issues Cause: Two managers including each other's headers Solution: One-way dependency with interface or event system
Issue 2: State-to-State Dependencies
Symptom: States including other state headers Cause: Sharing data/logic between states Solution: Move shared logic to Manager or GameEngine
Issue 3: GameEngine.hpp Bloat
Symptom: Long compile times for any GameEngine change Cause: GameEngine includes all managers in header Solution: Forward declarations + includes in .cpp
Issue 4: Layer Violations
Symptom: Manager includes State header Cause: Manager needs state-specific logic Solution: Dependency inversion - state registers callback with manager
Issue 5: Utils Dependencies
Symptom: Utils including Core or Manager headers Cause: Utils trying to use engine-specific types Solution: Make Utils pure (STL only), or move to appropriate layer
Performance Expectations
- Quick Circular Check: 2-3 minutes (scan + cycle detection)
- Coupling Analysis: 5-10 minutes (metrics + matrix)
- Full Architecture Audit: 15-20 minutes (all checks + visualization)
- Specific Component: 3-5 minutes (single component deep dive)
Manual Equivalent: 60-120 minutes per full audit
Exit Codes
- 0: No architectural issues detected
- 1: Circular dependencies found (BLOCKING)
- 2: Layer violations detected (CRITICAL)
- 3: High coupling detected (WARNING)
- 4: Multiple issues detected
Important Notes
- Run regularly - Architecture degrades over time without monitoring
- Fix issues promptly - Small issues compound into major refactors
- Document patterns - Share good architectural examples with team
- Automate checks - Consider pre-commit hooks for critical violations
- Track trends - Monitor health score over time
- Game Engine Context - Remember that tight manager coupling is often functionally necessary
Scoring Guidance for Game Engines
Coupling Strength Score Calculation:
When scoring coupling (20% of health score), distinguish between:
-
Functional Coupling (✅ Good, score: 8-10/10)
- Game systems that must interact to work
- Examples: AI→Collision, Collision→World, Managers→Events
- These are correct design and should NOT reduce the score significantly
-
Problematic Coupling (🔴 Bad, score: 0-4/10)
- Circular dependencies (breaks compilation)
- Layer violations (Manager→State)
- Unclear/unnecessary dependencies
Scoring Formula:
Coupling Score = 10 - (problematic_coupling_count * 1.5) Where problematic_coupling_count = - Circular dependencies found - Layer-violating dependencies - Non-functional tight coupling (unclear purpose) Functional coupling does NOT reduce score.
Example:
- 0 problematic, 9 functional: Score = 10/10 ✅ Excellent
- 1-2 problematic, 9 functional: Score = 7-8.5/10 ✅ Good
- 3-5 problematic, 9 functional: Score = 4-6/10 ⚠️ Needs work
- 6+ problematic: Score = 0-2/10 🔴 Critical
This scoring recognizes that game engines NEED manager coupling to function.
Ready to analyze HammerEngine architecture. Ask user for analysis mode.