debtmap 0.17.0

Code complexity and technical debt analyzer
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
# Architectural Analysis

Debtmap provides comprehensive architectural analysis capabilities based on Robert C. Martin's software engineering principles. These tools help identify structural issues, coupling problems, and architectural anti-patterns in your codebase.

## Overview

Architectural analysis examines module-level relationships and dependencies to identify:

- **Circular Dependencies** - Modules that create dependency cycles
- **Coupling Metrics** - Afferent and efferent coupling measurements
- **Bidirectional Dependencies** - Inappropriate intimacy between modules
- **Stable Dependencies Principle Violations** - Unstable modules being depended upon
- **Zone of Pain** - Rigid, concrete implementations heavily depended upon
- **Zone of Uselessness** - Overly abstract, unstable modules
- **Code Duplication** - Identical or similar code blocks across files

These analyses help you maintain clean architecture and identify refactoring opportunities.

## Circular Dependency Detection

Circular dependencies occur when modules form a dependency cycle (A depends on B, B depends on C, C depends on A). These violations break architectural boundaries and make code harder to understand, test, and maintain.

### How It Works

Debtmap builds a **dependency graph** from module imports and uses **depth-first search (DFS)** with recursion stack tracking to detect cycles:

1. Parse all files to extract import/module dependencies
2. Build a directed graph where nodes are modules and edges are dependencies
3. Run DFS from each unvisited module
4. Track visited nodes and recursion stack
5. When a node is reached that's already in the recursion stack, a cycle is detected

**Implementation:** `src/debt/circular.rs:46-66` (detect_circular_dependencies)

### Example

```rust
// Module A (src/auth.rs)
use crate::user::User;
use crate::session::validate_session;

// Module B (src/user.rs)
use crate::session::Session;

// Module C (src/session.rs)
use crate::auth::authenticate; // Creates cycle: auth → session → auth
```

**Debtmap detects:**
```
Circular dependency detected: auth → session → auth
```

### Refactoring Recommendations

To break circular dependencies:

1. **Extract Interface** - Create a trait that both modules depend on
2. **Dependency Inversion** - Introduce an abstraction layer
3. **Move Shared Code** - Extract common functionality to a new module
4. **Remove Dependency** - Inline or duplicate small amounts of code

## Coupling Metrics

Coupling metrics measure how interconnected modules are. Debtmap calculates two primary metrics:

### Afferent Coupling (Ca)

**Afferent coupling** is the number of modules that depend on this module. High afferent coupling means many modules rely on this code.

```rust
pub struct CouplingMetrics {
    pub module: String,
    pub afferent_coupling: usize, // Number depending on this module
    pub efferent_coupling: usize, // Number this module depends on
    pub instability: f64,         // Calculated from Ca and Ce
    pub abstractness: f64,        // Ratio of abstract types
}
```

**Implementation:** `src/debt/coupling.rs:6-30`

### Efferent Coupling (Ce)

**Efferent coupling** is the number of modules this module depends on. High efferent coupling means this module has many dependencies.

**Note on Abstractness:** The `abstractness` field in `CouplingMetrics` requires advanced type analysis to calculate properly. The current implementation uses a placeholder value (0.0) as full abstractness calculation would need semantic analysis of trait definitions, abstract types, and implementation ratios. This is similar to the cohesion analysis limitation documented below (see "Cohesion Analysis" section).

**Source:** `src/debt/coupling.rs:44`

### Example Coupling Analysis

```
Module: api_handler
  Afferent coupling (Ca): 8  // 8 modules depend on api_handler
  Efferent coupling (Ce): 3  // api_handler depends on 3 modules
  Instability: 0.27          // Relatively stable
```

High afferent or efferent coupling (typically >5) indicates potential maintainability issues.

## Instability Metric

The **instability metric** measures how resistant a module is to change. It's calculated as:

```
I = Ce / (Ca + Ce)
```

**Interpretation:**
- **I = 0.0** - Maximally stable (no dependencies, many dependents)
- **I = 1.0** - Maximally unstable (many dependencies, no dependents)

**Implementation:** `src/debt/coupling.rs:16-24` (calculate_instability)

### Stability Guidelines

- **Stable modules (I < 0.3)** - Hard to change but depended upon; should contain stable abstractions
- **Balanced modules (0.3 ≤ I ≤ 0.7)** - Normal modules with both dependencies and dependents
- **Unstable modules (I > 0.7)** - Change frequently; should have few or no dependents

