# Debt Patterns

Debtmap detects **35 types of technical debt**, organized into 4 strategic categories. Each debt type is mapped to a category that guides prioritization and remediation strategies.

The 35 debt types consist of:
- **26 priority-specific variants**: Specialized debt patterns with detailed diagnostic data
- **9 legacy variants**: Backward-compatible types from earlier versions (prefer specialized variants)

**Source**: DebtType enum defined in `src/priority/debt_types.rs:47-205`, category mappings in `src/priority/mod.rs:216-254`

## Debt Type Enum

The `DebtType` enum defines all specific debt patterns that Debtmap can detect.

**Note**: Each `DebtType` variant carries structured diagnostic data specific to that pattern. For example, `ComplexityHotspot` includes `cyclomatic` and `cognitive` fields that provide detailed metrics for the detected issue. This structured data enables precise prioritization.

**Source**: DebtType structure defined in `src/priority/debt_types.rs:47-205`

### Priority-Specific Debt Types (26 types)

These are the primary debt types with specialized detection logic and detailed diagnostic data.

**Testing Debt (6 types):**
- `TestingGap` - Functions with insufficient test coverage (fields: `coverage`, `cyclomatic`, `cognitive`)
- `TestTodo` - TODO comments in test code (fields: `priority`, `reason`)
- `TestDuplication` - Duplicated code in test files (fields: `instances`, `total_lines`, `similarity`)
- `TestComplexityHotspot` - Complex test logic that's hard to maintain (fields: `cyclomatic`, `cognitive`, `threshold`)
- `AssertionComplexity` - Complex test assertions (fields: `assertion_count`, `complexity_score`)
- `FlakyTestPattern` - Non-deterministic test behavior (fields: `pattern_type`, `reliability_impact`)

**Architecture Debt (6 types):**
- `GodObject` - Unified variant for classes/files/modules with too many responsibilities (fields: `methods`, `fields`, `responsibilities`, `god_object_score`, `lines`). The detection type (GodClass, GodFile, GodModule) is determined by `god_object_indicators.detection_type` in the parent structure.
- `FeatureEnvy` - Using more data from other objects than own (fields: `external_class`, `usage_ratio`)
- `PrimitiveObsession` - Overusing basic types instead of domain objects (fields: `primitive_type`, `domain_concept`)
- `ScatteredType` - Types with methods scattered across multiple files (fields: `type_name`, `total_methods`, `file_count`, `severity` as String)
- `OrphanedFunctions` - Functions that should be methods on a type (fields: `target_type`, `function_count`, `file_count`)
- `UtilitiesSprawl` - Utility modules with poor cohesion (fields: `function_count`, `distinct_types`)

**Performance Debt (8 types):**
- `AllocationInefficiency` - Inefficient memory allocations (fields: `pattern`, `impact`)
- `StringConcatenation` - Inefficient string building in loops (fields: `loop_type`, `iterations`)
- `NestedLoops` - Multiple nested iterations O(n²) or worse (fields: `depth`, `complexity_estimate`)
- `BlockingIO` - Blocking I/O in async contexts (fields: `operation`, `context`)
- `SuboptimalDataStructure` - Wrong data structure for access pattern (fields: `current_type`, `recommended_type`)
- `AsyncMisuse` - Improper async/await usage (fields: `pattern`, `performance_impact`)
- `ResourceLeak` - Resources not properly released (fields: `resource_type`, `cleanup_missing`)
- `CollectionInefficiency` - Inefficient collection operations (fields: `collection_type`, `inefficiency_type`)

**Code Quality Debt (6 types):**
- `ComplexityHotspot` - Functions exceeding complexity thresholds (fields: `cyclomatic`, `cognitive`)
- `DeadCode` - Unreachable or unused code (fields: `visibility`, `cyclomatic`, `cognitive`, `usage_hints`)
- `MagicValues` - Unexplained literal values (fields: `value`, `occurrences`)
- `Risk` - High-risk code combining complexity + poor test coverage (fields: `risk_score`, `factors`)
- `Duplication` - Duplicated code blocks (fields: `instances`, `total_lines`)
- `ErrorSwallowing` - Errors caught but ignored (fields: `pattern`, `context`)

### Legacy Debt Types (9 types)

These variants are maintained for backward compatibility. For new analysis, prefer the specialized priority-specific variants listed above.

