Как писать эффективный software design document
Знаешь, что раздражает больше всего? Когда команда месяцами пилит фичу, а потом выясняется, что архитектура была выбрана неправильно. Или когда два человека вроде как договорились, но каждый понял задачу по-своему. Или когда приходит новый разработчик, открывает код и не понимает, почему всё устроено именно так.
Я недавно наткнулся на статью Майкла Линча — он работал в Google и Microsoft, сейчас ведёт блог Refactoring English. И знаешь что? Он написал реальный design doc для своего проекта и выложил его. Не абстрактный пример из учебника, а живую работу. Это натолкнуло меня на мысли о том, как мы вообще подходим к проектированию.
Зачем тратить время на бумажки?
В разработке есть соблазн сразу писать код. Думать некогда, рынок ждёт, менеджер спрашивает. Кажется, что design doc — это бюрократия для больших корпораций, а у нас стартап, своя движуха.
Но вот в чём штука: проектирование — это единственный момент, когда изменить решение стоит дёшево. Поменять архитектуру в голове — бесплатно. Поменять в диаграмме — дёшево. Поменять после написания 200 тысяч строк кода… ну, ты понял.
Design doc решает три проблемы:
- Координация в команде. Ты фиксируешь решения, чтобы потом не было «а, я думал это будет работать иначе».
- Обратная связь до того, как поздно. Коллеги могут указать на проблему в дизайне за один день, а не после месяца разработки.
- Институциональная память. Через полгода ты сам забудешь, почему выбрал конкретное решение. Документ — это time capsule для будущего себя.
Когда это вообще нужно?
Не каждую задачу нужно оформлять в документ. Вот чеклист: стоит ли?
- Несколько человек реализуют дизайн? Да — нужен doc. Нет — можно обойтись.
- Проект займёт больше трёх месяцев? Да — документируйте.
- Решение будет жить в продакшене несколько лет? Да — подумайте дважды.
- Кросс-командное взаимодействие? Да — без вариантов.
- Цели и требования размыты? Да — тем более нужен doc.
- Есть катастрофические риски — безопасность, правовые вопросы? Да — обязательно.
Если на два и более вопросов ответ «да» — документ почти наверняка окупится.
А иногда правильный ответ — «не пишите». Маленький сайд-проект на выходные? Фича, которую можно переписать за день? Скорее всего, можно обойтись без формальностей.
Из чего состоит нормальный design doc
Автор статьи приводит такую структуру. Разберём по порядку:
Заголовок — короткий, запоминающийся, отражающий суть. Не «Проект А», а что-то вроде «RecencyBank» для системы кэширования по давности обращения. Легко произносить, легко гуглить.
Метаданные — скучно, но критично. Автор, дата создания, статус, кто подписал. Если у вас есть система коротких ссылок вроде go/project-name — добавьте.
Цель — одно предложение, понятное любому стейкхолдеру. Не «внедрить Redis», а «ускорить загрузку страниц для пользователей».
Контекст — почему вы вообще этим занимаетесь? Какие проблемы решаете? Были ли предыдущие попытки? Это ответ на вопрос, почему мир должен измениться после этого проекта.
Цели и не-цели — здесь важно именно не-цели. Это то, что читатель мог бы ожидать, но чего в проекте нет. Без этого пункта каждый второй комментарий будет «а почему не сделали X?».
Сценарии использования — конкретные примеры, как система работает в реальности. Не «пользователь видит отчёт», а «Боб создаёт отчёт, нажимает „Поделиться → как URL“, отправляет ссылку Чарли, Чарли открывает и видит копию в режиме только для чтения».
Диаграммы — визуализация архитектуры. Критически важно. Когда ты автор, ты видишь всю картину в голове. Читатель — нет. Нарисуй ему.
Интерфейсы, зависимости, ограничения — технические детали, которые определяют границы решения.
Риски и открытые вопросы — честный взгляд на то, что может пойти не так. И что пока не решено.
Рассмотренные альтернативы — почему вы выбрали именно этот путь, а не другие. Это защита от будущих «а почему не на React?».
СТРУКТУРА DESIGN DOC
────────────────────
┌─────────────────────────────────────────────────────────┐
│ ЦЕЛЬ: Одно предложение о том, ЗАЧЕМ это нужно │
├─────────────────────────────────────────────────────────┤
│ КОНТЕКСТ → ЦЕЛИ → НЕ-ЦЕЛИ │
│ Почему? Что? Чего НЕ? │
├─────────────────────────────────────────────────────────┤
│ СЦЕНАРИИ + ДИАГРАММЫ │
│ Как это работает в реальности │
├─────────────────────────────────────────────────────────┤
│ ДЕТАЛИ: интерфейсы, зависимости, ограничения │
├─────────────────────────────────────────────────────────┤
│ РИСКИ + ОТКРЫТЫЕ ВОПРОСЫ │
│ Что может пойти не так │
├─────────────────────────────────────────────────────────┤
│ АЛЬТЕРНАТИВЫ + ПЛАН ВНЕДРЕНИЯ │
│ Почему не X? Когда и как делаем? │
└─────────────────────────────────────────────────────────┘
▶ Чтение сверху вниз = понимание контекста
Правило «цены ошибки»
Вот самая полезная идея из статьи. Спрашивай себя: какова цена быть неправым?
Не все решения одинаково важны. Одни — навсегда. Выбрал C++ для веб-приложения, а потом понял, что нужен Ruby on Rails? Поздно. Два языка, два стека, ад на поддержку.
Другие — мелочи. Показывать 25 элементов или 100? Кнопка «Загрузить ещё» или бесконечный скролл? Если ошибся — поправишь за пару часов. Не нужно это документировать, спорить об этом на ревью и тем более переживать.
Суть: документируй только те решения, где цена ошибки высока. Сложность архитектуры, выбор хранилища данных, схема аутентификации, дизайн API. Остальное — решай по ситуации и двигайся дальше.
Пример из жизни
Автор приводит кейс: команда запустила веб-приложение. Страницы грузились за 100 мс. Через три года — уже 600 мс. Исследование показало: 95% запросов к базе — это одни и те же 3% строк. Решение — добавить кэширующий слой между веб-сервером и базой.
Теперь вопрос: нужно ли документировать, что кэш хранит данные в оперативной памяти? Да. Какой eviction policy использовать — LRU, LFU, TTL? Да. Будет ли геолокационное кэширование? Нет — это не-цель.
Но нужно ли документировать, какой конкретно Redis string или hash использовать? Скорее всего, нет. Это деталь реализации, которую можно поменять.
ЦЕНА ОШИБКИ: Бинарная шкала
───────────────────────────
ВЫСОКАЯ НИЗКАЯ
│ │
│ • Выбор языка │ • UI-фреймворк
│ • Архитектура БД │ • Цвет кнопок
│ • Схема аутентификации │ • Текст placeholder
│ • Дизайн API │ • Пагинация (25 vs 50)
▼ ▼
┌─────────────────────────────────────────┐
│ ДОКУМЕНТИРОВАТЬ НЕ ДОКУМЕНТИРОВАТЬ │
│ Глубоко продумать Решить и двинуться │
└─────────────────────────────────────────┘
│
└───▶ Золотое правило: если переделать
сложно — продумывай заранее
Практический вывод
Design doc — это не формальность и не бюрократия. Это инструмент мышления. Ты садишься писать, и внезапно обнаруживаешь, что не продумал, как система будет масштабироваться. Или что твоё решение противоречит тому, что делают соседние команды.
Не нужно писать 50-страничные документы на каждую задачу. Но если проект серьёзный, если от него зависит будущее, если над ним работают несколько человек — потрать вечер на документ. Это дешевле, чем месяц переработок.
И ещё: если ты тимлид или продакт, не заставляй команду писать docs ради docs. Спрашивай: «Какова цена ошибки в этом решении?» Если низкая — отпусти. Если высокая — дай людям время и пространство подумать.
Проектируй там, где это важно. Кодируй там, где это возможно.
Ссылки
- How to Write an Effective Software Design Doc — оригинальная статья Майкла Линча (Refactoring English)
Дмитрий Полухин — продуктовый дизайнер. Пишу про разработку, AI и дизайн интерфейсов. Обо мне, контакты и профили.