### Example

```rust
// Stable module (I = 0.1)
// core/types.rs - defines fundamental types, depended on by 20 modules
pub struct User { ... }
pub struct Session { ... }

// Unstable module (I = 0.9)
// handlers/admin_dashboard.rs - depends on 10 modules, no dependents
use crate::auth::*;
use crate::database::*;
use crate::templates::*;
// ... 7 more imports
```

## Stable Dependencies Principle

The **Stable Dependencies Principle (SDP)** states: *Depend in the direction of stability*. Modules should depend on modules that are more stable than themselves.

### SDP Violations

Debtmap flags violations when a module has:
- **Instability > 0.8** (very unstable)
- **Afferent coupling > 2** (multiple modules depend on it)

This means an unstable, frequently changing module is being depended upon by multiple other modules - a recipe for maintenance problems.

**Implementation:** `src/debt/coupling.rs:69-76`

### Example Violation

```
Module 'temp_utils' violates Stable Dependencies Principle
(instability: 0.85, depended on by 5 modules)

Problem: This module changes frequently but is heavily depended upon.
Solution: Extract stable interface or reduce dependencies on this module.
```

### Fixing SDP Violations

1. **Increase stability** - Reduce the module's dependencies
2. **Reduce afferent coupling** - Extract interface, use dependency injection
3. **Split module** - Separate stable and unstable parts

## Bidirectional Dependencies

Bidirectional dependencies (also called **inappropriate intimacy**) occur when two modules depend on each other:

```
Module A depends on Module B
Module B depends on Module A
```

This creates tight coupling and makes both modules harder to change, test, or reuse independently.

**Implementation:** `src/debt/coupling.rs:98-117` (detect_inappropriate_intimacy)

### Example

```rust
// order.rs
use crate::customer::Customer;

pub struct Order {
    customer: Customer,
}

// customer.rs
use crate::order::Order; // Bidirectional dependency!

pub struct Customer {
    orders: Vec<Order>,
}
```

**Debtmap detects:**
```
Inappropriate intimacy detected between 'order' and 'customer'
```

### Refactoring Recommendations

1. **Create Mediator** - Introduce a third module to manage the relationship
2. **Break into Separate Modules** - Split concerns more clearly
3. **Use Events** - Replace direct dependencies with event-driven communication
4. **Dependency Inversion** - Introduce interfaces/traits both depend on

## Zone of Pain Detection

The **zone of pain** contains modules with:
- **Low abstractness (< 0.2)** - Concrete implementations, no abstractions
- **Low instability (< 0.2)** - Stable, hard to change
- **High afferent coupling (> 3)** - Many modules depend on them

These modules are rigid concrete implementations that are heavily used but hard to change - causing pain when modifications are needed.

**Implementation:** `src/debt/coupling.rs:125-138`

### Example

```
Module 'database_client' is in the zone of pain (rigid and hard to change)
  Abstractness: 0.1  (all concrete implementation)
  Instability: 0.15  (very stable, many dependents)
  Afferent coupling: 12 (12 modules depend on it)

Problem: This concrete database client is used everywhere.
Any change to its implementation requires updating many modules.
```

### Refactoring Recommendations

1. **Extract Interfaces** - Create a `DatabaseClient` trait
2. **Introduce Abstractions** - Define abstract operations others depend on
3. **Break into Smaller Modules** - Separate concerns to reduce coupling
4. **Use Dependency Injection** - Pass implementations via interfaces

## Zone of Uselessness Detection

The **zone of uselessness** contains modules with:
- **High abstractness (> 0.8)** - Mostly abstract, few concrete implementations
- **High instability (> 0.8)** - Frequently changing

These modules are overly abstract and unstable, providing little stable value to the system.

**Implementation:** `src/debt/coupling.rs:141-153`

### Example

```
Module 'base_processor' is in the zone of uselessness
(too abstract and unstable)
  Abstractness: 0.9  (mostly traits and interfaces)
  Instability: 0.85  (changes frequently)

Problem: This module defines many abstractions but provides little
concrete value. It changes often, breaking implementations.
```

### Refactoring Recommendations

