Представьте: команда несколько дней обсуждала архитектуру, разошлась довольная, а через месяц никто не помнит, что именно решили и почему. Новый коллега предлагает те же варианты, которые уже отвергли. В проде всплывает сценарий падения, который никто не рассматривал.
Именно поэтому дизайн нужно записывать и проводить через ревью. Дизайн, который не записан — это мнение одного человека. Ревью делает его общим решением, на которое можно опираться.
Что такое design doc
Design doc — это короткий инженерный документ, который фиксирует: что строим, почему именно так, и какие варианты отвергли. Не презентация руководству, не техническое задание — а рабочий документ для команды.
Типичная структура:
# Платформа уведомлений — design doc
Статус: на ревью | Автор: ... | Ревьюеры: ... | Дата: ...
1. Контекст и задача — зачем строим, что болит сейчас
2. Требования — функциональные, числа, анти-требования
3. Оценки — расчёт нагрузки, выводы из чисел
4. Предлагаемый дизайн — контракты, модель данных, схема, горячие точки
5. Отказы и деградация — таблица «что лежит → что видит пользователь»
6. Рассмотренные альтернативы — что отвергли и почему
7. Развилки → ADR — ссылки на записанные решения
8. План: первая версия и далее — что строим сейчас, что отложено
9. Открытые вопросы — честный список нерешённого
Три секции особенно важны:
- Альтернативы — без них ревьюеры предложат те же варианты заново. Через год их принесёт новый коллега.
- Отказы и деградация — дизайн без сценариев падения не дизайн.
- Открытые вопросы — если список пуст, документ либо гениален, либо авторы не думали. Второй вариант вероятнее.
Как выглядит заполненный раздел
Оглавление показывает, что должно быть; разница между «знаю структуру» и «умею написать» — в том, как выглядит один раздел на самом деле. Вот «Рассмотренные альтернативы» целиком, на нашем же примере уведомлений:
## 6. Рассмотренные альтернативы
### 6.1. Очередь в PostgreSQL вместо Kafka
Что предлагалось: таблица задач, выборка с блокировкой строк, отправщики
читают её порциями. Не нужна новая система в эксплуатации, событие и
бизнес-запись пишутся одной транзакцией.
Почему отвергли: при 6000 сообщений в секунду на пике это вставка,
обновление и уборка мусора на каждое сообщение — по нашей прикидке
15–20 % ресурсов базы, которая нужна на обслуживание ленты. Второе:
нельзя переиграть поток для нового потребителя (аналитика) и для
восстановления счётчика непрочитанных.
При каких условиях вернёмся: если поток окажется ниже 500 в секунду
(то есть прикидка завышена в 10 раз) и от переигрывания откажемся.
### 6.2. Отправка напрямую из сервиса заказов
Что предлагалось: каждый сервис сам отправляет письма и пуши по своим
шаблонам, без отдельной платформы.
Почему отвергли: шесть сервисов уже отправляют письма тремя разными
способами; предпочтения пользователя и отписка дублируются в каждом,
и отписка не работает глобально — это и было исходной болью (см. раздел 1).
При каких условиях вернёмся: не вернёмся; это то, от чего уходим.
Что делает такой раздел работающим, по частям: у каждой альтернативы есть имя и одно предложение о сути (не надо восстанавливать по памяти, о чём речь); причина отказа опирается на число или на факт, а не на «не подходит» и «не масштабируется»; и есть строка «при каких условиях вернёмся» — самая полезная и самая редкая. Она превращает решение из приговора в условное: через год, когда числа изменятся, видно, надо ли пересматривать. И она же снимает главный спор на ревью — не «кто прав», а «при каких числах прав каждый».
Тот же принцип у остальных разделов: число или факт вместо оценки. В требованиях — «6000 в секунду на пике, допущение: множитель 5 от среднего», а не «высокая нагрузка». В отказах — «пользователь видит уведомление в ленте, пуш придёт позже», а не «деградируем корректно». В открытых вопросах — «не решили, кто владеет шаблонами: маркетинг или разработка; решаем до 10 октября, решает такой-то», а не «нужно уточнить».
Про объём есть ходовой ориентир — 3–6 страниц. Это не норматив из стандарта, а наблюдение команд, которые такие документы пишут: пятнадцатистраничные простыни не читает никто, а всё, что не влезло, уходит в приложения и ссылки. Сверяйтесь не с цифрой, а с реальностью: если ревьюеры дочитывают до конца и задают вопросы по последней секции — объём нормальный. Документ живёт в git рядом с кодом — тогда его можно ревьюить как pull request, видеть историю и легко найти.
Кто пишет и когда это вообще нужно
Два вопроса, которые возникают раньше структуры и на которые в статье пока нет ответа.
Когда design doc не нужен. Новое поле, новый эндпоинт по образцу соседних, правка бизнес-правила, замена библиотеки на совместимую — обычный пул-реквест, и никакого документа. Требовать документ на всё — верный способ добиться того, что его перестанут писать вообще.
Порог тот же, что у записи решений, и он из двух условий: дорого отменить (появляется новый компонент или хранилище, меняется модель данных необратимо, делится или объединяется сервис) или затрагивает больше одной команды (меняется публичный контракт, появляется общая зависимость, кто-то начинает владеть чужими данными). Выполнено хотя бы одно — документ; не выполнено ни одного — не документ.
Промежуточный вариант, который стоит знать: одна страница вместо шести. Контекст, решение, альтернативы, отказы, открытые вопросы — по абзацу. Годится, когда изменение существенное, но не большое, и это самый частый режим в работающей команде.
Кто пишет. Тот, кто будет это делать, — а не тот, кто лучше пишет и не «архитектор за всех». Причина простая: документ пишется, чтобы автор сам нашёл дыры до кода, и этот эффект теряется, если текст приносят готовым. Помощь допустима и полезна: архитектор помогает со структурой и приносит контекст из соседних систем, но руку на клавиатуре держит автор изменения.
Кто владелец решения. Это отдельная роль, и её стоит назвать в шапке документа рядом с автором — потому что ревьюеров бывает пять, и без владельца пять мнений превращаются в бесконечное согласование. Правило простое: ревьюеры советуют, владелец решает и отвечает за последствия. Обычно владелец — тот, кто будет жить с этим кодом: техлид команды, владеющей сервисом. Архитектор владельцем бывает только у решений уровня платформы, затрагивающих несколько команд.
Что делать с несогласием, которое не удалось снять: оно записывается в документ — кто не согласен, с чем и какой вариант предлагал. Это не бюрократия, а страховка обеих сторон: через год видно, что возражение было и почему его отклонили; и это единственный честный способ закрыть обсуждение, не убедив всех.
Асинхронное ревью без встречи
Совет «встреча за два дня до» предполагает, что встреча будет. В распределённой команде с разными часовыми поясами её часто нет, и это нормальный режим, а не деградация — но правила у него свои.
Документ идёт как запрос на изменение. Не ссылка в чате, а обычный пул-реквест с файлом: комментарии привязаны к строкам, видно, что автор ответил, а что нет, и есть явное одобрение. Это и есть главное преимущество асинхронного ревью перед встречей: след разговора остаётся привязанным к тексту, а не растворяется в записи созвона.
Срок вместо встречи. У асинхронного ревью должна быть дата, иначе оно длится вечно: «комментарии до четверга, решение в пятницу». Молчание до срока считается согласием — и это правило объявляют заранее, иначе «все согласны» снова окажется непрочитанным документом.
Явное подтверждение от ключевых ревьюеров. От двух-трёх человек (эксплуатация и потребители API) нужен не молчаливый пропуск, а отметка «прочитал, замечаний нет». Их просят лично, и это не формальность: именно они находят то, что автор не мог увидеть.
Когда встреча всё-таки нужна. Три признака: больше двух развилок, по которым ревьюеры не сходятся; спор идёт третий круг в комментариях; или решение затрагивает команды, которые друг о друге не знают. Тогда встреча — короткая и только по спорным местам, со списком развилок в повестке. Всё остальное остаётся письменным.
Чего не хватает без встречи и что приходится добавлять специально: у письменного ревью нет момента, когда все одновременно смотрят на схему и находят несостыковку. Это частично лечится тем, что автор сам прогоняет сценарии по схеме в тексте («запрос приходит сюда, дальше очередь…») — тогда ревьюер идёт по описанному пути и спотыкается там же, где споткнулся бы вслух.
Диаграммы: модель C4
Главная ошибка при рисовании архитектурных схем — один рисунок обо всём: контейнеры, классы и сетевые зоны в одной каше. Разобраться невозможно.
Модель C4 решает это уровнями. Каждый уровень — своя диаграмма с чёткой аудиторией:
Context — самый верхний уровень. Показывает систему и её соседей: кто пользователь, какие внешние системы задействованы. Понятен всем, включая нетехнических участников.
Container — рабочая лошадка дизайн-документа; вместе с Context эти два уровня в документе обязательны. Показывает сервисы, базы данных, очереди и связи между ними. Для читателя важно понять: из чего состоит система и как части общаются.
Component — внутренности одного контейнера. Рисуется только для «горячих точек» — мест, где есть архитектурная сложность. Нет смысла делать это для каждого сервиса.
Code — не рисуется вручную. Либо генерируется из кода, либо не нужен вовсе.
Подробный разбор уровней, а заодно двух дополнительных диаграмм модели — в отдельной статье про C4.
Практические правила для любого уровня:
- Каждую стрелку подписать: что передаётся и как (синхронно/асинхронно).
- Каждый элемент называть терминами из домена — не «Backend» и «Service 2», а «Сервис уведомлений» и «Очередь доставки».
- Хранить диаграммы в текстовом формате, который лежит в git рядом с документом (для C4 для этого есть Structurizr) — иначе они устареют к третьему ревью и никто не будет знать, актуальны ли они.
ADR: фиксируем важные развилки
В процессе проектирования возникают развилки — моменты, когда можно пойти двумя разными путями. Например: «Kafka или SQS?», «Лента в PostgreSQL или в MongoDB?».
Design doc описывает итоговое решение целиком. Но каждую существенную развилку имеет смысл фиксировать отдельно — в формате ADR (Architecture Decision Record).
Почему отдельно? Дизайн-документ читают один раз при ревью. ADR находят годами при вопросе «а почему здесь именно так?» — через полгода, при вводе в работу нового инженера, при аудите. Дизайн-документ ссылается на ADR-ы; ADR-ы переживают сам документ.
Подробнее о формате — в статье ADR.
Как проводить ревью дизайна
Ревью дизайна — это не формальность. Это поиск дыр до того, как написан код. Найденная проблема на ревью — экономия недель работы.
Рабочий процесс:
1. Документ — заранее. Минимум за два дня до встречи, чтобы участники успели прочитать и написать комментарии. Встреча, на которой документ видят впервые — это чтение вслух, а не ревью.
2. Встреча — по спорным местам. Не пересказ документа, а разбор собранных комментариев и открытых вопросов. 60–90 минут — разумный максимум.
3. Правильные ревьюеры. Хватит 2–4 человек. Обязательно должны быть: кто-то от эксплуатации этой системы и кто-то от потребителей её API. Ревью только архитекторами пропускает ровно те проблемы, которые всплывут в продакшене и у клиентов.
4. Итог — письменно. Решение (принято / принято с правками / переработать), список обязательных изменений, новые ADR. Без письменного итога через месяц никто не помнит, что решили.
Пять отметок ревью на одной линии времени: документ уходит за два дня, встреча берёт только спорные места, а письменный итог и записи решений появляются в тот же день.
Полезные вопросы для ревьюера:
- Какие числа? Откуда они? Что происходит на пике?
- Что видит пользователь при отказе компонента X?
- Зачем этот блок — какое требование его позвало?
- Где идемпотентность при ретраях?
- Как мигрируем или откатываемся?
- Что входит в первую версию, что отложено?
Вопрос, на который у автора нет ответа — нормальный результат ревью. Он уходит в открытые вопросы, а не закрывается уверенным тоном.
Типичные ошибки при защите дизайна
Дизайн как презентация. Красивые слайды вместо документа: нечего комментировать построчно, нечего вернуть через год. Слайды показывают, документ исследуют.
Автор защищается вместо того, чтобы слушать. Вопросы воспринимаются как атака, а не как помощь. Ревью — поиск дыр до продакшена; найденная дыра — выигрыш автора, не его поражение.
Ревью после начала разработки. Когда написана половина кода, ревью не способно ничего изменить — оно легализует сделанное. Дизайн ревьюится до спринта.
Бесконечное согласование. Пять раундов правок у пяти участников. Решается жёстким сроком и явным владельцем решения: ревьюеры советуют, решает один человек — и записывает это.
«Все согласны» молчанием. Отсутствие комментариев — не согласие, а непрочитанный документ. Просить явный ответ от каждого ревьюера.
Design doc, ADR, спецификация и README — кто за что
Четыре жанра постоянно путают, и от путаницы документы дублируются, устаревают и перестают читаться. Разница между ними — не в объёме, а в отношении ко времени.
| Жанр | Отвечает на вопрос | Когда пишется | Живёт |
|---|---|---|---|
| Design doc | Что строим и почему именно так | До реализации | До запуска, потом архив |
| ADR | Почему выбрали это, а не то | В момент развилки | Вечно, неизменным |
| Спецификация | Как система устроена сейчас | Вместе с кодом | Пока живёт система |
| README | Как это запустить и где что лежит | Вместе с кодом | Пока живёт код |
Практические границы между ними:
Design doc и ADR. Документ описывает целое, запись решения — одну развилку. Правило: если развилку через год будут вспоминать («а почему у нас Kafka?»), она заслуживает отдельной записи, потому что документ к тому времени будет в архиве, а запись останется.
Design doc и спецификация. Это документы разного времени: один про «что собираемся сделать», другая про «как есть». Самая частая ошибка — продолжать править design doc после запуска, превращая его в описание системы. Так получается документ, в котором смешаны замысел и реальность, и по нему нельзя ни узнать, как работает система (устарел), ни понять, что задумывали (переписан).
Спецификация и README. Спецификация — про предметную область и поведение (сущности, операции, правила, события); README — про механику работы с кодом (как собрать, как запустить, куда смотреть, кому писать). Их путают, и получается README на тридцать экранов, где бизнес-правила соседствуют с командами запуска.
Что происходит с документом после запуска
Ответ, который надо дать прямо: design doc становится историческим артефактом, и это нормально. Он описывает решение на момент принятия, а не систему сегодня.
Что с ним делают:
Помечают состоявшимся и не правят. Статус меняется на «реализовано» с датой, и дальше документ живёт как запись замысла. Не «обновляем по мере изменений»: попытка держать его актуальным превращает его в плохую документацию системы и одновременно уничтожает как запись замысла.
Расхождения с реальностью фиксируют — коротко. Если в ходе реализации решение изменилось, в документ дописывают абзац «что изменилось по ходу и почему» — это самое ценное чтение для следующего похожего дизайна. Например: «отказались от отдельной темы для кампаний, оказалось достаточно приоритета» — одна строка, которая экономит будущий спор.
Развилки, которые переживут документ, выносят в записи решений. Это и есть ответ на вопрос «что остаётся»: после запуска от документа в активном обороте остаются ссылки на решения и спецификация системы, а сам он уходит в архив.
Живой документацией становится спецификация. Она обновляется вместе с кодом и проходит ревью в том же изменении. Если её нет, то через полгода единственный источник правды о системе — код, а design doc в архиве будет уверенно врать тому, кто откроет его как описание.
И маленькое правило, которое спасает от самого частого недоразумения: в шапке документа стоит дата и статус. Читатель, открывший файл через год, должен за секунду понять, что перед ним — план, который уже реализован (и, возможно, иначе), а не описание текущей системы.
Глубже: безопасность в дизайне: четыре вопроса ревьюерарасширенное
Ни в структуре документа, ни в чек-листе ревьюера выше нет безопасности, а на настоящем ревью это первый блок вопросов, и ответы на них меняют схему. Раздел «Безопасность» в design doc отвечает на четыре.
Кто входит и где это проверяется. На границе стоит шлюз, который проверяет токен, а сервисы внутри ходят по mTLS или проверяют подпись каждый; какие вызовы идут от имени пользователя, а какие от имени сервиса, и через какой механизм это различается, о чём статьи про паттерны аутентификации.
Кому что можно. Роли для операций и владение для объектов: кто может отменить заказ, кто видит чужой, что делает администратор и как это попадает в журнал. Ответ «проверяем права в контроллере» недостаточен, ответ «чужой объект отвечает 404, админ через отдельную команду с журналом» достаточен.
Какие данные и куда текут. Список персональных и чувствительных полей, где они хранятся, шифруются ли, сколько живут, в какие внешние системы и страны уходят, включая логи, аналитику и резервные копии. Здесь всплывают требования локализации и минимизации, и лучше в дизайне, чем при проверке регулятора.
Что фиксируется и как узнаем о взломе. Журнал административных действий, аудит доступа к чувствительным данным, сигналы на аномалии (всплеск отказов доступа, массовое чтение), и что делать при утечке ключа, о чём статья про действия при утечке.
Лёгкая модель угроз занимает пятнадцать минут: по каждому компоненту схемы спросить, что будет, если его подменят, подслушают, перегрузят или в него войдут с чужими правами; результат это три-пять рисков с ответом в дизайне. Ревьюер, не найдя раздела, спрашивает эти четыре вопроса вслух, и ответ «потом добавим» это красный флаг того же уровня, что и отсутствие раздела про отказы.
Глубже: как мы узнаем, что оно работает: SLI, SLO и бюджет ошибокрасширенное
Раздел «как узнаем, что работает» в документе обычно пуст или содержит «настроим мониторинг». Его содержание выводится из требований в три шага и определяет, что вообще будет измеряться после выката.
Из требования в показатель. Нефункциональное требование «оформление заказа быстрое и надёжное» превращают в измеримый показатель, SLI: доля запросов на оформление, завершившихся успешно быстрее двух секунд, считая на балансировщике, за скользящее окно в 28 дней. В формулировке есть что считаем, где, каким окном, и её можно записать запросом к метрикам.
Цель. SLO это порог для показателя: 99,9 % таких запросов. Число берут не с потолка: оно ниже, чем SLA, обещанное клиентам, если оно есть, и выше, чем то, что даёт цепочка компонентов по их обязательствам, о чём статья про SLA в разделе облаков. Цели ставят на два-три показателя, а не на двадцать, и для каждого пишут, что происходит при нарушении.
Бюджет ошибок. 99,9 % за 28 дней это 40 минут неуспеха; это бюджет, который тратят на инциденты и на выкаты. Пока он есть, команда выкатывает, экспериментирует, проводит учения; когда он сгорел, до конца окна только исправления надёжности. Тревога ставится не на факт ошибки, а на скорость сгорания бюджета: сгорает за час, будят ночью, сгорает за неделю, задача на утро, о чём статья про SLO и оповещения в разделе наблюдаемости.
В документ попадает таблица: показатель, как считается, цель, что смотрим на панели, какая тревога и кому. Ревьюер проверяет, что каждое нефункциональное требование из начала документа имеет строку в этой таблице, а каждое решение про отказы отвечает на вопрос «как это отразится на показателе». Без таблицы «работает» узнают от пользователей.
Коротко
- Design doc — 3–6 страниц: контекст, требования, оценки, дизайн, отказы, альтернативы, ADR, план, открытые вопросы. Секции «Альтернативы», «Отказы» и «Открытые вопросы» делают документ честным инженерным артефактом.
- Модель C4 делит диаграммы на уровни: Context (для всех), Container (главная для дизайн-документа), Component (только горячие точки). Диаграммы текстом в git рядом с документом — иначе они устаревают и никто не знает, актуальны ли они. ADR фиксирует каждую важную развилку отдельно — их находят годами, design doc читают один раз. Документ отправляется минимум за два дня; встреча — по спорным местам, не пересказ.
- Ревью — поиск дыр до написания кода, не формальность после. Итог ревью всегда фиксируется письменно.
- Раздел «Безопасность» отвечает на четыре вопроса: кто входит и где проверяется, кому что можно, какие данные куда текут, что фиксируется; лёгкая модель угроз по компонентам за пятнадцать минут.
- «Как узнаем, что работает» это таблица: показатель из требования с формулой и окном, цель ниже SLA и выше цепочки компонентов, бюджет ошибок в минутах и тревога на скорость его сгорания.
- В заполненном разделе у каждой альтернативы есть суть одним предложением, причина отказа с числом или фактом и строка «при каких условиях вернёмся»; та же дисциплина в требованиях, отказах и открытых вопросах.
- Документ нужен, когда решение дорого отменить или затрагивает больше одной команды; пишет его автор изменения, а у решения есть владелец — ревьюеры советуют, решает один и отвечает за последствия.
- Асинхронное ревью — полноценный режим: документ как запрос на изменение, объявленный срок, явное подтверждение от эксплуатации и потребителей, встреча только по развилкам, где не сошлись.
- Четыре жанра различает отношение ко времени: design doc — замысел до реализации, запись решения — развилка навсегда, спецификация — как есть сейчас, README — как запустить.
- После запуска документ помечают состоявшимся и не правят, дописав абзац «что изменилось по ходу»; живой документацией становится спецификация, а в шапке всегда дата и статус.
Что почитать дальше
- Метод системного дизайна — содержание, которое этот документ оформляет.
- Модель C4 — уровни диаграмм подробно.
- ADR — формат записи важных решений.
- Что делает архитектор — чья работа довести дизайн до решения.