- 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
393 lines
11 KiB
Markdown
393 lines
11 KiB
Markdown
# Управление техническим долгом
|
|
|
|
## Навигация
|
|
- [🏠 Главная страница курса](../../../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
|
|
- Автоматические проверки
|
|
- Уведомления о проблемах
|