1. **Add Concrete Implementations** - Make the module useful by implementing functionality
2. **Remove if Unused** - Delete if no real value is provided
3. **Stabilize Interfaces** - Stop changing abstractions frequently
4. **Merge with Implementations** - Combine abstract and concrete code

## Distance from Main Sequence

The **main sequence** represents the ideal balance between abstractness and instability. Modules should lie on the line:

```
A + I = 1
```

Where:
- **A** = Abstractness (ratio of abstract types to total types)
- **I** = Instability (Ce / (Ca + Ce))

**Distance** from the main sequence:

```
D = |A + I - 1|
```

**Implementation:** `src/debt/coupling.rs:119-123`

### Interpretation

- **D ≈ 0.0** - Module is on the main sequence (ideal)
- **D > 0.5** - Module is far from ideal
  - High D with low A and I → Zone of Pain
  - High D with high A and I → Zone of Uselessness

### Visual Representation

```
Abstractness
    1.0 ┤        Zone of Uselessness
        │      ╱
        │    ╱
    0.5 ┤  ╱ Main Sequence
        │╱
    0.0 ┤──────────────────────────
        0.0    0.5              1.0
                 Instability

        Zone of Pain
```

## Code Duplication Detection

Debtmap detects code duplication using **hash-based chunk comparison**:

1. **Extract chunks** - Split files into fixed-size chunks (default: 50 lines)
2. **Normalize** - Remove whitespace and comments
3. **Calculate hash** - Compute xxHash64 hash for each normalized chunk (10-20x faster than SHA-256)
4. **Match duplicates** - Find chunks with identical hashes
5. **Merge adjacent** - Consolidate consecutive duplicate blocks

**Note:** The minimum chunk size is configurable via the `--threshold-duplication` flag or in `.debtmap.toml` (default: 50 lines).

**Implementation:** `src/debt/duplication.rs:6-44` (detect_duplication)

### Algorithm Details

```rust
pub fn detect_duplication(
    files: Vec<(PathBuf, String)>,
    min_lines: usize,           // Default: 50
    _similarity_threshold: f64, // Currently unused (exact matching)
) -> Vec<DuplicationBlock>
```

The algorithm:
1. Extracts overlapping chunks from each file
2. Normalizes by trimming whitespace and removing comments
3. Calculates xxHash64 hash for each normalized chunk (returns a `u64` value)
4. Groups chunks by hash using thread-safe concurrent aggregation
5. Returns groups with 2+ locations (duplicates found)

### Example Output

```
Code duplication detected:
  Hash: 14628437538729542158 (xxHash64)
  Lines: 50
  Locations:
    - src/handlers/user.rs:120-169
    - src/handlers/admin.rs:85-134
    - src/handlers/guest.rs:200-249

Recommendation: Extract common validation logic to shared module
```

## Duplication Configuration

Configure duplication detection in `.debtmap.toml`:

```toml
# Minimum lines for duplication detection
threshold_duplication = 50  # Default value

# Smaller values catch more duplications but increase noise
# threshold_duplication = 30  # More sensitive

# Larger values only catch major duplications
# threshold_duplication = 100  # Less noise
```

**Configuration reference:** `src/cli/args.rs:86-87` (threshold_duplication flag definition)

**Implementation:** `src/debt/duplication.rs:11-15`

### Current Limitations

- **Exact matching only** - Currently uses hash-based exact matching
- **similarity_threshold parameter** - Defined in function signature but not implemented yet
- **Future enhancement** - Fuzzy matching for near-duplicates using similarity algorithms (e.g., Levenshtein distance, token-based similarity)

The `similarity_threshold` parameter exists for future extensibility but is currently unused. All duplication detection uses exact hash matching. Track progress on fuzzy matching in the project's issue tracker or roadmap.

## Refactoring Recommendations

Debtmap provides specific refactoring recommendations for each architectural issue:

### For Circular Dependencies

1. **Extract Interface** - Create shared abstraction both modules use
2. **Dependency Inversion** - Introduce interfaces to reverse dependency direction
3. **Move Shared Code** - Extract to new module both can depend on
4. **Event-Driven** - Replace direct calls with event publishing/subscribing

### For High Coupling

1. **Facade Pattern** - Provide simplified interface hiding complex dependencies
2. **Reduce Dependencies** - Remove unnecessary imports and calls
3. **Dependency Injection** - Pass dependencies via constructors/parameters
4. **Interface Segregation** - Split large interfaces into focused ones