**Source**: Legacy variants defined in `src/priority/debt_types.rs:48-77`

| Legacy Type | Preferred Alternative | Migration Note |
|-------------|----------------------|----------------|
| `Todo` | Use for general TODO markers | Fields: `reason` |
| `Fixme` | Use for general FIXME markers | Fields: `reason` |
| `CodeSmell` | Use specific debt types | Fields: `smell_type` |
| `Complexity` | `ComplexityHotspot` | Fields: `cyclomatic`, `cognitive` |
| `Dependency` | Specific architecture types | Fields: `dependency_type` |
| `ResourceManagement` | `ResourceLeak`, `AllocationInefficiency` | Fields: `issue_type` |
| `CodeOrganization` | `ScatteredType`, `OrphanedFunctions`, `UtilitiesSprawl` | Fields: `issue_type` |
| `TestComplexity` | `TestComplexityHotspot` | Fields: `cyclomatic`, `cognitive` |
| `TestQuality` | `FlakyTestPattern`, `AssertionComplexity` | Fields: `issue_type` |

**Note**: Legacy types are categorized under `CodeQuality` by default (see `src/priority/mod.rs:251-252`).

## Debt Categories

The `DebtCategory` enum groups debt types into strategic categories:

**Source**: `src/priority/mod.rs:196-213`

```rust
pub enum DebtCategory {
    Architecture,  // Structure, design, complexity
    Testing,       // Coverage, test quality
    Performance,   // Speed, memory, efficiency
    CodeQuality,   // Maintainability, readability
}
```

### Category Mapping

**Source**: Category assignment logic in `src/priority/mod.rs:216-254`

| Category | Debt Types | Strategic Focus |
|----------|-----------|-----------------|
| Architecture | GodObject, FeatureEnvy, PrimitiveObsession, ScatteredType, OrphanedFunctions, UtilitiesSprawl | Structural improvements, design patterns, type organization |
| Testing | TestingGap, TestComplexityHotspot, TestTodo, TestDuplication, AssertionComplexity, FlakyTestPattern | Test coverage, test quality |
| Performance | AsyncMisuse, CollectionInefficiency, NestedLoops, BlockingIO, AllocationInefficiency, StringConcatenation, SuboptimalDataStructure, ResourceLeak | Runtime efficiency, resource usage |
| CodeQuality | ComplexityHotspot, DeadCode, Duplication, Risk, ErrorSwallowing, MagicValues, *all legacy types* | Maintainability, reliability, code clarity |

**Note**: `GodObject` is a unified variant that handles all god object detection types (GodClass, GodFile, GodModule). There is no separate `GodModule` debt type in the enum.

**Language-Specific Debt Patterns:**

Some debt patterns only apply to languages with specific features:
- **BlockingIO, AsyncMisuse**: Async-capable languages (Rust)
- **AllocationInefficiency, ResourceLeak**: Languages with manual memory management (Rust)
- **Error handling patterns**: Vary by language error model (Result in Rust)

Debtmap automatically applies only the relevant debt patterns during analysis.

### Examples by Category

#### Architecture Debt

**GodObject** (unified variant for GodClass/GodFile/GodModule): Too many responsibilities

**Source**: `src/priority/debt_types.rs:143-154`

```rust
// God module: handles parsing, validation, storage, notifications
mod user_service {
    fn parse_user() { /* ... */ }
    fn validate_user() { /* ... */ }
    fn save_user() { /* ... */ }
    fn send_email() { /* ... */ }
    fn log_activity() { /* ... */ }
    // ... 20+ more functions
}
```

The `GodObject` debt type captures all god object patterns through a unified variant. The specific detection type (GodClass, GodFile, or GodModule) is stored in the parent `UnifiedDebtItem.god_object_indicators.detection_type` field:

| Detection Type | When Used | Fields Used |
|---------------|-----------|-------------|
| GodClass | Class with too many methods/fields | `methods`, `fields` (Some), `responsibilities` |
| GodFile | File with too many functions | `methods`, `fields` (None), `lines` |
| GodModule | Module with too many responsibilities | `methods`, `fields` (None), `responsibilities` |

**When detected**: Complexity-weighted scoring system (see detailed explanation below)
**Action**: Split into focused modules (parser, validator, repository, notifier)

