home / skills / kaakati / rails-enterprise-dev / technical-debt-patterns

technical-debt-patterns skill

/plugins/reactree-rails-dev/skills/technical-debt-patterns

This skill helps you detect, classify, and prioritize Rails technical debt to guide audits, refactors, and sprint planning.

npx playbooks add skill kaakati/rails-enterprise-dev --skill technical-debt-patterns

Review the files below or copy the command above to add this skill to your agents.

Files (8)
SKILL.md
9.5 KB
---
name: "Technical Debt Patterns"
description: "Expert guide to detecting, categorizing, and prioritizing technical debt in Rails applications. Use when: (1) Auditing codebase health, (2) Planning refactoring sprints, (3) Estimating feature impact, (4) Identifying code smells, (5) Tracking deprecations. Trigger keywords: technical debt, code smell, complexity, cyclomatic, deprecation, legacy, refactor, audit, health check, god class"
version: 1.1.0
tags: [technical-debt, code-quality, refactoring, audit, complexity]
---

# Technical Debt Patterns

Expert patterns for detecting, categorizing, and prioritizing technical debt in Rails applications.

## Decision Tree: Debt Category Identification

```
What type of issue is this?
│
├─ Code structure problem?
│   ├─ Method too long (>20 lines) → Code Smell: Long Method
│   ├─ Class too large (>150 lines) → Code Smell: Large Class
│   ├─ Excessive parameter passing → Code Smell: Data Clump
│   └─ Method uses another object's data → Code Smell: Feature Envy
│
├─ Complexity issue?
│   ├─ Flog score >60 → Complexity: High
│   ├─ Cyclomatic complexity >10 → Complexity: High
│   ├─ Deep nesting (>3 levels) → Complexity: Nesting
│   └─ Too many conditionals → Complexity: Conditional
│
├─ Security concern?
│   ├─ SQL injection risk → Security: SQL Injection
│   ├─ XSS vulnerability → Security: XSS
│   ├─ Mass assignment issue → Security: Mass Assignment
│   └─ Outdated gem with CVE → Security: Dependency
│
├─ Outdated code?
│   ├─ Rails deprecation warning → Deprecation: Rails
│   ├─ Ruby version warning → Deprecation: Ruby
│   └─ Deprecated gem API → Deprecation: Gem
│
├─ Performance problem?
│   ├─ N+1 query pattern → Performance: N+1
│   ├─ Missing database index → Performance: Index
│   ├─ Memory bloat → Performance: Memory
│   └─ Slow query → Performance: Query
│
└─ Architecture violation?
    ├─ Fat controller → Architecture: Controller
    ├─ God object/model → Architecture: God Object
    ├─ Circular dependency → Architecture: Circular
    └─ Layer violation → Architecture: Layering
```

---

## NEVER Do These (Critical Anti-Patterns)

**NEVER ignore security debt** because "we'll fix it later":
```ruby
# WRONG - Ignoring SQL injection
User.where("name = '#{params[:name]}'")  # Security debt accumulates risk

# RIGHT - Fix immediately or track with Critical severity
User.where(name: params[:name])
```
→ Security debt has exponential risk growth. Track as Critical, not backlog.

**NEVER create technical debt to "fix" technical debt**:
```ruby
# WRONG - Adding wrapper to hide complexity
class PaymentWrapper
  def process
    @legacy_payment.complex_legacy_method  # Just hiding the problem
  end
end

# RIGHT - Either refactor properly or track explicitly
# If time-constrained, create beads issue with clear scope
```
→ Debt wrappers compound into "debt squared". Refactor or track, don't hide.

**NEVER disable linters globally to silence debt warnings**:
```ruby
# WRONG - Global disable in .rubocop.yml
Metrics/MethodLength:
  Enabled: false  # Hides ALL long method debt

# RIGHT - Explicit inline disable with justification
# rubocop:disable Metrics/MethodLength -- Legacy payment processor, tracked in PROJ-123
def complex_legacy_method
  # ...
end
# rubocop:enable Metrics/MethodLength
```
→ Global disables hide debt accumulation. Use inline disables with tracking.

**NEVER skip team discussion on Critical/High debt**:
```markdown
# WRONG - Solo decision on major debt
"I found a god object, I'll refactor it this sprint"

# RIGHT - Team alignment first
1. Document finding in debt report
2. Create beads issue with severity
3. Discuss in sprint planning
4. Get consensus on approach
```
→ Major refactoring affects the whole team. Collaborate before large changes.