### For Zone of Pain

1. **Introduce Abstractions** - Extract traits/interfaces for flexibility
2. **Adapter Pattern** - Wrap concrete implementations with adapters
3. **Strategy Pattern** - Make algorithms pluggable via interfaces

### For Zone of Uselessness

1. **Add Concrete Implementations** - Provide useful functionality
2. **Remove Unused Code** - Delete if providing no value
3. **Stabilize Interfaces** - Stop changing abstractions frequently

### For Bidirectional Dependencies

1. **Create Mediator** - Third module manages relationship
2. **Break into Separate Modules** - Clearer separation of concerns
3. **Observer Pattern** - One-way communication via observers

### For Code Duplication

1. **Extract Common Code** - Create shared function/module
2. **Use Inheritance/Composition** - Share via traits or composition
3. **Parameterize Differences** - Extract variable parts as parameters
4. **Template Method** - Define algorithm structure, vary specific steps

## Examples and Use Cases

### Running Architectural Analysis

```bash
# Architectural analysis runs automatically with standard analysis
debtmap analyze .

# Duplication detection with custom chunk size
debtmap analyze . --threshold-duplication 30

# Note: Circular dependencies, coupling metrics, and SDP violations
# are analyzed automatically. There are no separate flags to enable
# or disable specific architectural checks.
```

### Example: Circular Dependency

**Before:**
```
src/auth.rs → src/session.rs → src/user.rs → src/auth.rs

Circular dependency detected: auth → session → user → auth
```

**After refactoring:**
```
src/auth.rs → src/auth_interface.rs ← src/session.rs
              src/user.rs

No circular dependencies found.
```

### Example: Coupling Metrics Table

```
Module Analysis Results:

Module              Ca    Ce    Instability  Issues
-------------------------------------------------
core/types          15     0       0.00      None
api/handlers         2     8       0.80      High Ce
database/client      8     2       0.20      None
utils/temp          5    12       0.71      SDP violation
auth/session        3     3       0.50      None
```

### Example: Zone of Pain

**Module:** `legacy_db_client`

```
Metrics:
  Abstractness: 0.05 (all concrete code)
  Instability: 0.12 (depended on by 25 modules)
  Afferent coupling: 25
  Distance from main sequence: 0.83

Status: Zone of Pain - rigid and hard to change

Refactoring steps:
1. Extract interface DatabaseClient trait
2. Create adapter wrapping legacy implementation
3. Gradually migrate dependents to use trait
4. Introduce alternative implementations
```

## Interpreting Results

### Prioritization

Address architectural issues in this order:

1. **Circular Dependencies** (Highest Priority)
   - Break architectural boundaries
   - Make testing impossible
   - Cause build issues

2. **Bidirectional Dependencies** (High Priority)
   - Create tight coupling
   - Prevent independent testing
   - Block modular changes

3. **Zone of Pain Issues** (Medium-High Priority)
   - Indicate rigid architecture
   - Block future changes
   - High risk for bugs

4. **SDP Violations** (Medium Priority)
   - Cause ripple effects
   - Increase maintenance cost
   - Unstable foundation

5. **High Coupling** (Medium Priority)
   - Maintainability risk
   - Testing difficulty
   - Change amplification

6. **Code Duplication** (Lower Priority)
   - Maintenance burden
   - Bug multiplication
   - Inconsistency risk

### Decision Flowchart

```
Is there a circular dependency?
├─ YES → Break immediately (extract interface, DI)
└─ NO  → Continue

Is there bidirectional dependency?
├─ YES → Refactor (mediator, event-driven)
└─ NO  → Continue

Is module in zone of pain?
├─ YES → Introduce abstractions
└─ NO  → Continue

Is SDP violated?
├─ YES → Stabilize or reduce afferent coupling
└─ NO  → Continue

Is coupling > threshold?
├─ YES → Reduce dependencies
└─ NO  → Continue

Is there significant duplication?
├─ YES → Extract common code
└─ NO  → Architecture is good!
```

## Integration with Debt Categories

Architectural analysis results are integrated with debtmap's debt categorization system:

### Debt Type Mapping

Architectural issues are mapped to existing DebtType enum variants:

- **Duplication** - Duplicated code blocks found
- **Dependency** - Used for circular dependencies and coupling issues
- **CodeOrganization** - May be used for architectural violations (SDP, zone issues)

