# 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 getADRsByStatus(ADRStatus status) { return adrRepository.findByStatus(status); } public List 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 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 значительно улучшает понимание архитектуры проекта и облегчает принятие будущих решений.