#### Complexity-Weighted God Object Detection

Debtmap uses **complexity-weighted scoring** for god object detection to reduce false positives on well-refactored code. This ensures that a file with 100 simple helper functions doesn't rank higher than a file with 10 complex functions.

**The Problem:**

Traditional god object detection counts methods:
- File A: 100 methods (average complexity: 1.5) → Flagged as god object
- File B: 10 methods (average complexity: 17.0) → Not flagged

But File A might be a well-organized utility module with many small helpers, while File B is truly problematic with highly complex functions that need refactoring.

**The Solution:**

Debtmap weights each function by its cyclomatic complexity using this formula:

```
weight = (max(1, complexity) / 3)^1.5
```

**Weight Examples:**
- Simple helper (complexity 1): weight ≈ 0.19
- Baseline function (complexity 3): weight = 1.0
- Moderate function (complexity 9): weight ≈ 5.2
- Complex function (complexity 17): weight ≈ 13.5
- Critical function (complexity 33): weight ≈ 36.5

**God Object Score Calculation:**

```
weighted_method_count = sum(weight for each function)
complexity_penalty = 0.7 if avg_complexity < 3, 1.0 if 3-10, 1.5 if > 10

god_object_score = (
    (weighted_method_count / threshold) * 40% +
    (field_count / threshold) * 20% +
    (responsibility_count / threshold) * 15% +
    (lines_of_code / 500) * 25%
) * complexity_penalty
```

**Threshold**: God object detected if `score >= 70.0`

**Real-World Example:**

```
shared_cache.rs:
  - 100 functions, average complexity: 1.5
  - Weighted score: ~19.0 (100 * 0.19)
  - God object score: 45.2
  - Result: Not a god object ✓

legacy_parser.rs:
  - 10 functions, average complexity: 17.0
  - Weighted score: ~135.0 (10 * 13.5)
  - God object score: 87.3
  - Result: God object detected ✓
```

**Benefits:**

- **Reduces false positives** on utility modules with many simple functions
- **Focuses attention** on truly problematic complex modules
- **Rewards good refactoring** - breaking large functions into small helpers improves score
- **Aligns with reality** - complexity matters more than count for maintainability

**How to View:**

When Debtmap detects a god object, the output includes:
- Raw method count
- Weighted method count
- Average complexity
- God object score
- Recommended module splits based on responsibility clustering

#### Type Organization Debt

**Source**: Type organization patterns defined in `src/priority/debt_types.rs:189-205` (Spec 187), detection logic in `src/organization/codebase_type_analyzer.rs`

These patterns detect issues with how types and their associated functions are organized across the codebase.

**ScatteredType**: Type with methods scattered across multiple files

```rust
// Type definition in types/user.rs
pub struct User {
    id: UserId,
    name: String,
}

// Methods scattered across files:
// In modules/auth.rs:
impl User {
    fn authenticate(&self) -> Result<Session> { /* ... */ }
}

// In modules/validation.rs:
impl User {
    fn validate_email(&self) -> Result<()> { /* ... */ }
}

// In modules/persistence.rs:
impl User {
    fn save(&self) -> Result<()> { /* ... */ }
}

// Problem: User methods spread across 4+ files!
```

**When detected**: Type has methods in 2+ files
**Severity levels**: Stored as String field derived from `file_count`:
- Low = 2 files
- Medium = 3-5 files
- High = 6+ files

**Action**: Consolidate methods into primary file or create focused trait implementations

**Source**: Detection criteria from `src/organization/codebase_type_analyzer.rs:46-47`, type definition in `src/priority/debt_types.rs:190-195`

**OrphanedFunctions**: Functions that should be methods on a type

```rust
// Bad: Orphaned functions operating on User
fn validate_user_email(user: &User) -> Result<()> {
    // Email validation logic
}

fn calculate_user_age(user: &User) -> u32 {
    // Age calculation from birthdate
}

fn format_user_display(user: &User) -> String {
    // Display formatting
}

// Good: Functions converted to methods
impl User {
    fn validate_email(&self) -> Result<()> { /* ... */ }
    fn age(&self) -> u32 { /* ... */ }
    fn display(&self) -> String { /* ... */ }
}
```

**When detected**: Multiple functions with shared type parameter pattern (e.g., all take `&User`)
**Action**: Convert functions to methods on the target type