**Note:** The DebtType enum does not have dedicated variants for CircularDependency, HighCoupling, or ArchitecturalViolation. Architectural issues are mapped to existing general-purpose debt types.

**Reference:** `src/core/mod.rs:220-236` for actual DebtType enum definition

### Tiered Prioritization

Architectural issues are assigned priority tiers:

- **Tier 1 (Critical)** - Circular dependencies, bidirectional dependencies
- **Tier 2 (High)** - Zone of pain, SDP violations
- **Tier 3 (Medium)** - High coupling, large duplications
- **Tier 4 (Low)** - Small duplications, minor coupling issues

**Reference:** See [Tiered Prioritization](tiered-prioritization.md) for complete priority assignment logic

## Cohesion Analysis

**Note:** Module cohesion analysis is currently a simplified placeholder implementation.

**Current status:** `src/debt/coupling.rs:82-95` (analyze_module_cohesion)

The function exists but provides basic cohesion calculation. Full cohesion analysis (measuring how well module elements belong together) is planned for a future release.

### Future Enhancement

Full cohesion analysis would measure:
- Functional cohesion (functions operating on related data)
- Sequential cohesion (output of one function feeds another)
- Communicational cohesion (functions operating on same data structures)

## Configuration

### Configurable Parameters

Configure duplication detection in `.debtmap.toml` or via CLI:

```toml
# Minimum lines for duplication detection
threshold_duplication = 50  # Default value
```

Or via command line:

```bash
debtmap analyze . --threshold-duplication 50
```

**Configuration reference:** `src/cli/args.rs:86-87` (threshold_duplication flag definition)

### Hardcoded Thresholds

**Note:** Most architectural thresholds are currently hardcoded in the implementation and cannot be configured. These thresholds are based on industry-standard metrics from Robert C. Martin's research and empirical software engineering studies:

- **Coupling threshold:** 5 (modules with >5 dependencies are flagged)
- **Instability threshold:** 0.8 (for SDP violations)
- **SDP afferent threshold:** 2 (minimum dependents for SDP violations)
- **Zone of pain thresholds:**
  - Abstractness < 0.2
  - Instability < 0.2
  - Afferent coupling > 3
- **Zone of uselessness thresholds:**
  - Abstractness > 0.8
  - Instability > 0.8

These values represent widely-accepted boundaries in software architecture literature. While they work well for most projects, configurable thresholds may be added in a future release to support domain-specific tuning.

**Source:** `src/debt/coupling.rs:70-76, 130, 145` (hardcoded threshold definitions)

See [Configuration](configuration.md) for complete options.

## Troubleshooting

### "No circular dependencies detected but build fails"

**Cause:** Circular dependencies at the package/crate level, not module level.

**Solution:** Use `cargo tree` to analyze package-level dependencies.

### "Too many coupling warnings"

**Cause:** Default threshold of 5 may be too strict for your codebase.

**Solution:** The coupling threshold is currently hardcoded at 5 in the implementation (`src/debt/coupling.rs:62`). To adjust it, you would need to modify the source code. Consider using suppression patterns to exclude specific modules if needed. See [Suppression Patterns](suppression-patterns.md).

### "Duplication detected in generated code"

**Cause:** Code generation tools create similar patterns.

**Solution:** Use suppression patterns to exclude generated files. See [Suppression Patterns](suppression-patterns.md).

### "Zone of pain false positives"

**Cause:** Utility modules are intentionally stable and concrete.

**Solution:** This is often correct - utility modules should be stable. Consider whether the module should be more abstract.

## Further Reading

### Robert C. Martin's Principles

The architectural metrics in debtmap are based on:

- **Clean Architecture** by Robert C. Martin
- **Agile Software Development: Principles, Patterns, and Practices** by Robert C. Martin
- Stable Dependencies Principle (SDP)
- Stable Abstractions Principle (SAP)
- Main Sequence distance metric

### Related Topics

- [Analysis Guide]analysis-guide/index.md - Complete analysis workflow
- [Configuration]configuration.md - Configuration options
- [Entropy Analysis]entropy-analysis.md - Complexity vs. entropy
- [Scoring Strategies]scoring-strategies.md - How debt is scored
- [Tiered Prioritization]tiered-prioritization.md - Priority assignment