# Управление техническим долгом ## Навигация - [🏠 Главная страница курса](../../../README.md) - [📚 Модуль 9](../README.md) --- ## Что такое технический долг **Технический долг** — это накопленные в процессе разработки технические проблемы, которые требуют дополнительных усилий для их решения в будущем. ## Типы технического долга ### 1. Проблемы кода - Дублирование кода - Сложные методы - Неиспользуемый код - Плохие имена переменных ### 2. Проблемы архитектуры - Нарушение принципов SOLID - Слабая связанность - Отсутствие абстракций - Неправильное разделение ответственности ### 3. Проблемы инфраструктуры - Устаревшие зависимости - Неоптимальная конфигурация - Отсутствие мониторинга - Проблемы безопасности ## Оценка технического долга ### 1. Метрики кода ```yaml # 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. Метрики архитектуры ```yaml # 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. Идентификация проблем ```markdown # Technical Debt Inventory ## High Priority - [ ] Устаревшие зависимости (security vulnerabilities) - [ ] Критические баги в production - [ ] Проблемы производительности - [ ] Уязвимости безопасности ## Medium Priority - [ ] Дублирование кода - [ ] Сложные методы - [ ] Отсутствие тестов - [ ] Проблемы архитектуры ## Low Priority - [ ] Неиспользуемый код - [ ] Плохие имена переменных - [ ] Отсутствие документации - [ ] Стилистические проблемы ``` ### 2. Приоритизация ```yaml # 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. Планирование исправлений ```markdown # Technical Debt Remediation Plan ## Sprint 1: Critical Issues - [ ] Обновить устаревшие зависимости - [ ] Исправить критические баги - [ ] Устранить уязвимости безопасности ## Sprint 2: Architecture Issues - [ ] Рефакторинг сложных методов - [ ] Устранение дублирования кода - [ ] Улучшение архитектуры ## Sprint 3: Quality Issues - [ ] Добавление тестов - [ ] Улучшение документации - [ ] Оптимизация производительности ``` ## Инструменты управления техническим долгом ### 1. SonarQube ```yaml # 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 ```yaml # .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 ```python # 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 - Автоматические проверки - Уведомления о проблемах