Files
sa-lessons/modules/module9/sections/07-technical-debt-management.md
Alexander Abakumov 15e744da49 Initial commit: Complete Software Architecture course with 11 modules
- Added comprehensive course structure with 11 modules
- Included theoretical content, practical examples, and tasks
- Multi-language code examples (Java, Rust, Node.js, Python)
- Detailed analysis of architectural approaches and trade-offs
- Complete caching strategies documentation
- Architecture examples from real-world systems (Twitter, Netflix, Uber)
- Structured navigation and learning path
- Ready for educational use
2025-09-09 22:08:07 +03:00

11 KiB

Управление техническим долгом

Навигация


Что такое технический долг

Технический долг — это накопленные в процессе разработки технические проблемы, которые требуют дополнительных усилий для их решения в будущем.

Типы технического долга

1. Проблемы кода

  • Дублирование кода
  • Сложные методы
  • Неиспользуемый код
  • Плохие имена переменных

2. Проблемы архитектуры

  • Нарушение принципов SOLID
  • Слабая связанность
  • Отсутствие абстракций
  • Неправильное разделение ответственности

3. Проблемы инфраструктуры

  • Устаревшие зависимости
  • Неоптимальная конфигурация
  • Отсутствие мониторинга
  • Проблемы безопасности

Оценка технического долга

1. Метрики кода

# SonarQube Quality Gates
quality_gates:
  code_smells:
    - name: "Code Smells"
      threshold: 100
      severity: "Warning"
    
    - name: "Duplicated Lines"
      threshold: 3%
      severity: "Warning"
    
    - name: "Complexity"
      threshold: 10
      severity: "Warning"
  
  bugs:
    - name: "Bugs"
      threshold: 0
      severity: "Error"
    
    - name: "Vulnerabilities"
      threshold: 0
      severity: "Error"
  
  coverage:
    - name: "Coverage"
      threshold: 80%
      severity: "Warning"
    
    - name: "Duplicated Lines"
      threshold: 3%
      severity: "Warning"

2. Метрики архитектуры

# Architecture Quality Metrics
architecture_metrics:
  coupling:
    - name: "Afferent Coupling"
      threshold: 10
      severity: "Warning"
    
    - name: "Efferent Coupling"
      threshold: 10
      severity: "Warning"
  
  cohesion:
    - name: "Lack of Cohesion"
      threshold: 0.5
      severity: "Warning"
    
    - name: "Tight Coupling"
      threshold: 0.8
      severity: "Error"
  
  complexity:
    - name: "Cyclomatic Complexity"
      threshold: 10
      severity: "Warning"
    
    - name: "Cognitive Complexity"
      threshold: 15
      severity: "Warning"

Управление техническим долгом

1. Идентификация проблем

# Technical Debt Inventory

## High Priority
- [ ] Устаревшие зависимости (security vulnerabilities)
- [ ] Критические баги в production
- [ ] Проблемы производительности
- [ ] Уязвимости безопасности

## Medium Priority
- [ ] Дублирование кода
- [ ] Сложные методы
- [ ] Отсутствие тестов
- [ ] Проблемы архитектуры

## Low Priority
- [ ] Неиспользуемый код
- [ ] Плохие имена переменных
- [ ] Отсутствие документации
- [ ] Стилистические проблемы

2. Приоритизация

# Technical Debt Prioritization Matrix
prioritization:
  criteria:
    - name: "Impact"
      weight: 0.4
      values: [1, 2, 3, 4, 5]
    
    - name: "Urgency"
      weight: 0.3
      values: [1, 2, 3, 4, 5]
    
    - name: "Effort"
      weight: 0.2
      values: [1, 2, 3, 4, 5]
    
    - name: "Risk"
      weight: 0.1
      values: [1, 2, 3, 4, 5]
  
  scoring:
    - name: "High Priority"
      threshold: 4.0
      color: "red"
    
    - name: "Medium Priority"
      threshold: 3.0
      color: "yellow"
    
    - name: "Low Priority"
      threshold: 2.0
      color: "green"

3. Планирование исправлений

# Technical Debt Remediation Plan

## Sprint 1: Critical Issues
- [ ] Обновить устаревшие зависимости
- [ ] Исправить критические баги
- [ ] Устранить уязвимости безопасности

## Sprint 2: Architecture Issues
- [ ] Рефакторинг сложных методов
- [ ] Устранение дублирования кода
- [ ] Улучшение архитектуры

## Sprint 3: Quality Issues
- [ ] Добавление тестов
- [ ] Улучшение документации
- [ ] Оптимизация производительности

Инструменты управления техническим долгом

1. SonarQube

# sonar-project.properties
sonar.projectKey=myproject
sonar.projectName=My Project
sonar.projectVersion=1.0

