← назад к разделу

Представьте: команда несколько дней обсуждала архитектуру, разошлась довольная, а через месяц никто не помнит, что именно решили и почему. Новый коллега предлагает те же варианты, которые уже отвергли. В проде всплывает сценарий падения, который никто не рассматривал.

Именно поэтому дизайн нужно записывать и проводить через ревью. Дизайн, который не записан — это мнение одного человека. Ревью делает его общим решением, на которое можно опираться.

Обязательно

Что такое 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. Без письменного итога через месяц никто не помнит, что решили.

за 2 дня документ ревьюерам 2 дня комментарии в тексте встреча 60-90 минут по спорным в тот же день письменный итог после 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 — как запустить.
  • После запуска документ помечают состоявшимся и не правят, дописав абзац «что изменилось по ходу»; живой документацией становится спецификация, а в шапке всегда дата и статус.

Что почитать дальше