Centrality Metrics
Centrality Metrics
Section titled “Centrality Metrics”Overview
Section titled “Overview”Centrality metrics measure the importance and influence of modules in your dependency graph. They help identify critical nodes (hubs, bottlenecks) that have disproportionate impact on system stability and change propagation.
This plugin provides two types of centrality measures:
- Degree Centrality (Fan-in/Fan-out) - Based on direct connections
- Betweenness Centrality - Based on position in shortest paths
What It Measures
Section titled “What It Measures”Degree Centrality (Fan-in/Fan-out)
Section titled “Degree Centrality (Fan-in/Fan-out)”centrality.module.max_fan_in: Maximum in-degree (most depended-upon module)centrality.module.max_fan_out: Maximum out-degree (module with most dependencies)centrality.module.avg_fan_in: Average in-degree across all modulescentrality.module.avg_fan_out: Average out-degree across all modulescentrality.module.median_fan_in: Median in-degree (robust to outliers)centrality.module.median_fan_out: Median out-degree (robust to outliers)centrality.module.hub_count: Number of hub modules (fan-in + fan-out > 10) - legacy metric
Hub-like Dependencies
Section titled “Hub-like Dependencies”Hub-like dependencies are modules that exhibit both high in-degree AND high out-degree, making them critical architectural nodes that require special attention.
centrality.module.hub_like_count: Total number of hub-like dependency modulescentrality.module.hub_like_severe_count: Severe hubs (95th percentile + high betweenness)centrality.module.hub_like_moderate_count: Moderate hubs (90th percentile)centrality.module.hub_like_mild_count: Mild hubs (75th percentile)
Hub detection uses statistical thresholds (percentiles) rather than fixed values, making it adaptive to your codebase size. A hub must have both high fan-in and high fan-out, distinguishing it from simple utility modules (high fan-in only) or fragile modules (high fan-out only).
Betweenness Centrality
Section titled “Betweenness Centrality”centrality.module.betweenness_max: Maximum betweenness centrality valuecentrality.module.betweenness_avg: Average betweenness centralitycentrality.module.high_betweenness_count: Number of nodes with high betweenness (> 0.1)
Why It Matters
Section titled “Why It Matters”High Fan-in (Many Dependents)
Section titled “High Fan-in (Many Dependents)”Indicates:
- Core utility or shared infrastructure
- High reusability (good)
- Single point of failure (risk)
- Breaking changes affect many modules
Examples:
- Shared utilities (
utils/,common/) - Core types/interfaces
- Configuration modules
High Fan-out (Many Dependencies)
Section titled “High Fan-out (Many Dependencies)”Indicates:
- Fragile module (depends on many things)
- High coupling (risk)
- Likely to break when dependencies change
- Difficult to test in isolation
Examples:
- Orchestration modules
- Feature modules that aggregate functionality
- Legacy code with accumulated dependencies
Hub-like Dependencies (High Fan-in + Fan-out)
Section titled “Hub-like Dependencies (High Fan-in + Fan-out)”Indicates:
- Critical architectural nodes that both depend on many modules AND are depended upon by many
- High impact on system stability and change propagation
- Potential bottlenecks and single points of failure
- Require careful design, comprehensive testing, and documentation
Severity Levels:
- Severe: Both fan-in and fan-out exceed 95th percentile AND high betweenness (>0.1) - immediate refactoring priority
- Moderate: Both fan-in and fan-out exceed 90th percentile - monitor closely
- Mild: Both fan-in and fan-out exceed 75th percentile - consider splitting if growing
Why this matters: Unlike simple high fan-in (utilities) or high fan-out (fragile modules), hub-like dependencies combine both characteristics, making them architectural hotspots where changes ripple through the system in multiple directions.
High Betweenness Centrality
Section titled “High Betweenness Centrality”Indicates:
- Module acts as a “bridge” between parts of the system
- Many dependency paths flow through this node
- Critical bottleneck - if it breaks, many paths are disrupted
- Good candidate for refactoring to reduce coupling
Interpretation
Section titled “Interpretation”Fan-in/Fan-out Guidelines
Section titled “Fan-in/Fan-out Guidelines”| Metric | Good | Warning | Critical |
|---|---|---|---|
max_fan_in | < 15 | 15-30 | > 30 |
max_fan_out | < 10 | 10-20 | > 20 |
avg_fan_in | < 3 | 3-5 | > 5 |
avg_fan_out | < 2 | 2-4 | > 4 |
hub_count | < 3 | 3-10 | > 10 |
hub_like_count | < 2 | 2-5 | > 5 |
hub_like_severe_count | 0 | 1 | > 1 |
Betweenness Centrality Guidelines
Section titled “Betweenness Centrality Guidelines”| Metric | Good | Warning | Critical |
|---|---|---|---|
betweenness_max | < 0.05 | 0.05-0.15 | > 0.15 |
betweenness_avg | < 0.01 | 0.01-0.03 | > 0.03 |
high_betweenness_count | < 2 | 2-5 | > 5 |
Examples
Section titled “Examples”Well-balanced system:
centrality.module.max_fan_in: 12centrality.module.max_fan_out: 8centrality.module.avg_fan_in: 2.3centrality.module.avg_fan_out: 1.8centrality.module.hub_count: 2centrality.module.betweenness_max: 0.04centrality.module.high_betweenness_count: 1Dependencies are distributed, no single module dominates.
Hub-heavy system:
centrality.module.max_fan_in: 45centrality.module.max_fan_out: 28centrality.module.avg_fan_in: 4.2centrality.module.avg_fan_out: 3.1centrality.module.hub_count: 15centrality.module.betweenness_max: 0.22centrality.module.high_betweenness_count: 8Too many critical nodes; system is fragile.
Policy Recommendations
Section titled “Policy Recommendations”For New Projects (Strict)
Section titled “For New Projects (Strict)”policy: invariants: - metric: centrality.module.max_fan_in op: "<=" value: 15 - metric: centrality.module.max_fan_out op: "<=" value: 10 - metric: centrality.module.hub_count op: "<=" value: 3 - metric: centrality.module.hub_like_count op: "<=" value: 2 - metric: centrality.module.hub_like_severe_count op: "==" value: 0 - metric: centrality.module.betweenness_max op: "<=" value: 0.05For Legacy Refactoring (Pragmatic)
Section titled “For Legacy Refactoring (Pragmatic)”policy: invariants: - metric: centrality.module.max_fan_in op: "<=" value: 30 - metric: centrality.module.max_fan_out op: "<=" value: 20 - metric: centrality.module.hub_count op: "<=" value: 10 - metric: centrality.module.hub_like_count op: "<=" value: 5 - metric: centrality.module.hub_like_severe_count op: "<=" value: 1 - metric: centrality.module.betweenness_max op: "<=" value: 0.15With Regression Prevention
Section titled “With Regression Prevention”policy: baseline: mode: git ref: origin/main no_regression: true # Hub count and max fan-out must not increaseHow to Improve Centrality Metrics
Section titled “How to Improve Centrality Metrics”1. Identify Problem Modules
Section titled “1. Identify Problem Modules”Check centrality entries in metric data:
centrality.module.nodes_table: Per-module fan-in/fan-out, betweenness, closeness, and PageRankcentrality.edge.top_bottlenecks_table: Top dependency bridge edges by edge betweennessfindings: Prioritized hub/bottleneck recommendations with evidence
2. Reduce Fan-out (Dependencies)
Section titled “2. Reduce Fan-out (Dependencies)”Extract shared code:
// Before: Module depends on 15 different utilitiesimport { util1 } from './utils/util1';import { util2 } from './utils/util2';// ... 13 more imports
// After: Single facadeimport { utils } from './utils';Use dependency injection:
// Before: Direct dependenciesclass Service { constructor() { this.db = new Database(); this.cache = new Cache(); this.logger = new Logger(); }}
// After: Injected dependenciesclass Service { constructor(deps: ServiceDependencies) { this.db = deps.db; this.cache = deps.cache; this.logger = deps.logger; }}Apply facade pattern:
// Create a single interface for related functionalityexport { api } from './api-facade';3. Reduce Fan-in (Dependents)
Section titled “3. Reduce Fan-in (Dependents)”Split large utilities:
// Before: One giant utils module// utils/index.ts (imported by 40 modules)
// After: Domain-specific utilities// utils/string.ts// utils/date.ts// utils/validation.tsCreate focused interfaces:
// Instead of one large types module, split by domain// types/product.ts// types/order.ts4. Reduce Betweenness Centrality
Section titled “4. Reduce Betweenness Centrality”Break critical paths:
Before: A → B → C → D E → B → F G → B → H(B has high betweenness)
After: A → C → D E → F G → H(Remove B, create direct connections)Use event-driven architecture:
// Instead of direct dependencies through a hub// Use events/messageseventBus.emit('user.created', userData);5. Monitor Hub Modules
Section titled “5. Monitor Hub Modules”Hub modules (high fan-in + fan-out) need special attention:
- Add comprehensive tests
- Document dependencies clearly
- Consider splitting if too large
- Use dependency injection for testability
Use Cases
Section titled “Use Cases”Identifying Core Infrastructure
Section titled “Identifying Core Infrastructure”High fan-in modules are often core infrastructure:
# Look for modules with fan-in > 20centrality.module.max_fan_in: 25# Inspect centrality.module.nodes_table and sort by fan_inFinding Fragile Modules
Section titled “Finding Fragile Modules”High fan-out modules are fragile:
# Modules with fan-out > 15 are riskycentrality.module.max_fan_out: 18# Inspect centrality.module.nodes_table and sort by fan_outDetecting Architectural Bottlenecks
Section titled “Detecting Architectural Bottlenecks”High betweenness indicates bottlenecks:
# Nodes with betweenness > 0.1 are criticalcentrality.module.betweenness_max: 0.15centrality.module.high_betweenness_count: 3# Inspect centrality.module.nodes_table and sort by betweennessRefactoring Prioritization
Section titled “Refactoring Prioritization”Combine metrics to prioritize:
- High priority: High fan-out + high betweenness (fragile bottleneck)
- Medium priority: High fan-in + high betweenness (critical hub)
- Low priority: High fan-in only (stable core)
Academic Background
Section titled “Academic Background”Degree Centrality
Section titled “Degree Centrality”Degree centrality is one of the simplest and most intuitive centrality measures in network analysis. It’s been used in software engineering since the 1990s to identify:
- God classes (high fan-out)
- Utility classes (high fan-in)
- Hub components
Betweenness Centrality
Section titled “Betweenness Centrality”Betweenness centrality was introduced by Freeman (1977) in social network analysis and adapted for software dependency graphs. It measures:
“The extent to which a node lies on paths between other nodes”
In software architecture:
- High betweenness = critical dependency path
- Removing high-betweenness nodes can break many connections
- Useful for identifying refactoring targets
Algorithm: Brandes’ algorithm (O(V × E) for unweighted graphs)
Technical Details
Section titled “Technical Details”- Algorithm:
- Degree: Direct neighbor counting (O(V + E))
- Betweenness: Brandes’ algorithm (O(V × E))
- Requires: Import graph
- Cache: Results are cached; recomputed only when graph changes
- Normalization: Betweenness is normalized by (n-1)(n-2) for directed graphs
Related Metrics
Section titled “Related Metrics”- Propagation Cost: High fan-out increases propagation cost
- SCC: Hub modules often participate in cycles
- Core-Periphery: High fan-in nodes are often in the core
- Modularity Q: Hub modules can reduce modularity scores
References
Section titled “References”- Freeman, L. C. (1977). “A set of measures of centrality based on betweenness”
- Brandes, U. (2001). “A faster algorithm for betweenness centrality”
- Martin, R. C. (2002). “Agile Software Development: Principles, Patterns, and Practices”
- Lanza, M., & Marinescu, R. (2006). “Object-Oriented Metrics in Practice”