sonar.sources=src/main/java
sonar.tests=src/test/java
sonar.java.binaries=target/classes
sonar.java.libraries=target/lib/*.jar

sonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml
sonar.junit.reportPaths=target/surefire-reports

sonar.qualitygate.wait=true
sonar.qualitygate.timeout=300

2. CodeClimate

# .codeclimate.yml
version: "2"

checks:
  argument-count:
    config:
      threshold: 4
  complex-logic:
    config:
      threshold: 4
  file-lines:
    config:
      threshold: 250
  method-complexity:
    config:
      threshold: 5
  method-lines:
    config:
      threshold: 50
  nested-control-flow:
    config:
      threshold: 4
  return-statements:
    config:
      threshold: 4
  similar-code:
    config:
      threshold: 50
  identical-code:
    config:
      threshold: 50

exclude_patterns:
  - "spec/**/*"
  - "test/**/*"
  - "vendor/**/*"
  - "node_modules/**/*"

3. Custom Tools

# technical_debt_analyzer.py
import ast
import os
from typing import List, Dict, Any

class TechnicalDebtAnalyzer:
    def __init__(self):
        self.issues = []
    
    def analyze_file(self, file_path: str) -> List[Dict[str, Any]]:
        """Анализирует файл на предмет технического долга"""
        with open(file_path, 'r', encoding='utf-8') as file:
            content = file.read()
        
        tree = ast.parse(content)
        issues = []
        
        # Анализ сложности методов
        for node in ast.walk(tree):
            if isinstance(node, ast.FunctionDef):
                complexity = self.calculate_complexity(node)
                if complexity > 10:
                    issues.append({
                        'type': 'high_complexity',
                        'severity': 'warning',
                        'message': f'Method {node.name} has complexity {complexity}',
                        'line': node.lineno,
                        'file': file_path
                    })
                
                # Анализ длины методов
                if len(node.body) > 20:
                    issues.append({
                        'type': 'long_method',
                        'severity': 'info',
                        'message': f'Method {node.name} is too long ({len(node.body)} lines)',
                        'line': node.lineno,
                        'file': file_path
                    })
        
        return issues
    
    def calculate_complexity(self, node: ast.FunctionDef) -> int:
        """Вычисляет цикломатическую сложность метода"""
        complexity = 1  # Базовая сложность
        
        for child in ast.walk(node):
            if isinstance(child, (ast.If, ast.While, ast.For, ast.AsyncFor)):
                complexity += 1
            elif isinstance(child, ast.ExceptHandler):
                complexity += 1
            elif isinstance(child, ast.BoolOp):
                complexity += len(child.values) - 1
        
        return complexity
    
    def analyze_project(self, project_path: str) -> List[Dict[str, Any]]:
        """Анализирует весь проект"""
        all_issues = []
        
        for root, dirs, files in os.walk(project_path):
            for file in files:
                if file.endswith('.py'):
                    file_path = os.path.join(root, file)
                    issues = self.analyze_file(file_path)
                    all_issues.extend(issues)
        
        return all_issues
    
    def generate_report(self, issues: List[Dict[str, Any]]) -> str:
        """Генерирует отчет о техническом долге"""
        report = "# Technical Debt Report\n\n"
        
        # Группировка по типам
        by_type = {}
        for issue in issues:
            issue_type = issue['type']
            if issue_type not in by_type:
                by_type[issue_type] = []
            by_type[issue_type].append(issue)
        
        # Генерация отчета
        for issue_type, type_issues in by_type.items():
            report += f"## {issue_type.replace('_', ' ').title()}\n"
            report += f"Count: {len(type_issues)}\n\n"
            
            for issue in type_issues:
                report += f"- **{issue['file']}:{issue['line']}** - {issue['message']}\n"
            
            report += "\n"
        
        return report

# Использование
analyzer = TechnicalDebtAnalyzer()
issues = analyzer.analyze_project('./src')
report = analyzer.generate_report(issues)
print(report)

Стратегии управления

1. Проактивное управление

  • Регулярные рефакторинги
  • Непрерывная интеграция
  • Автоматизированные проверки

2. Реактивное управление

  • Исправление по мере обнаружения
  • Планирование исправлений
  • Приоритизация проблем

3. Гибридный подход

  • Критические проблемы исправляются немедленно
  • Остальные планируются в спринтах
  • Регулярные рефакторинги

Best Practices

1. Измерение

  • Регулярный анализ метрик
  • Отслеживание трендов
  • Установка пороговых значений

2. Планирование

  • Включение в спринты
  • Приоритизация по важности
  • Оценка усилий

3. Коммуникация

  • Информирование команды
  • Документирование проблем
  • Отчеты для руководства

4. Автоматизация

  • Интеграция в CI/CD
  • Автоматические проверки
  • Уведомления о проблемах