**Source**: Detection in `src/organization/codebase_type_analyzer.rs:58-71`, type definition in `src/priority/debt_types.rs:196-200`

**UtilitiesSprawl**: Utility module with poor cohesion

```rust
// Bad: utils.rs with mixed responsibilities
mod utils {
    fn parse_date(s: &str) -> Date { /* ... */ }
    fn validate_email(s: &str) -> bool { /* ... */ }
    fn calculate_hash(data: &[u8]) -> Hash { /* ... */ }
    fn format_currency(amount: f64) -> String { /* ... */ }
    fn send_notification(msg: &str) { /* ... */ }
    // ... 20+ more unrelated functions
}

// Good: Focused modules
mod date_utils { fn parse(s: &str) -> Date { /* ... */ } }
mod validators { fn email(s: &str) -> bool { /* ... */ } }
mod crypto { fn hash(data: &[u8]) -> Hash { /* ... */ } }
mod formatters { fn currency(amount: f64) -> String { /* ... */ } }
mod notifications { fn send(msg: &str) { /* ... */ } }
```

**When detected**: Utility module has many functions operating on diverse types with low cohesion
**Action**: Split into focused modules based on domain or responsibility

**Source**: Detection in `src/organization/codebase_type_analyzer.rs:74-80`, type definition in `src/priority/debt_types.rs:201-204`

#### Testing Debt

**TestingGap**: Functions with insufficient test coverage
```rust
// 0% coverage - critical business logic untested
fn calculate_tax(amount: f64, region: &str) -> f64 {
    // Complex tax calculation logic
    // No tests exist for this function!
}
```
**When detected**: Coverage data shows function has < 80% line coverage
**Action**: Add unit tests to cover all branches and edge cases

**TestComplexity**: Test functions too complex
```rust
#[test]
fn complex_test() {
    // Cyclomatic: 12 (too complex for a test)
    for input in test_cases {
        if input.is_special() {
            match input.type {
                /* complex test logic */
            }
        }
    }
}
```
**When detected**: Test functions with cyclomatic > 10 or cognitive > 15
**Action**: Split into multiple focused tests, use test fixtures

**FlakyTestPattern**: Non-deterministic tests
```rust
#[test]
fn flaky_test() {
    let result = async_operation().await;  // Timing-dependent
    thread::sleep(Duration::from_millis(100));  // Race condition!
    assert_eq!(result.status, "complete");
}
```
**When detected**: Pattern analysis for timing dependencies, random values
**Action**: Use mocks, deterministic test data, proper async test utilities

#### Performance Debt

**AllocationInefficiency**: Excessive allocations
```rust
// Bad: Allocates on every iteration
fn process_items(items: &[Item]) -> Vec<String> {
    let mut results = Vec::new();
    for item in items {
        results.push(item.name.clone());  // Unnecessary clone
    }
    results
}

// Good: Pre-allocate, avoid clones
fn process_items(items: &[Item]) -> Vec<&str> {
    items.iter().map(|item| item.name.as_str()).collect()
}
```

**BlockingIO**: Blocking operations in async contexts
```rust
// Bad: Blocks async runtime
async fn load_data() -> Result<Data> {
    let file = std::fs::read_to_string("data.json")?;  // Blocking!
    parse_json(&file)
}

// Good: Async I/O
async fn load_data() -> Result<Data> {
    let file = tokio::fs::read_to_string("data.json").await?;
    parse_json(&file)
}
```

**NestedLoops**: O(n²) or worse complexity
```rust
// Bad: O(n²) nested loops
fn find_duplicates(items: &[Item]) -> Vec<(Item, Item)> {
    let mut dupes = vec![];
    for i in 0..items.len() {
        for j in i+1..items.len() {
            if items[i] == items[j] {
                dupes.push((items[i].clone(), items[j].clone()));
            }
        }
    }
    dupes
}

// Good: O(n) with HashSet
fn find_duplicates(items: &[Item]) -> Vec<Item> {
    let mut seen = HashSet::new();
    items.iter().filter(|item| !seen.insert(item)).cloned().collect()
}
```

#### Code Quality Debt

**ComplexityHotspot**: Functions exceeding complexity thresholds

**Source**: Type definition in `src/priority/debt_types.rs:84-87`, categorized as CodeQuality in `src/priority/mod.rs:245`

