https://github.com/nwiizo/cargo-coupling
A coupling analysis tool for Rust projects - measuring the 'right distance' in your code
https://github.com/nwiizo/cargo-coupling
Last synced: 3 months ago
JSON representation
A coupling analysis tool for Rust projects - measuring the 'right distance' in your code
- Host: GitHub
- URL: https://github.com/nwiizo/cargo-coupling
- Owner: nwiizo
- License: mit
- Created: 2025-12-18T16:02:52.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2026-01-02T00:07:52.000Z (3 months ago)
- Last Synced: 2026-01-05T23:19:37.391Z (3 months ago)
- Language: Rust
- Homepage: https://crates.io/crates/cargo-coupling
- Size: 900 KB
- Stars: 58
- Watchers: 1
- Forks: 2
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- fucking-awesome-rust - cargo-coupling - A Rust coupling analysis tool using Vlad Khononov's "Balancing Coupling in Software Design" framework (Development tools / Static analysis)
- awesome-rust - cargo-coupling - A Rust coupling analysis tool using Vlad Khononov's "Balancing Coupling in Software Design" framework (Development tools / Static analysis)
- awesome-rust-with-stars - cargo-coupling - 12-29 | (Development tools / Static analysis)
README
# cargo-coupling
[](https://crates.io/crates/cargo-coupling)
[](https://opensource.org/licenses/MIT)
[](https://www.rust-lang.org)
**Measure the "right distance" in your Rust code.**
`cargo-coupling` analyzes coupling in Rust projects based on Vlad Khononov's "Balancing Coupling in Software Design" framework. It calculates a **Balance Score** from three core dimensions: **Integration Strength**, **Distance**, and **Volatility**.

> ⚠️ **Experimental Project**
>
> This tool is currently experimental. The scoring algorithms, thresholds, and detected patterns are subject to change based on real-world feedback.
>
> **We want your input!** If you try this tool on your project, please share your experience:
> - Are the grades and scores meaningful for your codebase?
> - Are there false positives or patterns that shouldn't be flagged?
> - What additional metrics would be useful?
>
> Please open an issue at [GitHub Issues](https://github.com/nwiizo/cargo-coupling/issues) to discuss. Your feedback helps improve the tool for everyone.
## Quick Start
### 1. Install
```bash
cargo install cargo-coupling
```
Or use Docker:
```bash
docker pull ghcr.io/nwiizo/cargo-coupling
```
### 2. Analyze
```bash
# Analyze current project (default: shows only important issues)
cargo coupling ./src
# Show summary only
cargo coupling --summary ./src
# Japanese output with explanations (日本語出力)
cargo coupling --summary --japanese ./src
cargo coupling --summary --jp ./src
# Show all issues including Low severity
cargo coupling --summary --all ./src
```
### 3. Refactor with AI
```bash
# Generate AI-friendly output
cargo coupling --ai ./src
```
Copy the output and use this prompt with Claude, Copilot, or any AI coding assistant:
```
The following is the output of `cargo coupling --ai`, which analyzes coupling issues in a Rust project.
For each issue, suggest specific code changes to reduce coupling.
Focus on introducing traits, moving code closer, or breaking circular dependencies.
```
Example output:
```
Coupling Issues in my-project:
────────────────────────────────────────────────────────────
Grade: B (Good) | Score: 0.88 | Issues: 0 High, 5 Medium
Issues:
1. 🟡 api::handler → db::internal::Query
Type: Global Complexity
Problem: Intrusive coupling to db::internal::Query across module boundary
Fix: Introduce trait `QueryTrait` with methods: // Extract required methods
2. 🟡 25 dependents → core::types
Type: High Afferent Coupling
Problem: Module core::types is depended on by 25 other components
Fix: Introduce trait `TypesInterface` with methods: // Define stable public API
```
The AI will analyze patterns and suggest specific refactoring strategies.
### 4. Interactive Web Visualization (Experimental)
> ⚠️ **Experimental Feature**: The Web UI is currently in an experimental state. The interface, features, and behavior may change significantly in future versions.

```bash
# Start interactive web UI
cargo coupling --web ./src
# Custom port
cargo coupling --web --port 8080 ./src
```
The web UI provides:
- Interactive graph visualization with Cytoscape.js
- **Hotspots panel**: Top refactoring targets ranked by severity
- **Blast Radius**: Impact analysis with risk score
- **Clusters**: Architecture grouping detection
- Filtering by strength, distance, volatility, balance score
- Source code viewing with syntax highlighting
### 5. Job-Focused CLI Commands
For quick, focused analysis without opening the web UI:
```bash
# Find top refactoring targets
cargo coupling --hotspots ./src
cargo coupling --hotspots=10 ./src
# With beginner-friendly explanations
cargo coupling --hotspots --verbose ./src
# Analyze change impact for a specific module
cargo coupling --impact main ./src
cargo coupling --impact analyzer ./src
# Trace dependencies for a specific function or type
cargo coupling --trace analyze_file ./src
cargo coupling --trace BalanceScore ./src
# CI/CD quality gate (exits with code 1 on failure)
cargo coupling --check ./src
cargo coupling --check --min-grade=B ./src
cargo coupling --check --max-critical=0 --max-circular=0 ./src
# Machine-readable JSON output
cargo coupling --json ./src
cargo coupling --json ./src | jq '.hotspots[0]'
```
Example `--hotspots --verbose` output:
```
#1 my-project::main (Score: 55)
🟡 Medium: High Efferent Coupling
💡 What it means:
This module depends on too many other modules
⚠️ Why it's a problem:
• Changes elsewhere may break this module
• Testing requires many mocks/stubs
• Hard to understand in isolation
🔧 How to fix:
Split into smaller modules with clear responsibilities
e.g., Split main.rs into cli.rs, config.rs, runner.rs
```
### More Options
```bash
# Generate detailed report to file
cargo coupling -o report.md ./src
# Show timing information
cargo coupling --summary --timing ./src
# Use 4 threads for parallel processing
cargo coupling -j 4 ./src
# Skip Git history analysis for faster results
cargo coupling --no-git ./src
```
## Features
- **3-Dimensional Balance Score**: Calculates coupling balance based on **Integration Strength**, **Distance**, and **Volatility** (0.0 - 1.0)
- **Khononov Balance Formula**: `BALANCE = (STRENGTH XOR DISTANCE) OR NOT VOLATILITY`
- **Interactive Web UI**: `--web` flag starts a browser-based visualization with graph, hotspots, and blast radius analysis
- **Job-Focused CLI**: Quick commands for common tasks (`--hotspots`, `--impact`, `--check`, `--json`)
- **Japanese Support**: `--japanese` / `--jp` flag for Japanese output with explanations and design decision matrix
- **Noise Reduction**: Default strict mode hides Low severity issues (`--all` to show all)
- **Beginner-Friendly**: `--verbose` flag explains issues in plain language with fix examples
- **CI/CD Quality Gate**: `--check` command with configurable thresholds and exit codes
- **AI-Friendly Output**: `--ai` flag generates output optimized for coding agents (Claude, Copilot, etc.)
- **Rust Pattern Detection**: Detects newtype usage, serde derives, public fields, primitive obsession
- **Issue Detection**: Automatically identifies problematic coupling patterns (God Module, etc.)
- **Circular Dependency Detection**: Detects and reports dependency cycles
- **Visibility Tracking**: Analyzes Rust visibility modifiers (pub, pub(crate), etc.)
- **Git Integration**: Analyzes change frequency from Git history for volatility scoring
- **Configuration File**: Supports `.coupling.toml` for volatility overrides
- **Parallel Processing**: Uses Rayon for fast analysis of large codebases
- **Configurable Thresholds**: Customize dependency limits via CLI or config
- **Markdown Reports**: Generates detailed analysis reports
- **Cargo Integration**: Works as a cargo subcommand
## Khononov's Coupling Balance
**Coupling Balance** is a framework proposed by Vlad Khononov that evaluates coupling between modules across three dimensions to guide design decisions.
### Core Principle
Coupling is not inherently bad. What matters is **the balance between coupling strength, distance, and volatility**.
## The Three Dimensions
### 1. Strength (Integration Strength)
Represents how tightly components depend on each other.
| Level | Description | Rust Example | Score |
|-------|-------------|--------------|-------|
| **Intrusive** | Direct dependency on internal implementation | Direct access to `struct.field` | 1.00 (strong) |
| **Functional** | Dependency on behavior | Method calls on concrete types | 0.75 |
| **Model** | Dependency on data structures | Sharing type definitions | 0.50 |
| **Contract** | Dependency on interfaces only | Access via `trait` | 0.25 (weak) |
→ Lower in the table = **weaker** coupling (preferred)
### 2. Distance
The physical or logical distance between dependent components.
| Level | Description | Score |
|-------|-------------|-------|
| **Same Module** | Within the same module | 0.25 (close) |
| **Different Module** | Different module in the same crate | 0.50 |
| **External Crate** | Dependency on external crate | 1.00 (far) |
→ Lower in the table = **farther** distance
### 3. Volatility
How frequently a component changes (automatically calculated from Git history).
| Level | Description | Changes (6 months) | Score |
|-------|-------------|-------------------|-------|
| **Low** | Stable, rarely changes | 0-2 times | 0.00 |
| **Medium** | Occasionally changes | 3-10 times | 0.50 |
| **High** | Frequently changes | 11+ times | 1.00 |
> **Note**: Volatility requires Git history. Use `cargo coupling ./src` (not `--no-git`) to enable volatility analysis.
## The Balance Law
Good design follows this principle:
```
Strong coupling is only acceptable when distance is close OR volatility is low
```
Expressed as a logical formula:
```
BALANCED = (STRENGTH ≤ threshold) OR (DISTANCE = near) OR (VOLATILITY = low)
```
Or Khononov's formula:
```
BALANCE = (STRENGTH XOR DISTANCE) OR NOT VOLATILITY
```
- **STRENGTH XOR DISTANCE**: Strong coupling × close distance OR weak coupling × far distance = Good
- **OR NOT VOLATILITY**: Even if the above isn't satisfied, low volatility makes it acceptable
## Design Decision Matrix
| Strength | Distance | Volatility | Decision | Reason |
|----------|----------|------------|----------|--------|
| Strong | Close | Low-Medium | ✅ OK | High cohesion, changes are localized |
| Weak | Far | Any | ✅ OK | Loose coupling with healthy dependencies |
| Strong | Far | Any | ⚠️ Needs improvement | Change impact spreads widely (global complexity) |
| Strong | Any | High | ⚠️ Needs improvement | Changes cascade through the system |
| Weak | Close | Low | 🤔 Consider | Opportunity for integration (possibly over-modularized) |
## Improvement Patterns
### Pattern 1: Reducing Coupling Strength via Abstraction
**Problem**: Strong coupling + far distance
```
┌─────────────┐ ┌─────────────┐
│ Module A │ ──────▶ │ Module B │
│ │ strong │ (impl) │
└─────────────┘ └─────────────┘
far distance (different module)
```
**Solution**: Introduce a Contract (trait)
```
┌─────────────┐ ┌─────────────┐
│ Module A │ ──────▶ │ trait T │
│ │ weak │ (contract) │
└─────────────┘ └─────────────┘
▲
│ implements
┌─────────────┐
│ Module B │
│ (impl) │
└─────────────┘
```
### Pattern 2: Isolating Volatility
**Problem**: Strong coupling + high volatility
**Solution**: Insert a stable interface layer
## Concrete Example (Rust)
### Before: Problematic Code
```rust
// module_a.rs
fn process_user(user: &User) {
// Direct access to struct internal fields (Intrusive)
let name = &user.name; // ← strong coupling
let age = user.age; // ← strong coupling
let email = &user.email_address; // ← breaks if field name changes
// ...
}
```
```rust
// module_b.rs (frequently modified)
pub struct User {
pub name: String,
pub age: u32,
pub email_address: String, // ← renamed from email
}
```
**Issues**:
- Coupling strength: Intrusive (direct field access)
- Distance: Different Module
- Volatility: High (User struct changes frequently)
### After: Improved Code
```rust
// contracts.rs (stable layer)
pub trait UserInfo {
fn display_name(&self) -> &str;
fn age(&self) -> u32;
fn contact_email(&self) -> &str;
}
```
```rust
// module_b.rs (implementation details hidden)
pub struct User {
name: String, // changed to private
age: u32,
email_address: String,
}
impl UserInfo for User {
fn display_name(&self) -> &str { &self.name }
fn age(&self) -> u32 { self.age }
fn contact_email(&self) -> &str { &self.email_address }
}
```
```rust
// module_a.rs (access via trait)
fn process_user(user: &impl UserInfo) {
let name = user.display_name(); // ← Contract coupling
let age = user.age(); // ← Contract coupling
let email = user.contact_email(); // ← unaffected by internal changes
// ...
}
```
**Improvements**:
- Coupling strength: Reduced to Contract (via trait)
- Changes are contained within the `User` struct
- `module_a` no longer needs to know `User`'s internal structure
## Coupling Balance Summary
| Perspective | Guideline |
|-------------|-----------|
| Strong coupling... | Keep components close, or reduce volatility |
| Far dependencies... | Use weak coupling (Contract) |
| Highly volatile components... | Isolate with stable abstraction layers |
Coupling balance is not about "eliminating coupling" but about "placing the right strength of coupling in the right place."
## Numeric Implementation
In the actual implementation:
```rust
let alignment = 1.0 - (strength - (1.0 - distance)).abs();
let volatility_impact = 1.0 - (volatility * strength);
let score = alignment * volatility_impact;
```
## CLI Options
```
cargo coupling [OPTIONS] [PATH]
Arguments:
[PATH] Path to analyze [default: ./src]
Options:
-o, --output Output report to file
-s, --summary Show summary only
--ai AI-friendly output for coding agents
--all Show all issues (default: hide Low severity)
--japanese, --jp Japanese output with explanations (日本語)
--git-months Git history period [default: 6]
--no-git Skip Git analysis
-c, --config Config file path (default: .coupling.toml)
-v, --verbose Verbose output with explanations
--timing Show timing information
-j, --jobs Number of threads (default: auto)
--max-deps Max outgoing dependencies [default: 20]
--max-dependents Max incoming dependencies [default: 30]
Web Visualization:
--web Start interactive web UI
--port Web server port [default: 3000]
--no-open Don't auto-open browser
--api-endpoint API endpoint URL (for separate deployments)
Job-Focused Commands:
--hotspots[=] Show top N refactoring targets [default: 5]
--impact Analyze change impact for a module
--trace Trace dependencies for a function/type
--check CI/CD quality gate (exit code 1 on failure)
--min-grade Minimum grade for --check (A/B/C/D/F)
--max-critical Max critical issues for --check
--max-circular Max circular dependencies for --check
--fail-on Fail --check on severity (critical/high/medium/low)
--json Output in JSON format
-h, --help Print help
-V, --version Print version
```
## Thresholds
### Issue Detection Thresholds
The tool uses the following default thresholds for detecting coupling issues:
| Threshold | Default | CLI Flag | Description |
|-----------|---------|----------|-------------|
| Strong Coupling | 0.75 | - | Minimum strength value considered "strong" (Intrusive level) |
| Far Distance | 0.50 | - | Minimum distance value considered "far" (DifferentModule+) |
| High Volatility | 0.75 | - | Minimum volatility value considered "high" |
| Max Dependencies | 20 | `--max-deps` | Outgoing dependencies before flagging High Efferent Coupling |
| Max Dependents | 30 | `--max-dependents` | Incoming dependencies before flagging High Afferent Coupling |
### Health Grade Calculation
Health grades are calculated based on internal couplings only (external crate dependencies are excluded):
| Grade | Description | Criteria |
|-------|-------------|----------|
| **S (Over-optimized!)** | Stop refactoring! | Medium density <= 5% with >= 20 couplings |
| **A (Well-balanced)** | Coupling is appropriate | Medium density 5-10%, no high issues |
| **B (Healthy)** | Minor issues, manageable | Medium density > 10%, no critical issues |
| **C (Room for improvement)** | Some structural issues | Any high issues OR medium density > 25% |
| **D (Attention needed)** | Significant issues | Any critical issues OR high density > 5% |
| **F (Immediate action required)** | Critical issues | More than 3 critical issues |
**Note**: S is a WARNING, not a reward. It means you might be over-engineering. Aim for A.
### Severity Classification
Issues are classified by severity based on:
| Severity | Criteria |
|----------|----------|
| **Critical** | Multiple critical issues detected (circular dependencies, etc.) |
| **High** | Count > threshold × 2 (e.g., > 40 dependencies when threshold is 20) |
| **Medium** | Count > threshold but <= threshold × 2 |
| **Low** | Minor issues, generally informational |
## Output Example
### Summary Mode (English)
```
$ cargo coupling --summary ./src
Balanced Coupling Analysis: my-project
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Grade: B (Good) | Score: 0.67/1.00 | Modules: 14
3-Dimensional Analysis:
Strength: Contract 1% / Model 24% / Functional 66% / Intrusive 8%
Distance: Same 6% / Different 2% / External 91%
Volatility: Low 2% / Medium 98% / High 0%
Balance State:
✅ High Cohesion (strong+close): 24 (6%)
✅ Loose Coupling (weak+far): 5 (1%)
🤔 Acceptable (strong+far+stable): 352 (92%)
Detected Issues:
🟡 Medium: 3
Top Priorities:
- [Medium] metrics → 17 functions, 17 types, 11 impls
- [Medium] main → 21 dependencies
```
### Summary Mode (Japanese)
```
$ cargo coupling --summary --jp ./src
カップリング分析: my-project
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
評価: B (Good) | スコア: 0.67/1.00 | モジュール数: 14
3次元分析:
結合強度: Contract 1% / Model 24% / Functional 66% / Intrusive 8%
(トレイト) (型) (関数) (内部アクセス)
距離: 同一モジュール 6% / 別モジュール 2% / 外部 91%
変更頻度: 低 2% / 中 98% / 高 0%
バランス状態:
✅ 高凝集 (強い結合 + 近い距離): 24 (6%) ← 理想的
✅ 疎結合 (弱い結合 + 遠い距離): 5 (1%) ← 理想的
🤔 許容可能 (強い結合 + 遠い距離 + 安定): 352 (92%)
優先的に対処すべき問題:
- 神モジュール (責務が多すぎる) | metrics
→ モジュールを分割: metrics_core, metrics_helpers
設計判断ガイド (Khononov):
✅ 強い結合 + 近い距離 → 高凝集 (理想的)
✅ 弱い結合 + 遠い距離 → 疎結合 (理想的)
🤔 強い結合 + 遠い距離 + 安定 → 許容可能
❌ 強い結合 + 遠い距離 + 頻繁に変更 → 要リファクタリング
```
### Coupling Distribution
The tool shows how couplings are distributed by Integration Strength:
```
By Integration Strength:
| Strength | Count | % | Description |
|------------|-------|-----|--------------------------------|
| Contract | 23 | 4% | Depends on traits/interfaces |
| Model | 199 | 31% | Uses data types/structs |
| Functional | 382 | 59% | Calls specific functions |
| Intrusive | 46 | 7% | Accesses internal details |
```
## Detected Issues
### Critical Severity
- **Circular Dependencies**: Modules that depend on each other in a cycle
### High Severity
- **Global Complexity**: Strong coupling spanning long distances
- **Cascading Change Risk**: Strong coupling with frequently changing components
### Medium Severity
- **God Module**: Module with too many functions, types, or implementations
- **High Efferent Coupling**: Module depends on too many other modules
- **High Afferent Coupling**: Too many modules depend on this module
- **Inappropriate Intimacy**: Intrusive coupling across module boundaries
### Low Severity (hidden by default, use `--all` to show)
- **Public Field Exposure**: Public fields that could use getter methods
- **Primitive Obsession**: Functions with many primitive parameters (suggest newtype)
## Performance
`cargo-coupling` is optimized for large codebases with parallel AST analysis and streaming Git processing.
### Benchmark Results (Large OSS Projects)
| Project | Files | With Git | Without Git | Speed |
|---------|-------|----------|-------------|-------|
| tokio | 488 | 655ms | 234ms | 745 files/sec |
| alacritty | 83 | 298ms | 161ms | 514 files/sec |
| ripgrep | 59 | 181ms | - | 326 files/sec |
| bat | 40 | 318ms | - | 126 files/sec |
### Performance Features
1. **Parallel AST Analysis**: Uses Rayon for multi-threaded file processing
2. **Optimized Git Analysis**: Streaming processing with path filtering
3. **Configurable Thread Count**: Use `-j N` to control parallelism
```bash
# Show timing information
cargo coupling --timing ./src
# Use 4 threads
cargo coupling -j 4 ./src
# Skip Git analysis for faster results
cargo coupling --no-git ./src
```
### Git Analysis Optimization
The Git volatility analysis is optimized with:
- **Path filtering**: `-- "*.rs"` filters at Git level (reduces data transfer)
- **Diff filtering**: `--diff-filter=AMRC` skips deleted files
- **Streaming**: `BufReader` processes output without loading all into memory
- **Async spawn**: Starts processing before Git completes
These optimizations provide **5x-47x speedup** compared to naive implementation on large repositories.
## Library Usage
```rust
use cargo_coupling::{
analyze_workspace,
generate_report_with_thresholds,
IssueThresholds,
VolatilityAnalyzer
};
use std::path::Path;
fn main() -> Result<(), Box> {
// Analyze project with workspace support
let mut metrics = analyze_workspace(Path::new("./src"))?;
// Add volatility from Git history
let mut volatility = VolatilityAnalyzer::new(6);
if let Ok(()) = volatility.analyze(Path::new("./src")) {
metrics.file_changes = volatility.file_changes;
metrics.update_volatility_from_git();
}
// Detect circular dependencies
let circular = metrics.circular_dependency_summary();
if circular.total_cycles > 0 {
println!("Found {} cycles!", circular.total_cycles);
}
// Generate report with custom thresholds
let thresholds = IssueThresholds {
max_dependencies: 20,
max_dependents: 25,
..Default::default()
};
generate_report_with_thresholds(&metrics, &thresholds, &mut std::io::stdout())?;
Ok(())
}
```
## Docker
Run cargo-coupling without installing Rust:
```bash
# Basic analysis
docker run --rm -v $(pwd):/workspace ghcr.io/nwiizo/cargo-coupling coupling /workspace/src
# Summary mode
docker run --rm -v $(pwd):/workspace ghcr.io/nwiizo/cargo-coupling coupling --summary /workspace/src
# Web UI (access at http://localhost:3000)
docker run --rm -p 3000:3000 -v $(pwd):/workspace ghcr.io/nwiizo/cargo-coupling coupling --web --no-open /workspace/src
# Japanese output
docker run --rm -v $(pwd):/workspace ghcr.io/nwiizo/cargo-coupling coupling --summary --jp /workspace/src
```
### Docker Compose
```bash
# Run analysis
docker compose run --rm analyze
# Start Web UI
docker compose up web
```
### Available Tags
| Tag | Description |
|-----|-------------|
| `latest` | Latest release |
| `main` | Latest main branch build |
| `vX.Y.Z` | Specific version |
## CI/CD Integration
```yaml
# .github/workflows/coupling.yml
name: Coupling Analysis
on: [push, pull_request]
jobs:
analyze:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history for volatility analysis
- name: Install cargo-coupling
run: cargo install cargo-coupling
- name: Run coupling analysis
run: cargo coupling --summary --timing ./src
- name: Quality gate check
run: cargo coupling --check --min-grade=C --max-circular=0 ./src
- name: Generate report
run: cargo coupling -o coupling-report.md ./src
- name: Upload report
uses: actions/upload-artifact@v4
with:
name: coupling-report
path: coupling-report.md
```
### Quality Gate Options
The `--check` command provides flexible quality gate configuration:
```bash
# Fail if grade is below C
cargo coupling --check --min-grade=C ./src
# Fail if there are any circular dependencies
cargo coupling --check --max-circular=0 ./src
# Fail if there are any critical issues
cargo coupling --check --max-critical=0 ./src
# Fail on any high severity or above
cargo coupling --check --fail-on=high ./src
# Combine multiple conditions
cargo coupling --check --min-grade=B --max-circular=0 --max-critical=0 ./src
```
Exit codes:
- `0`: All checks passed
- `1`: One or more checks failed
## Best Practices
### ✅ Good: Strong Coupling at Close Distance
```rust
mod user_profile {
pub struct User { /* ... */ }
pub struct UserProfile { /* ... */ }
impl User {
pub fn get_profile(&self) -> &UserProfile { /* ... */ }
}
}
```
### ✅ Good: Weak Coupling at Far Distance
```rust
// core/src/lib.rs
pub trait NotificationService {
fn send(&self, message: &str) -> Result<()>;
}
// adapters/email/src/lib.rs
impl NotificationService for EmailService { /* ... */ }
```
### ❌ Bad: Strong Coupling at Far Distance
```rust
// src/api/handlers.rs
impl Handler {
fn handle(&self) {
// Direct dependency on internal implementation ❌
let result = database::internal::execute_raw_sql(...);
}
}
```
### ❌ Bad: Circular Dependencies
```rust
// module_a.rs
use crate::module_b::TypeB; // ❌ Creates cycle
// module_b.rs
use crate::module_a::TypeA; // ❌ Creates cycle
```
## Limitations
**This tool is a measurement aid, not an absolute authority on code quality.**
Please keep the following limitations in mind:
### What This Tool Cannot Do
- **Understand Business Context**: The tool analyzes structural patterns but cannot understand why certain couplings exist. Some "problematic" patterns may be intentional design decisions.
- **Replace Human Judgment**: Coupling metrics are heuristics. A high coupling score doesn't always mean bad code, and a low score doesn't guarantee good design.
- **Detect All Issues**: Static analysis has inherent limitations. Runtime behavior, dynamic dispatch, and macro-generated code may not be fully analyzed.
- **Provide Perfect Thresholds**: The default thresholds are calibrated for typical Rust projects but may not fit every codebase. Adjust them based on your project's needs.
### Important Considerations
- **External Dependencies Are Excluded**: The health grade only considers internal couplings. Dependencies on external crates (serde, tokio, etc.) are not penalized since you cannot control their design.
- **Git History Affects Volatility**: If Git history is unavailable or limited, volatility analysis will be incomplete.
- **Small Projects May Score Differently**: Projects with very few internal couplings (< 10) may receive a Grade B by default, as there's insufficient data for accurate assessment.
### Recommended Usage
1. **Use as a Starting Point**: The tool highlights areas worth investigating, not definitive problems.
2. **Combine with Code Review**: Human review should validate any suggested refactoring.
3. **Track Trends Over Time**: Use the tool regularly to track coupling trends rather than focusing on absolute scores.
4. **Customize Thresholds**: Adjust `--max-deps` and `--max-dependents` to match your project's architecture.
**The goal is to provide visibility into coupling patterns, empowering developers to make informed decisions.**
## References
- [Vlad Khononov - "Balancing Coupling in Software Design"](https://www.amazon.com/dp/B0FVDYKJYQ)
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.