**NEVER estimate features without considering debt in affected areas**:
```markdown
# WRONG - Ignoring debt in estimates
"Add payment retry logic: 2 story points"

# RIGHT - Include debt impact
"Add payment retry logic: 5 story points
 - 2 points: feature implementation
 - 3 points: PaymentService complexity (Flog 127) requires refactoring first"
```
→ Debt adds hidden cost. Include remediation in feature estimates.

---

## Code Smell Detection Patterns

### Long Method (>20 lines)

**Detection**:
```bash
# Find methods longer than 20 lines
awk '
  /^[[:space:]]*def / { start = NR; name = $2 }
  /^[[:space:]]*end/ && start > 0 {
    len = NR - start
    if (len > 20) print FILENAME ":" name " (" len " lines)"
    start = 0
  }
' app/**/*.rb
```

**Severity Thresholds**:
| Lines | Severity |
|-------|----------|
| 20-40 | Medium |
| 40-80 | High |
| >80 | Critical |

### Large Class (>150 lines)

**Detection**:
```bash
# Find classes larger than 150 lines
for file in app/models/*.rb app/services/*.rb; do
  lines=$(wc -l < "$file" 2>/dev/null)
  if [ "$lines" -gt 150 ]; then
    echo "$file: $lines lines"
  fi
done
```

**Severity Thresholds**:
| Lines | Severity |
|-------|----------|
| 150-300 | Medium |
| 300-500 | High |
| >500 | Critical |

### Feature Envy

Method uses another object's data more than its own.

**Detection Pattern**:
```ruby
# Smell: Method calls another object's methods repeatedly
def calculate_total(order)
  order.items.sum(&:price) +
    order.shipping_cost +
    order.tax_amount -
    order.discount_amount
end

# Fix: Move method to Order class
class Order
  def calculate_total
    items.sum(&:price) + shipping_cost + tax_amount - discount_amount
  end
end
```

### Data Clump

Same group of parameters passed together repeatedly.

**Detection Pattern**:
```ruby
# Smell: Repeated parameter group
def create_user(name, email, phone, address)
def update_user(name, email, phone, address)
def validate_user(name, email, phone, address)

# Fix: Extract to value object
class ContactInfo
  attr_reader :name, :email, :phone, :address
end

def create_user(contact_info)
def update_user(contact_info)
```

---

## Complexity Metrics

### Flog Score Thresholds

| Score | Rating | Action |
|-------|--------|--------|
| < 30 | Low | No action needed |
| 30-60 | Medium | Consider refactoring |
| 60-100 | High | Plan refactoring |
| > 100 | Critical | Immediate refactoring |

**Running Flog**:
```bash
# Overall complexity score
flog -q -g app/

# Top 10 most complex methods
flog -q app/ | head -10

# Score for specific file
flog app/services/payment_service.rb
```

### Cyclomatic Complexity

Measures independent execution paths through code.

| Complexity | Rating | Risk |
|------------|--------|------|
| 1-5 | Low | Easy to test |
| 6-10 | Medium | Moderate risk |
| 11-20 | High | Difficult to test |
| >20 | Critical | Very high risk |

---

## Severity Scoring Framework

Calculate overall severity using weighted factors:

```
Severity Score = (Blast × 0.30) + (Fix × 0.20) + (Risk × 0.30) + (Age × 0.10) + (Freq × 0.10)
```

| Factor | Weight | 1 (Low) | 3 (Medium) | 5 (High) |
|--------|--------|---------|------------|----------|
| Blast Radius | 30% | Single file | Module | System-wide |
| Fix Complexity | 20% | Trivial | Moderate | Major refactor |
| Risk Level | 30% | Cosmetic | Functional | Security/Data |
| Age | 10% | < 6 months | 6mo-2yr | > 2 years |
| Frequency | 10% | Rare path | Normal | Hot path |

**Severity Categories**:
- **Critical**: Score >= 4.0 (SLA: 1 sprint)
- **High**: Score >= 3.0 (SLA: 2 sprints)
- **Medium**: Score >= 2.0 (SLA: Quarterly)
- **Low**: Score < 2.0 (Opportunistic)

---

## Quick Reference Tables

