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
This commit is contained in:
commit
15e744da49
107 files changed
+61762
No files matched your search
@@ -0,0 +1,280 @@
|
||||
# Architecture Decision Records (ADR)
|
||||
|
||||
## Навигация
|
||||
- [🏠 Главная страница курса](../../../README.md)
|
||||
- [📚 Модуль 7](../README.md)
|
||||
|
||||
---
|
||||
|
||||
## Что такое ADR
|
||||
|
||||
**Architecture Decision Record (ADR)** — документ, который фиксирует важное архитектурное решение, принятое в проекте.
|
||||
|
||||
## Структура ADR
|
||||
|
||||
### 1. Статус
|
||||
- **Proposed** — предложено
|
||||
- **Accepted** — принято
|
||||
- **Deprecated** — устарело
|
||||
- **Superseded** — заменено
|
||||
|
||||
### 2. Контекст
|
||||
- Описание ситуации
|
||||
- Проблема, которую нужно решить
|
||||
- Ограничения и требования
|
||||
|
||||
### 3. Решение
|
||||
- Описание принятого решения
|
||||
- Обоснование выбора
|
||||
- Альтернативы, которые рассматривались
|
||||
|
||||
### 4. Последствия
|
||||
- Положительные последствия
|
||||
- Отрицательные последствия
|
||||
- Риски и митигации
|
||||
|
||||
## Пример ADR
|
||||
|
||||
**Технический пример - Advanced ADR Management:**
|
||||
|
||||
```markdown
|
||||
# ADR-001: Использование микросервисной архитектуры
|
||||
|
||||
## Статус
|
||||
Принято
|
||||
|
||||
## Дата
|
||||
2024-01-15
|
||||
|
||||
## Контекст
|
||||
Наша система электронной коммерции растет и становится сложнее. Монолитная архитектура создает следующие проблемы:
|
||||
|
||||
- Сложность развертывания изменений
|
||||
- Технологическая привязка к одному стеку
|
||||
- Сложность масштабирования отдельных компонентов
|
||||
- Риск каскадных отказов
|
||||
|
||||
Команда разработки увеличилась до 15 человек, и мы планируем дальнейший рост.
|
||||
|
||||
## Решение
|
||||
Мы решили перейти к микросервисной архитектуре со следующими принципами:
|
||||
|
||||
- Каждый сервис отвечает за один бизнес-домен
|
||||
- Сервисы независимо развертываются
|
||||
- Сервисы имеют собственные базы данных
|
||||
- Коммуникация через REST API и события
|
||||
|
||||
## Альтернативы
|
||||
1. **Модульный монолит** — разделение на модули внутри одного приложения
|
||||
2. **SOA** — сервисно-ориентированная архитектура
|
||||
3. **Оставить монолит** — продолжить развитие текущей архитектуры
|
||||
|
||||
## Последствия
|
||||
|
||||
### Положительные
|
||||
- Независимое развертывание сервисов
|
||||
- Возможность использования разных технологий
|
||||
- Лучшая масштабируемость
|
||||
- Изоляция отказов
|
||||
|
||||
### Отрицательные
|
||||
- Увеличение сложности системы
|
||||
- Проблемы с распределенными транзакциями
|
||||
- Сложность мониторинга
|
||||
- Overhead коммуникации
|
||||
|
||||
### Риски
|
||||
- **Сложность отладки** — митигация через distributed tracing
|
||||
- **Проблемы с данными** — митигация через event sourcing
|
||||
- **Сетевые задержки** — митигация через кэширование
|
||||
|
||||
## Реализация
|
||||
- Начать с выделения User Service
|
||||
- Использовать API Gateway для маршрутизации
|
||||
- Настроить мониторинг и логирование
|
||||
- Постепенно выделять остальные сервисы
|
||||
|
||||
## Метрики успеха
|
||||
- Время развертывания: < 5 минут
|
||||
- Время восстановления: < 30 минут
|
||||
- Доступность: > 99.9%
|
||||
- Производительность: P95 < 200ms
|
||||
```
|
||||
|
||||
**Технический пример - ADR Management System:**
|
||||
|
||||
```java
|
||||
// ADR Management Service
|
||||
@Service
|
||||
public class ADRManagementService {
|
||||
|
||||
@Autowired
|
||||
private ADRRepository adrRepository;
|
||||
|
||||
@Autowired
|
||||
private NotificationService notificationService;
|
||||
|
||||
@Autowired
|
||||
private VersionControlService versionControlService;
|
||||
|
||||
public ADR createADR(CreateADRRequest request) {
|
||||
// Валидация
|
||||
validateADRRequest(request);
|
||||
|
||||
// Создание ADR
|
||||
ADR adr = ADR.builder()
|
||||
.id(generateADRId())
|
||||
.title(request.getTitle())
|
||||
.status(ADRStatus.PROPOSED)
|
||||
.context(request.getContext())
|
||||
.decision(request.getDecision())
|
||||
.alternatives(request.getAlternatives())
|
||||
.consequences(request.getConsequences())
|
||||
.author(request.getAuthor())
|
||||
.createdDate(LocalDateTime.now())
|
||||
.build();
|
||||
|
||||
// Сохранение в БД
|
||||
adr = adrRepository.save(adr);
|
||||
|
||||
// Создание файла в Git
|
||||
createADRFile(adr);
|
||||
|
||||
// Уведомление команды
|
||||
notifyTeamAboutNewADR(adr);
|
||||
|
||||
return adr;
|
||||
}
|
||||
|
||||
public ADR updateADRStatus(Long adrId, ADRStatus newStatus, String comment) {
|
||||
ADR adr = adrRepository.findById(adrId)
|
||||
.orElseThrow(() -> new ADRNotFoundException("ADR not found"));
|
||||
|
||||
// Проверяем права на изменение статуса
|
||||
validateStatusChangePermission(adr, newStatus);
|
||||
|
||||
// Обновляем статус
|
||||
adr.setStatus(newStatus);
|
||||
adr.setLastModified(LocalDateTime.now());
|
||||
adr.setStatusComment(comment);
|
||||
|
||||
adr = adrRepository.save(adr);
|
||||
|
||||
// Обновляем файл в Git
|
||||
updateADRFile(adr);
|
||||
|
||||
// Уведомляем команду об изменении
|
||||
notifyTeamAboutStatusChange(adr);
|
||||
|
||||
return adr;
|
||||
}
|
||||
|
||||
public List<ADR> getADRsByStatus(ADRStatus status) {
|
||||
return adrRepository.findByStatus(status);
|
||||
}
|
||||
|
||||
public List<ADR> getADRsByDomain(String domain) {
|
||||
return adrRepository.findByDomain(domain);
|
||||
}
|
||||
|
||||
public ADRImpactAnalysis analyzeImpact(Long adrId) {
|
||||
ADR adr = adrRepository.findById(adrId)
|
||||
.orElseThrow(() -> new ADRNotFoundException("ADR not found"));
|
||||
|
||||
return ADRImpactAnalysis.builder()
|
||||
.affectedServices(analyzeAffectedServices(adr))
|
||||
.requiredChanges(analyzeRequiredChanges(adr))
|
||||
.estimatedEffort(estimateEffort(adr))
|
||||
.risks(identifyRisks(adr))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Scheduled(cron = "0 0 9 * * MON") // Каждый понедельник в 9:00
|
||||
public void reviewADRs() {
|
||||
List<ADR> proposedADRs = getADRsByStatus(ADRStatus.PROPOSED);
|
||||
|
||||
for (ADR adr : proposedADRs) {
|
||||
if (isADRStale(adr)) {
|
||||
notifyTeamAboutStaleADR(adr);
|
||||
}
|
||||
}
|
||||
|
||||
// Генерируем отчет по ADR
|
||||
generateADRReport();
|
||||
}
|
||||
|
||||
private void createADRFile(ADR adr) {
|
||||
String fileName = String.format("adr/%04d-%s.md", adr.getId(),
|
||||
adr.getTitle().toLowerCase().replaceAll("\\s+", "-"));
|
||||
|
||||
String content = generateADRMarkdown(adr);
|
||||
|
||||
versionControlService.createFile(fileName, content,
|
||||
String.format("Add ADR-%d: %s", adr.getId(), adr.getTitle()));
|
||||
}
|
||||
|
||||
private void updateADRFile(ADR adr) {
|
||||
String fileName = String.format("adr/%04d-%s.md", adr.getId(),
|
||||
adr.getTitle().toLowerCase().replaceAll("\\s+", "-"));
|
||||
|
||||
String content = generateADRMarkdown(adr);
|
||||
|
||||
versionControlService.updateFile(fileName, content,
|
||||
String.format("Update ADR-%d: %s", adr.getId(), adr.getTitle()));
|
||||
}
|
||||
|
||||
private String generateADRMarkdown(ADR adr) {
|
||||
StringBuilder markdown = new StringBuilder();
|
||||
|
||||
markdown.append(String.format("# ADR-%d: %s\n\n", adr.getId(), adr.getTitle()));
|
||||
markdown.append("## Статус\n");
|
||||
markdown.append(adr.getStatus().getDisplayName()).append("\n\n");
|
||||
markdown.append("## Дата\n");
|
||||
markdown.append(adr.getCreatedDate().format(DateTimeFormatter.ISO_LOCAL_DATE)).append("\n\n");
|
||||
markdown.append("## Контекст\n");
|
||||
markdown.append(adr.getContext()).append("\n\n");
|
||||
markdown.append("## Решение\n");
|
||||
markdown.append(adr.getDecision()).append("\n\n");
|
||||
markdown.append("## Альтернативы\n");
|
||||
markdown.append(adr.getAlternatives()).append("\n\n");
|
||||
markdown.append("## Последствия\n");
|
||||
markdown.append(adr.getConsequences()).append("\n\n");
|
||||
|
||||
if (adr.getStatusComment() != null) {
|
||||
markdown.append("## Комментарии\n");
|
||||
markdown.append(adr.getStatusComment()).append("\n\n");
|
||||
}
|
||||
|
||||
return markdown.toString();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Лучшие практики ADR
|
||||
|
||||
### 1. Ведите ADR для всех важных решений
|
||||
- Технологические решения
|
||||
- Архитектурные паттерны
|
||||
- Интеграционные решения
|
||||
- Операционные решения
|
||||
|
||||
### 2. Обновляйте статус ADR
|
||||
- Отслеживайте изменения
|
||||
- Документируйте причины изменений
|
||||
- Архивируйте устаревшие ADR
|
||||
|
||||
### 3. Используйте шаблоны
|
||||
- Стандартизируйте структуру
|
||||
- Обеспечивайте консистентность
|
||||
- Упрощайте создание новых ADR
|
||||
|
||||
## Заключение
|
||||
|
||||
ADR являются важным инструментом документирования архитектурных решений:
|
||||
|
||||
1. **Фиксация решений** — записывают важные архитектурные выборы
|
||||
2. **Контекст и обоснование** — объясняют почему было принято решение
|
||||
3. **Отслеживание изменений** — показывают эволюцию архитектуры
|
||||
4. **Обучение команды** — помогают новым участникам понять решения
|
||||
|
||||
Правильное ведение ADR значительно улучшает понимание архитектуры проекта и облегчает принятие будущих решений.
|
||||
Reference in new issue
Block a user