```rust
// Cyclomatic: 22, Cognitive: 35
fn process_transaction(tx: Transaction, account: &mut Account) -> Result<Receipt> {
    if tx.amount <= 0 {
        return Err(Error::InvalidAmount);
    }
    if account.balance < tx.amount {
        if account.overdraft_enabled {
            if account.overdraft_limit >= tx.amount {
                // More nested branches...
            }
        } else {
            return Err(Error::InsufficientFunds);
        }
    }
    // ... deeply nested logic with many branches
    Ok(receipt)
}
```

**Fields captured**: `cyclomatic: u32`, `cognitive: u32`
**When detected**: Cyclomatic > 10 OR Cognitive > 15 (configurable)
**Action**: Break into smaller functions, extract validation, simplify control flow

**DeadCode**: Unreachable or unused code

**Source**: Type definition in `src/priority/debt_types.rs:88-93`, categorized as CodeQuality in `src/priority/mod.rs:246`

```rust
// Private function never called within module
fn obsolete_calculation(x: i32) -> i32 {
    x * 2 + 5  // Dead code - no callers
}

// Public function but no external usage
pub fn deprecated_api(data: &str) -> Result<()> {
    // Unreachable in practice
    Ok(())
}
```

**When detected**: Function visibility analysis + call graph shows no callers
**Action**: Remove dead code or document if intentionally kept for future use

**MagicValues**: Unexplained literal values

**Source**: Type definition in `src/priority/debt_types.rs:163-166`, categorized as CodeQuality in `src/priority/mod.rs:250`

```rust
// Bad: Magic numbers
fn calculate_price(quantity: u32) -> f64 {
    quantity as f64 * 19.99 + 5.0  // What are these numbers?
}

// Good: Named constants
const UNIT_PRICE: f64 = 19.99;
const SHIPPING_COST: f64 = 5.0;
fn calculate_price(quantity: u32) -> f64 {
    quantity as f64 * UNIT_PRICE + SHIPPING_COST
}
```

**When detected**: Numeric or string literals without clear context (excludes 0, 1, common patterns)
**Action**: Extract to named constants or configuration

**Duplication**: Duplicated code blocks
```rust
// File A:
fn process_user(user: User) -> Result<()> {
    validate_email(&user.email)?;
    validate_age(user.age)?;
    save_to_database(&user)?;
    send_welcome_email(&user.email)?;
    Ok(())
}

// File B: Duplicated validation
fn process_admin(admin: Admin) -> Result<()> {
    validate_email(&admin.email)?;  // Duplicated
    validate_age(admin.age)?;       // Duplicated
    save_to_database(&admin)?;
    grant_admin_privileges(&admin)?;
    Ok(())
}
```
**When detected**: Similar code blocks > 50 lines (configurable)
**Action**: Extract shared code into reusable functions

**ErrorSwallowing**: Errors caught but ignored
```rust
// Bad: Error swallowed, no context
match risky_operation() {
    Ok(result) => process(result),
    Err(_) => {}, // Silent failure!
}

// Good: Error handled with context
match risky_operation() {
    Ok(result) => process(result),
    Err(e) => {
        log::error!("Risky operation failed: {}", e);
        return Err(e.into());
    }
}
```
**When detected**: Empty catch blocks, ignored Results
**Action**: Add proper error logging and propagation

**Risk**: High-risk code (complex + poorly tested)
```rust
// Cyclomatic: 18, Coverage: 20%, Risk Score: 47.6 (HIGH)
fn process_payment(tx: Transaction) -> Result<Receipt> {
    // Complex payment logic with minimal testing
    // High risk of bugs in production
}
```
**When detected**: Combines complexity metrics with coverage data
**Action**: Either add comprehensive tests OR refactor to reduce complexity

### Debt Scoring Formula

Each debt item gets a score based on priority and type:

```
debt_score = priority_weight × type_weight
```

**Priority weights:**
- Low = 1
- Medium = 3
- High = 5
- Critical = 10

**Combined examples:**
- Low Todo = 1 × 1 = 1
- Medium Fixme = 3 × 2 = 6
- High Complexity = 5 × 5 = 25
- Critical Complexity = 10 × 5 = 50

**Total debt score** = Sum of all debt item scores

Lower is better. Track over time to measure improvement.