### Detection Tools

| Tool | Purpose | Command |
|------|---------|---------|
| Flog | Complexity scoring | `flog -q app/` |
| Reek | Code smell detection | `reek app/` |
| Rubocop | Style + metrics | `rubocop --format json` |
| Brakeman | Security vulnerabilities | `brakeman -q` |
| bundler-audit | Gem CVEs | `bundle-audit check` |
| rails_best_practices | Rails anti-patterns | `rails_best_practices` |

### Effort Estimation

| Category | Typical Effort |
|----------|----------------|
| Long Method refactor | 2-4 hours |
| Large Class extraction | 1-3 days |
| God Object decomposition | 3-5 days |
| N+1 query fix | 1-2 hours |
| Security vulnerability | 2-8 hours |
| Deprecation update | 2-4 hours |
| Circular dependency fix | 2-5 days |

### Beads Integration

```bash
# Create debt issue
bd create --type task --priority 1 \
  --title "Tech Debt: [Description]" \
  --description "[Details]"

# Track debt item
bd update PROJ-123 --status in_progress

# Close after remediation
bd close PROJ-123 --reason "Refactored in commit abc123"
```

---

## References

For detailed patterns in each category, see:

- `references/code-smells.md` - Long method, large class, feature envy, data clump
- `references/complexity-metrics.md` - Flog, cyclomatic, cognitive complexity
- `references/deprecation-tracking.md` - Rails, Ruby, gem deprecations
- `references/security-debt.md` - Brakeman categories, OWASP patterns
- `references/performance-debt.md` - N+1 queries, indexes, memory
- `references/testing-debt.md` - Coverage gaps, flaky tests
- `references/architecture-debt.md` - God objects, circular deps, layers

---

## Integration with Other Skills

| Skill | Integration Point |
|-------|-------------------|
| `code-quality-gates` | Rubocop/Sorbet findings feed into debt report |
| `refactoring-workflow` | Debt items become refactoring targets |
| `rails-conventions` | Convention violations are architecture debt |
| `codebase-inspection` | Inspector discovers debt during analysis |

Overview

This skill is an expert guide for detecting, categorizing, and prioritizing technical debt in Rails applications. It codifies decision trees, detection scripts, metrics thresholds, and a severity scoring framework so teams can triage debt consistently. Apply it to produce actionable debt reports, estimate remediation effort, and feed tasks into existing tracking workflows.

How this skill works

The skill inspects code structure, complexity metrics, security findings, deprecations, performance patterns, and architectural violations using concrete detection patterns and CLI commands. It maps findings to debt categories (e.g., Code Smell, Complexity, Security, Deprecation, Performance, Architecture) and computes a weighted severity score to prioritize work. It also recommends remediation SLAs and generates beads-compatible task templates for tracking.

When to use it

  • During a codebase health audit or sprint zero
  • When planning refactoring sprints or technical spikes
  • Estimating feature work that touches legacy areas
  • Detecting and classifying code smells (long methods, large classes, data clumps)
  • Tracking Rails/Ruby/gem deprecations and CVEs

Best practices

  • Treat security debt as Critical; track and remediate or mitigate immediately
  • Avoid hidden wrappers that just hide legacy complexity; refactor or explicitly track scope
  • Never disable linters globally—use scoped inline exceptions with tracking IDs
  • Discuss Critical/High debt with the team before large refactors; add to sprint planning
  • Include debt remediation when estimating features; split estimates into feature + remediation parts

Example use cases

  • Run automated detectors (flog, reek, rubocop, brakeman) and convert outputs into prioritized beads tasks
  • Identify long methods and large classes with provided shell snippets and estimate refactor effort
  • Classify and score security findings and outdated gems for immediate mitigation
  • Find N+1 queries and missing indexes, estimate quick fixes vs. architectural changes
  • Use the severity formula to decide whether debt is sprint-level or quarterly work

FAQ

How is overall severity calculated?

Severity is a weighted score: Blast (30%), Fix complexity (20%), Risk (30%), Age (10%), Frequency (10%). Map the numeric score to Critical/High/Medium/Low and apply SLA guidance.

Which tools should I run for detection?

Use flog for complexity, reek and rubocop for smells and metrics, brakeman and bundle-audit for security, and rails_best_practices for Rails anti-patterns. Convert findings into tracked issues.