Читатель и решение: зачем существует этот документ
Инженер садится писать RFC. Через два часа готово восемь страниц: контекст, история вопроса, сравнение пяти библиотек, таблица бенчмарков, диаграмма компонентов. Документ уходит в канал: три реакции-эмодзи, ноль комментариев, решения нет. Через месяц команда делает ровно то, что предлагалось, — но по итогам получасового разговора у доски, а не по документу.
Это не история про плохой текст: предложения грамотные, факты верные, диаграмма аккуратная. Это история про документ без адресата и без запроса на решение: восемь страниц описывали мир, но никого ни к чему не приглашали.
Технический документ существует ради решения, которое должен принять конкретный читатель. Если вы не можете назвать читателя и назвать решение — документ не нужен, и его не прочтут.
Всё остальное в треке — структура, ясность, жанры, диаграммы, ревью — обслуживает эту связку. Карта трека в обзоре; здесь фундамент, на котором стоят ADR, RFC, постмортем, README, документация API.
Документ как звено в цепи, а не как результат
Перестаньте думать о документе как о продукте («я написал документацию») и начните думать о нём как о звене передачи: у автора в голове модель, читателю нужно принять решение, документ — единственный канал между ними, работающий без вашего присутствия.
что я знаю"] --> B["Документ:
что записано"] B --> C["Читатель:
что понято"] C --> D{"Решение"} D -->|"принято"| E["Действие
в системе"] D -->|"нужны детали"| F["Возврат с вопросами"] D -->|"не дочитал"| G["Решили
без вашего документа"] F --> B E --> H["Эффект,
ради которого писалось"] G --> H
Обратите внимание на ветку G: решение будет принято в любом случае, вопрос лишь в том,
поучаствует ли в нём ваш текст. Документ конкурирует не с идеальной документацией, а с чатом,
встречей и «сделаем как в прошлый раз», поэтому он должен быть не «полным», а достаточным
и дешевле альтернативы. Работает он в коротком окне, когда читатель открыл его
с конкретным вопросом: не ответили там — проиграли, даже если ответ был на пятой странице.
Три вопроса до первой строки
- Кто прочтёт? Не «команда», а роль в конкретной ситуации: «Аня, владелец
catalog-service», «дежурный в три часа ночи», «интегратор, не видевший наш код». - Какое решение он примет? «Одобрить перенос кэша», «выбрать вариант A или B», «понять, наш ли это сервис, и уйти, если не наш», «сделать частичный возврат с первого раза».
- Что будет, если он не прочтёт? «Ничего» — не пишите. «Спросит меня в личке» — возможно, дешевле ответить в личке. «Решит вслепую, потеряем неделю» — пишите.
Половина «сложных» документов рассыпается на первом же вопросе: автор пишет для себя, чтобы разобраться. Задача законная, но это черновик мышления: публиковать его нельзя, пока он не переписан под адресата.
Читателей несколько, главный — один
«Пишите для читателя» звучит как совет, пока не выясняется, что типов читателей минимум три и потребности противоположные: решающему — вывод и риски, исполнителю — шаги и параметры, будущему археологу — причины и дата.
Разложим их по двум осям: сколько у читателя контекста и насколько он влияет на решение.
- Верхняя половина решает судьбу документа: вступление пишется под того, кто принимает решение, а не под того, кому интереснее всего читать.
- Верх слева — опасная зона. Человек решает, контекста нет: ему нужны вывод, цена вопроса, риски, срок; технические детали он пролистает, и это нормально.
- Правый нижний угол — ваш будущий двойник. Через год вы сами будете читать этот текст, не помня ничего: «очевидное и не требующее записи» станет ровно тем, ради чего его откроют.
- Прохожим хватит абзаца: заголовок и
summaryпозволяют им закрыть вкладку без вины.
Если групп больше одной, не смешивайте их в одном потоке текста: слоистая структура — в главе «Структура», а здесь важен приоритет — главный адресат ровно один.
Каталог решений: что вообще решают по документам
«Решение» — это не только «да/нет»; от типа решения зависят жанр, объём и то, чем документ заканчивается.
| Тип решения | Читатель | Жанр | Признак провала |
|---|---|---|---|
| Одобрить или отклонить подход | тимлид, архитектор | RFC, дизайн-док | обсуждение расползлось, решения нет неделями |
| Понять, почему уже сделано так | инженер через год | ADR | «давайте перепишем» без знания старых причин |
| Начать работать с системой | новичок, интегратор | README | вопросы в личку в первый же день |
| Сделать шаг правильно | дежурный, исполнитель | руководство, runbook | шаги не воспроизводятся, инструкция врёт |
| Вызвать API и обработать ответ | внешний разработчик | справочник API | тикеты в поддержку об «очевидном» |
| Изменить систему после сбоя | команда и смежники | постмортем | список действий без владельцев и сроков |
| Согласиться, что делать не надо | заказчик, менеджер | короткая записка | тема всплывает каждый квартал заново |
Последняя строка недооценена: документ, аргументированно закрывающий идею, экономит месяцы — он тоже написан под решение «отказаться и не возвращаться». А вот строки «зафиксировать знания» в таблице нет: эта формулировка — главный источник мёртвых страниц. Знания фиксируются как побочный эффект документов под решения и живут потому, что по ним решают.
Шапка-контракт: делаем адресата видимым
Самый дешёвый инструмент главы — явная шапка: автора она заставляет ответить на три вопроса, читателю за пять секунд показывает, его ли это текст.
---
title: "RFC-014. Перенос кэша каталога в Redis"
status: proposed # proposed | accepted | rejected | superseded
reader: "владелец catalog-service, тимлид платформы"
decision: "переносим ли кэш каталога из процесса в Redis"
deadline: 2026-03-12 # нет возражений к дате — считаем принятым
owner: "@a.petrov"
review_by: 2026-09-01 # когда перечитать: жив документ или в архив
supersedes: "RFC-006"
---
readerиdecision— тот самый контракт: не заполняются без слов «все» и «ознакомиться» — документ не готов.deadlineс правилом умолчания — единственный надёжный способ вытащить решение из молчащих ревьюеров; так устроены Rust RFC (https://github.com/rust-lang/rfcs) и RFD в Oxide (https://rfd.shared.oxide.computer/rfd/0001).review_by— срок жизни (см. раздел про устаревание),statusпревращает текст в запись решения, а не в вечное обсуждение.
Восемь строк снимают половину вопросов, ради которых обычно созывают встречу.
Разбор: один и тот же абзац до и после
Теория проверяется на абзацах. Ниже три пары «плохо / переписано»: плохие версии не выдуманы, это усреднённые тексты из любой компании. Английский пример разбираем по-русски.
Тот же приём на README: вместо «This service is a part of the platform. It was created
in 2021 and is written in Go 1.19… For more information contact the team» — «Списывает
и возвращает деньги по запросам checkout, единственный сервис, который пишет в таблицу
payments. Вам сюда, если: двойное списание · подключение провайдера · нужен статус
платежа. Вам не сюда: счета — это billing-service». Первый отвечает на незаданный
вопрос «из чего сделано», второй — на решение «остаться или уйти», ради которого README
и открывают.
Пример 1. Вступление RFC
Плохо:
В рамках работы над улучшением производительности системы было проведено исследование существующих подходов к кэшированию. Были рассмотрены различные варианты, включая in-process кэш, Redis, Memcached и CDN-кэширование. Ниже приводится сравнительный анализ и описание текущей архитектуры кэширования в системе.
Формально вступление, фактически оглавление. Тимлид, который должен сказать «делаем» или «не делаем», не знает: что предлагают, сколько стоит, чем он рискует, к какому сроку ждут ответа. Пассив («было проведено», «были рассмотрены») прячет субъекта — непонятно, с кем спорить. Про пассив и номинализации — глава «Ясность».
Переписано:
Прошу решения до 12 марта: переносим кэш каталога из процесса в Redis. Рекомендую перенести.
Сейчас каждый экземпляр сервиса держит свою копию каталога (около 1.2 ГБ), после деплоя первые 3–5 минут мы отдаём 30% ошибок из-за холодного кэша и не масштабируемся дальше 12 подов. Redis убирает холодный старт и снимает потолок ценой одного сетевого хопа (
p99растёт с 8 до 11 мс) и нового компонента в зоне отказа.Если решения не будет до 12 марта, мы оставляем текущую схему и снимаем задачу масштабирования каталога с плана на квартал.
Первая строка — не тема, а запрос: решение, срок, рекомендация. Дальше цена в обе стороны. Последний абзац — цена бездействия; он превращает молчание в осознанный выбор и ускоряет ответ сильнее, чем три напоминания в чате.
Пример 2. Абзац постмортема
Плохо:
Инцидент произошёл из-за того, что разработчик выкатил конфигурацию без ревью. Разработчику указано на недопустимость подобных действий. Команде рекомендуется быть внимательнее при работе с продакшн-конфигурацией.
Читатели постмортема — команда и смежники, их решение — что менять в системе. Абзац не поддерживает ни одного изменения: у «быть внимательнее» нет исполнителя, срока и способа проверить. Зато он назначает виноватого, и следующий человек расскажет меньше. Механика безобвинительного разбора — в SRE-треке и главе «Постмортем».
Переписано:
Конфигурация попала в прод без ревью, потому что пайплайн
deploy-configне проверяет наличие апрува: он скопирован из шаблона 2022 года, где такой проверки ещё не было. На ревью-борде изменение выглядело как обычный пуш в ветку. Мы шесть раз за год деплоили конфигурацию этим путём — просто раньше значения были безопасными.Предлагаем принять решение: добавить в
deploy-configобязательную проверку апрува (2 дня, @petrov, до 20 марта) и вынести оставшиеся четыре пайплайна из шаблона 2022 года в общий шаблон (5 дней, @sidorova, до конца квартала).
Причина сместилась с человека на механизм — появилось то, что можно починить. «Шесть раз за год» показывает, что дело не в единичной ошибке: это аргумент, ради которого выделяют время. У действий есть владелец, оценка и срок — по ним можно решить «берём в спринт или нет».
Пример 3. Справочник API
Плохо:
POST /v1/refunds
Creates a refund.
Parameters:
payment_id (string, required) - the payment
amount (integer, optional) - the amount
Читатель — внешний интегратор без доступа к вашему коду. Его решения: как сделать частичный
возврат, что будет при повторе после таймаута, как отличить временную ошибку от постоянной.
Ответов нет: неизвестны единицы amount (рубли? копейки?), поведение по умолчанию,
идемпотентность, список ошибок. the amount — самый частый вид пустой документации:
перевод имени поля на английский.
Переписано:
POST /v1/refunds — возврат средств по платежу
Идемпотентен по заголовку Idempotency-Key: повтор с тем же ключом в течение 24 часов
вернёт тот же объект и НЕ создаст второй возврат. Без заголовка повтор после таймаута
создаст второй возврат — всегда передавайте ключ.
payment_id string, обяз. — платёж в статусе succeeded
amount integer, опц. — сумма в минорных единицах валюты платежа (1099 = 10.99 USD).
Не указана — полный возврат остатка;
больше остатка → 400 refund_amount_too_large.
Ошибки: 409 payment_not_settled — платёж ещё не проведён, повторите через 15 минут;
402 insufficient_funds — не хватает средств у продавца, нужно ручное решение.
Каждая строка отвечает на вопрос, который возникнет при интеграции или на инциденте: единицы с примером, поведение при повторе, поведение по умолчанию, что делать при ошибке. Режимы справочника и контракт — в главе «Документация API».
Процедура для своих абзацев: назовите читателя (не можете — переписать или удалить), назовите решение (никакого — это фон, в приложение), проверьте, хватает ли данных для решения (нет — добавьте цену, риск, единицы, срок), вынесите вывод в первое предложение.
Цена чтения: почему «полный» документ проигрывает
Внутренний RFC на восемь страниц читают по диагонали за четыре минуты, и это оптимистичная
оценка. Бюджет читателя жёсткий: пять секунд на «мой ли это документ» (заголовок, summary,
шапка), тридцать секунд на вывод, пара минут на проверку ключевого аргумента — и только потом
детали. Документ конкурирует сам с собой: каждый абзац, не работающий на решение,
отодвигает вниз тот, который работает.
Отсюда парадоксальное правило: документ, из которого выкинули треть, чаще меняет решения, чем полный — выкидывают обычно то, что не поддерживало ни одного решения.
Как документ доходит до решения
Между «опубликовал» и «решение принято» лежит процесс, и его стоит проектировать как код.
а ради ответа «почему так» F->>A: Нашёл ADR — вопрос закрыт без встречи
Три детали, которые чаще всего пропускают. Черновик отдельным адресатам: один-два
ревьюера до широкой публикации ловят 80% возражений, пока переписать вступление ещё дёшево
(как просить правки — глава «Ревью текста»). Явный запрос
при отправке: ссылка без запроса читается как «к сведению», а «нужно решение до даты,
иначе делаем X» — не давление, а информация. Фиксация результата в документе: решение
из треда чата исчезает вместе с историей чата, а status: accepted плюс дата и ссылка
на тикет делают текст источником истины для будущего читателя.
Почему документация устаревает и что с этим делают структурно
«Обновляйте документацию» — призыв того же класса, что «пишите без багов». Устаревание не следствие лени, а свойство конструкции: документ и система живут в разных местах и меняются по разным поводам, и чем дальше документ от источника истины, тем меньше шансов, что при изменении системы кто-то дотянется до текста.
Главное наблюдение: в Drift первыми и незаметнее всего сползают документы без адресата.
Есть читатель, регулярно принимающий решения по тексту, — расхождение находится быстро,
он приходит и жалуется. Читателя нет — устаревание никого не будит, страница тихо врёт
годами. Устаревание симптом, а не причина: сначала документ теряет адресата, потом
актуальность. Что работает вместо призывов:
- Близость к коду. Документ лежит в том же репозитории и меняется в том же pull request: расхождение видит ревьюер кода, и обновление становится частью изменения, а не отдельной задачей, которая никогда не приоритетна — docs as code (https://www.writethedocs.org/guide/docs-as-code/, оформление изменений — трек git).
- Генерация из источника истины. Всё, что выводится из кода, схемы или конфигурации,
надо выводить, а не переписывать руками: справочник из OpenAPI, описание CLI из
--help, метрики из кода экспортёра, схема БД из миграций. Рукописное дублирование — плановыйDrift. - Исполняемые примеры выполняются в CI: неверный пример роняет сборку, как неверный код:
from decimal import Decimal
EXPONENT = {"USD": 2, "EUR": 2, "RUB": 2, "JPY": 0} # у иены минорных единиц нет
def to_minor_units(amount: str, currency: str) -> int:
"""Переводит сумму в минорные единицы валюты.
Примеры ниже — документация и тест одновременно: их выполняет
`python -m doctest payments.py` в CI, поэтому они не устареют молча.
>>> to_minor_units("10.99", "USD")
1099
>>> to_minor_units("1000", "JPY")
1000
"""
return int(Decimal(amount).scaleb(EXPONENT[currency]))
- Владелец и срок жизни.
CODEOWNERSнаdocs/даёт ответ на вопрос «кто это писал», аreview_byплюс еженедельная проверка в CI превращает просроченное в задачу владельцу (ответ «в архив» — нормальный исход). - Меньше страниц. Двадцать страниц команда поддерживать не будет, две — будет; удаление устаревшего такая же работа, как написание.
- Записи решений вместо описаний состояния. ADR не устаревает по построению: он датирован. «Мы выбрали Kafka в марте 2026 по таким-то причинам» останется правдой навсегда, а «мы используем Kafka» станет ложью в день миграции — поэтому что можно записать как решение, записывайте как решение (ADR, архитектурные решения).
Метрики документации и процессы поддержки — в главе «Почему документация устаревает»; здесь важен корень: документ живёт столько, сколько по нему принимают решения.
Документы, которые пишут ради процесса
Честная часть, которую обычно опускают: часть документов в вашей организации пишется не для читателя, а потому что так требует шаблон, регламент или привычка — их адресат процесс. Делать вид, что таких документов нет, плохая стратегия: вы потратите на них столько же сил, сколько на настоящие, и разочаруетесь в письме вообще.
Как распознать:
- Читателя нельзя назвать без слова «все»: «ну, команда», «положено».
- Документ создаётся после решения, потому что «нужен артефакт»: изменить он ничего уже не может.
- Шаблон обязателен и не обсуждается, половина полей заполняется копипастом.
- Ревью — это подпись: апрув через восемь минут после отправки тридцати страниц.
- Нулевая телеметрия: четыре просмотра, три из них ваши (Confluence, Notion и GitBook показывают эту цифру — посмотрите, она отрезвляет).
- После публикации правок нет. Живой документ правят, процессный не меняется никогда.
- Вопросы задают в чате, хотя ответ есть в документе: канал знаний идёт мимо текста.
Быстрая проверка — тест на удаление: если завтра документ исчезнет, кто заметит и через какое время? «Никто и никогда» — вы нашли процессный артефакт. Второй — тест на решение: попросите последнего ревьюера назвать, что он решил, прочитав текст; пауза говорит всё.
Что делать (не саботировать процесс, особенно на новом месте — «Первые 90 дней»):
- Найти настоящего адресата. Часто он есть, просто это не инженер: аудитор, сертифицирующий орган, юрист, клиент с требованиями к поставщику. Тогда документ не бесполезен — у него другой читатель и другое решение («пройти аудит», «подписать контракт»), и писать его надо под этого читателя.
- Разделить слои. Рабочий документ (для решения) и процессный артефакт (для проверки) не должны быть одним текстом: угодить обоим — значит не сработать ни для кого; пусть артефакт генерируется из рабочего или ссылается на него.
- Автоматизировать. Отчёты о покрытии, списки изменений, матрицы прослеживаемости собираются из тикетов и кода скриптом: полдня работы экономят десятки часов в год.
- Сократить шаблон. Аргумент не «шаблон плохой», а «эти четыре поля никто не заполняет осмысленно, уберём и посмотрим, спросит ли кто-нибудь». Обычно не спрашивают.
- Считать честное время. «6 часов на релиз, 12 релизов в квартал — три недели инженерного времени в год» — единственный язык, на котором двигается такой разговор (см. «Работу вверх»). И храните такие артефакты отдельно от живой документации, иначе доверие к рабочим текстам упадёт до уровня процессных.
И отдельно: не всякий документ, который скучно писать, — процессный. Разница в наличии читателя и решения, а не в вашем удовольствии: постмортем скучно писать почти всем, но у него есть и адресат, и решение, и цена ошибки.
Типичные ошибки
- «Документация для команды». Команда не адресат; адресат — роль в конкретной ситуации.
- Вывод в конце. Структура «контекст → анализ → вывод» удобна автору и враждебна читателю: до вывода дочитывают единицы. См. «Структура».
- Документ вместо разговора. Если решение задевает интересы, текст — опора для разговора, а не замена ему: «Трудные разговоры», «Обратная связь».
- Проклятие знания. Автор не помнит состояние «я этого не знал» и пропускает шаг, без которого читатель застревает. Лечится внешним читателем: дайте текст тому, кто не в контексте, и смотрите, где он остановился.
- Один документ на все аудитории: для каждого читателя он наполовину лишний.
- Решение без срока уходит в вечное «обсудим», а документу без владельца перестают верить раньше, чем он реально устареет.
Практика
- Шапка-контракт. Возьмите свой документ за последние три месяца и допишите
reader,decision,deadline,owner,review_by. Еслиdecisionне заполняется без слов «ознакомить» и «зафиксировать» — этот документ стоило написать иначе. - Тест на удаление. Выпишите пять документов команды и честно ответьте, кто заметит их пропажу и через какое время; сверьтесь с телеметрией просмотров.
- Переписанный абзац. Перепишите первый абзац последнего дизайн-дока так, чтобы первое предложение содержало решение и адресата, и покажите обе версии коллеге, не говоря, какая новая: «какое решение от тебя тут ждут?»
Отдельная привычка: начинать документ со строки «читателю X нужно решить Y к сроку Z» — её потом можно удалить, но текст, написанный после неё, получается другим.
Источники
- Google Technical Writing Courses: https://developers.google.com/tech-writing
- Daniele Procida, Diátaxis — четыре типа документации, у каждого свой читатель: https://diataxis.fr/
- Write the Docs Guide, в том числе docs as code: https://www.writethedocs.org/guide/
- Michael Nygard, «Documenting Architecture Decisions», исходная заметка про ADR: https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions
- Oxide Computer, RFD 1: https://rfd.shared.oxide.computer/rfd/0001
- Google SRE Book, «Postmortem Culture»: https://sre.google/sre-book/postmortem-culture/
- Steven Pinker, «The Sense of Style» — про проклятие знания; Colin Bryar, Bill Carr, «Working Backwards» — документ как способ принять решение на встрече.
Мини-итог
- Документ существует ради решения конкретного читателя. Нет читателя и решения — нет документа: есть черновик мышления, который не нужно публиковать.
- Читателей несколько, главный один: вступление пишется под того, кто решает. Шапка-контракт
(
reader,decision,deadline,owner,review_by) стоит восемь строк и снимает половину проблем ещё до написания текста. - Читатель тратит секунды: вывод в начале, цена и риски рядом, детали ниже; документ конкурирует с чатом и встречей, а не с идеальной документацией.
- Устаревание — симптом отсутствия адресата; лечится структурно: близость к коду, генерация, исполняемые примеры, владелец, срок жизни, меньше страниц, записи решений.
- Часть документов пишется ради процесса: распознаются тестом на удаление и тестом на решение, лечатся поиском настоящего адресата, разделением слоёв и автоматизацией.
Что дальше
Мы выяснили, для кого и ради чего пишем. Следующий вопрос — как разложить материал внутри документа, чтобы читатель дошёл до нужного места за секунды: инвертированная пирамида, слои детализации, заголовки, по которым ищут, и почему хронологический порядок почти всегда плох.