Оценка архитектурных альтернатив
Спор «монолит или микросервисы», «REST или очередь», «PostgreSQL или Cassandra» редко имеет один правильный ответ для всех. Ответ зависит от контекста проекта: нагрузка, число команд, зрелость эксплуатации, регуляторика, сроки. Эта статья — практичный шаблон оценки альтернатив (trade-off analysis) для архитектора и техлида: как сравнивать варианты честно, фиксировать решение и не спорить «на вкус».
Ваша задача — записать, почему в нашем случае вариант A лучше B, и что мы готовы за это заплатить. Один ADR на 15–30 строк часто ценнее десятистраничного документа.
Связь: NFR, ADR в основах, техническое письмо — архитектурное решение, роль архитектора, Event Storming.
Зачем формальная оценка
Без явной оценки команда повторяет одни и те же споры каждый квартал. Новый техлид снова предлагает «разрезать монолит», старый — «вернуть всё в один деплой». Формальная оценка здесь — память и общий язык:
- все видят одни и те же критерии;
- веса согласованы с бизнесом («срок важнее идеальной согласованности»);
- решение можно пересмотреть, когда изменился контекст (новая нагрузка, новая команда).
Тяжёлые методы вроде ATAM (Architecture Tradeoff Analysis Method) существуют для крупных систем; для большинства agile-команд достаточно матрицы на 1–2 страницы + ADR + короткий review.
Термины простым языком
| Термин | Объяснение |
|---|---|
| Trade-off | Компромисс: усилили одно — ослабили другое (скорость релиза ↔ сложность эксплуатации). |
| Архитектурно значимое требование | NFR, от которого меняется выбор структуры (не «цвет кнопки»). |
| Quality attribute | Атрибут качества: производительность, доступность, безопасность и т.д. |
| Deal-breaker | Условие, при котором вариант отбрасывается без дальнейшего обсуждения. |
| Spike | Короткий эксперимент (обычно 2–5 дней), чтобы проверить риск до большого проекта. |
| Fitness function | Автоматическая проверка в CI (например, запрет импортов между модулями). |
| Eventual consistency | Данные со временем сходятся между частями системы; мгновенной общей картины нет. |
Когда нужна формальная оценка
- Выбор стиля развёртывания или способа интеграции.
- Смена брокера, БД, облака, модели согласованности.
- Спор между командами, который повторяется каждый квартал.
- Требование аудита или регулятора «обосновать решение».
Когда достаточно короткого обсуждения: переименование пакета, выбор между двумя библиотеками с одинаковым риском (достаточно spike на 1–2 дня и одной строки в ADR).
Шаг 1. Зафиксировать контекст и драйверы
Контекст — одна фраза проблемы, без решения внутри:
«Нужно обрабатывать до 3 000 заказов/мин с p95 ≤ 400 мс и выдерживать падение одной зоны доступности (AZ) без потери принятых заказов».
Плохой контекст: «Нужны микросервисы» — это уже решение, а не проблема.
Архитектурно значимые требования — обычно 3–6 штук, не двадцать. Иначе таблицу заполняют формально и забывают.
| Атрибут | Вопрос, который задаём | Пример формулировки |
|---|---|---|
| Производительность | Какая нагрузка и задержка? | p95 ≤ 400 мс при 3k RPM |
| Доступность | Какой простой допустим? | 99.9%, RTO 15 мин |
| Масштабируемость | Как растём? | Горизонтально без простоя |
| Безопасность | Где границы доверия? | PCI: карты только в Payment context |
| Сопровождаемость | Сколько команд? | 4 команды, независимый релиз раз в 2 недели |
| Стоимость | Бюджет инфры/людей? | OpEx облака ≤ X / месяц |
Полный каталог атрибутов (ISO/IEC 25010) в жизни сводят к такому короткому списку. Развёрнутый разбор — модель ISO/IEC 25010.
Откуда брать цифры: аналитик и бизнес (SLA), ops (текущие метрики), нагрузочные тесты, прошлые инциденты. Если цифры неизвестны — честно пишем «уточнить до выбора» и закладываем spike на измерение.
Шаг 2. Набросать 2–4 варианта (не больше)
Пример для подсистемы заказов:
- A. Модульный монолит + read replicas.
- B. Микросервисы Order / Payment / Inventory, синхронный REST.
- C. То же, но Order публикует события → Payment и Inventory (async).
- D. Оставить легаси, Strangler только для витрины.
Правила хороших вариантов:
- Каждый вариант меняет границы ответственности или способ интеграции, а не только «переезд в Kubernetes».
- Есть вариант ближе к текущему (baseline), чтобы видеть цену изменения.
- Варианты реализуемы командой в обозримый срок (или явно помечены как «через 2 года»).
Шаг 3. Матрица trade-off
Оценки: ++ / + / 0 / − / −− или баллы 1–5 — главное, одна шкала для всех и пояснение в легенде.
| Критерий (вес) | A Модульный монолит | B MS sync | C MS events |
|---|---|---|---|
| Time-to-market (×3) | ++ | − | − |
| p95 latency (×3) | + | 0 | + |
| Независимый релиз (×2) | − | ++ | ++ |
| Сложность эксплуатации (×2) | ++ | −− | − |
| Согласованность заказа (×3) | ++ | + | 0 |
| Стоимость (×1) | ++ | − | − |
Веса ставятся с бизнесом: для стартапа часто ×3 на time-to-market, для банка — на согласованность и аудит.
Как считать (упрощённо): для каждого варианта умножьте оценку на вес и сложите. Итог служит ориентиром для обсуждения; матрица сама по себе не выбирает победителя. Если матрица указывает на «C», а продукт обещает мгновенную оплату — побеждает продукт, и матрицу нужно дополнить критерием UX/согласованности для пользователя.
Вариант C выигрывает по независимым релизам, но проигрывает по объяснимости для пользователя (eventual consistency). Если витрина обещает «мгновенную оплату», нужен UX под задержку или синхронный шаг до подтверждения — иначе матрица «красивая», продукт — нет.
Шаг 4. Риски и «что убьёт вариант»
Для каждого варианта запишите deal-breaker — условие отказа:
| Вариант | Пример deal-breaker | Что сделать до выбора |
|---|---|---|
| B (MS sync) | Нет зрелого tracing → MTTR > 4 ч при инциденте | Внедрить observability, потом резать |
| C (events) | Нет идемпотентных consumer’ов → дубли заказов | Spike на повторную доставку сообщений |
| A (монолит) | 4 команды ломают друг другу main каждый день | Модульные границы + CI на граф зависимостей |
Spike на 3–5 дней дешевле, чем полгода «распределённого монолита» (много сервисов, но одна общая БД и хаотичные вызовы).
Шаг 5. Решение и ADR
Краткий ADR (можно в docs/adr/001-order-architecture.md):
# ADR-001: Архитектура подсистемы заказов
## Статус
Принято (2025-05-20)
## Контекст
3k RPM, 4 команды, легаси-Billing менять нельзя 12 месяцев.
## Рассмотренные варианты
- A модульный монолит
- B микросервисы + sync REST
- C микросервисы + события
## Решение
Модульный монолит Order+Fulfillment; Payment — Strangler через ACL;
события только на границе с Billing.
## Последствия
+ быстрый релиз, одна транзакция для заказа
− Payment остаётся узким местом до миграции
− нужен ADR-002 при выходе Billing из легаси
## Метрики пересмотра
Если p95 > 400 мс при 2k RPM или MTTR > 2 ч — пересмотр варианта C.
ADR читает новый разработчик за 5 минут и понимает ограничения, в которых писать код.
Architecture review (лёгкий формат)
30–45 минут, участники: автор решения, техлиды затронутых команд, по желанию ops/security.
| Блок | Время | Содержание |
|---|---|---|
| Контекст и NFR | 5 мин | Проблема и цифры |
| Варианты и матрица | 10 мин | 2–4 варианта, веса |
| Риски и spike’и | 10 мин | Deal-breaker’ы, эксперименты |
| Решение и действия | 10 мин | ADR, владельцы, сроки |
Ответственность за решение остаётся у назначенного архитектора/техлида; review собирает риски, а не голосование «большинством».
Fitness functions (по желанию): автопроверки в CI — запрет циклических зависимостей между модулями (ArchUnit, Deptrac), линтер на запрещённые импорты между контекстами. Так «договорённость на схеме» не разъезжается через месяц в коде.
Мини-кейс — синхронный REST и очередь
Сценарий: после OrderCreated нужно списать остаток и отправить чек.
| Sync REST | Async event | |
|---|---|---|
| Плюс | Проще отладка, ошибка сразу в UI | Слабая связность, пики сглаживаются |
| Минус | Цепочка отказов, latency суммируется | Задержка, дубли, сложнее тесты |
| Когда уместно | Мало вызовов, жёсткая согласованность для пользователя | Высокий throughput, допустима задержка на экране |
Частый компромисс: sync до оплаты (пользователь ждёт результат), async после (email, аналитика, склад в фоне). Это и есть осознанный trade-off, а не «всё в Kafka».
Частые ловушки при оценке
| Ловушка | Как избежать |
|---|---|
| Сравнение «на бумаге» без spike | 2–5 дней на самый рискованный вариант |
| 15 критериев без весов | 3–6 драйверов с весами от бизнеса |
| Игнор организации | 1 команда — монолит часто рационален; 4 — нужны границы |
| Забыть стоимость владения | Лицензии, облако, 24/7 on-call |
| Нет даты пересмотра ADR | Условие «пересмотреть, если p95 > X» |
Дальше
- Event Storming — откуда брать границы для вариантов.
- Threat modeling — если в матрице важен security.
- Декомпозиция монолита · микросервисные паттерны
См. также
Другие статьи этого же раздела в боковом меню (как на странице «О разделе»). Каждая система имеет свою архитектуру построения; систему нужно разворачивать под нагрузку; нужно понимать обновления и исправление ошибок; рано или поздно — интеграция, безопасность, расширение и поддержка. Подход к проектированию — это стратегия, которая определяет, откуда начинается работа над системой и в каком порядке формируются её компоненты. Принципы проектирования - критерии оценки решений и ориентиры для поддерживаемого и безопасно изменяемого кода. Проектирование сервисов - от микросервисов до доменных сервисов в DDD и как не путать уровни ответственности. Любое действие пользователя — это запрос на изменение состояния, а не прямая команда. Как формулировать измеримые NFR и переводить их в архитектурные решения: масштабирование, отказоустойчивость, безопасность, observability. Традиционный подход: 1. Команда проектирует систему, 2. Пишет код, 3. По завершении — создаёт документацию для сдачи заказчику или архивирования. Проектирование баз данных — это системная инженерная дисциплина, направленная на создание структуры хранения данных, которая обеспечивает корректность, целостность, производительность, расширяемость. Современные программные системы редко существуют изолированно. Декомпозиция, API Gateway, database per service, Saga, observability и антипаттерны — практика микросервисов. Переходите к изучению этой статьи только после того, как изучите микросервисы. Распределённые системы представляют собой совокупность независимых вычислительных узлов, которые взаимодействуют между собой через сеть для достижения общей цели.Проектирование программных систем
Подходы к проектированию
Принципы проектирования
Проектирование сервисов и методов
Проектирование функциональных UI
Проектирование под нефункциональные требования
Документация как инструмент проектирования
Проектирование баз данных
Проектирование API и интеграций
Паттерны микросервисной архитектуры
Проектирование веб-разработки
Проектирование распределенных систем