HammerEngine 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.