Техническое письмо Читатель и решение: зачем существует этот документ
0%

Читатель и решение: зачем существует этот документ

Читатель и решение: зачем существует этот документ

Инженер садится писать RFC. Через два часа готово восемь страниц: контекст, история вопроса, сравнение пяти библиотек, таблица бенчмарков, диаграмма компонентов. Документ уходит в канал: три реакции-эмодзи, ноль комментариев, решения нет. Через месяц команда делает ровно то, что предлагалось, — но по итогам получасового разговора у доски, а не по документу.

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

Технический документ существует ради решения, которое должен принять конкретный читатель. Если вы не можете назвать читателя и назвать решение — документ не нужен, и его не прочтут.

Всё остальное в треке — структура, ясность, жанры, диаграммы, ревью — обслуживает эту связку. Карта трека в обзоре; здесь фундамент, на котором стоят ADR, RFC, постмортем, README, документация API.

Документ как звено в цепи, а не как результат

Перестаньте думать о документе как о продукте («я написал документацию») и начните думать о нём как о звене передачи: у автора в голове модель, читателю нужно принять решение, документ — единственный канал между ними, работающий без вашего присутствия.

Обратите внимание на ветку G: решение будет принято в любом случае, вопрос лишь в том, поучаствует ли в нём ваш текст. Документ конкурирует не с идеальной документацией, а с чатом, встречей и «сделаем как в прошлый раз», поэтому он должен быть не «полным», а достаточным и дешевле альтернативы. Работает он в коротком окне, когда читатель открыл его с конкретным вопросом: не ответили там — проиграли, даже если ответ был на пятой странице.

Три вопроса до первой строки

  1. Кто прочтёт? Не «команда», а роль в конкретной ситуации: «Аня, владелец catalog-service», «дежурный в три часа ночи», «интегратор, не видевший наш код».
  2. Какое решение он примет? «Одобрить перенос кэша», «выбрать вариант A или B», «понять, наш ли это сервис, и уйти, если не наш», «сделать частичный возврат с первого раза».
  3. Что будет, если он не прочтёт? «Ничего» — не пишите. «Спросит меня в личке» — возможно, дешевле ответить в личке. «Решит вслепую, потеряем неделю» — пишите.

Половина «сложных» документов рассыпается на первом же вопросе: автор пишет для себя, чтобы разобраться. Задача законная, но это черновик мышления: публиковать его нельзя, пока он не переписан под адресата.

Читателей несколько, главный — один

«Пишите для читателя» звучит как совет, пока не выясняется, что типов читателей минимум три и потребности противоположные: решающему — вывод и риски, исполнителю — шаги и параметры, будущему археологу — причины и дата.

Орбиты читателей вокруг документа: ревью сейчас, работа через месяцы, археология через год

Разложим их по двум осям: сколько у читателя контекста и насколько он влияет на решение.

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

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

Как документ доходит до решения

Между «опубликовал» и «решение принято» лежит процесс, и его стоит проектировать как код.

Три детали, которые чаще всего пропускают. Черновик отдельным адресатам: один-два ревьюера до широкой публикации ловят 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, архитектурные решения).

Метрики документации и процессы поддержки — в главе «Почему документация устаревает»; здесь важен корень: документ живёт столько, сколько по нему принимают решения.

Документы, которые пишут ради процесса

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

Как распознать:

  1. Читателя нельзя назвать без слова «все»: «ну, команда», «положено».
  2. Документ создаётся после решения, потому что «нужен артефакт»: изменить он ничего уже не может.
  3. Шаблон обязателен и не обсуждается, половина полей заполняется копипастом.
  4. Ревью — это подпись: апрув через восемь минут после отправки тридцати страниц.
  5. Нулевая телеметрия: четыре просмотра, три из них ваши (Confluence, Notion и GitBook показывают эту цифру — посмотрите, она отрезвляет).
  6. После публикации правок нет. Живой документ правят, процессный не меняется никогда.
  7. Вопросы задают в чате, хотя ответ есть в документе: канал знаний идёт мимо текста.

Быстрая проверка — тест на удаление: если завтра документ исчезнет, кто заметит и через какое время? «Никто и никогда» — вы нашли процессный артефакт. Второй — тест на решение: попросите последнего ревьюера назвать, что он решил, прочитав текст; пауза говорит всё.

Что делать (не саботировать процесс, особенно на новом месте — «Первые 90 дней»):

  • Найти настоящего адресата. Часто он есть, просто это не инженер: аудитор, сертифицирующий орган, юрист, клиент с требованиями к поставщику. Тогда документ не бесполезен — у него другой читатель и другое решение («пройти аудит», «подписать контракт»), и писать его надо под этого читателя.
  • Разделить слои. Рабочий документ (для решения) и процессный артефакт (для проверки) не должны быть одним текстом: угодить обоим — значит не сработать ни для кого; пусть артефакт генерируется из рабочего или ссылается на него.
  • Автоматизировать. Отчёты о покрытии, списки изменений, матрицы прослеживаемости собираются из тикетов и кода скриптом: полдня работы экономят десятки часов в год.
  • Сократить шаблон. Аргумент не «шаблон плохой», а «эти четыре поля никто не заполняет осмысленно, уберём и посмотрим, спросит ли кто-нибудь». Обычно не спрашивают.
  • Считать честное время. «6 часов на релиз, 12 релизов в квартал — три недели инженерного времени в год» — единственный язык, на котором двигается такой разговор (см. «Работу вверх»). И храните такие артефакты отдельно от живой документации, иначе доверие к рабочим текстам упадёт до уровня процессных.

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

Типичные ошибки

  • «Документация для команды». Команда не адресат; адресат — роль в конкретной ситуации.
  • Вывод в конце. Структура «контекст → анализ → вывод» удобна автору и враждебна читателю: до вывода дочитывают единицы. См. «Структура».
  • Документ вместо разговора. Если решение задевает интересы, текст — опора для разговора, а не замена ему: «Трудные разговоры», «Обратная связь».
  • Проклятие знания. Автор не помнит состояние «я этого не знал» и пропускает шаг, без которого читатель застревает. Лечится внешним читателем: дайте текст тому, кто не в контексте, и смотрите, где он остановился.
  • Один документ на все аудитории: для каждого читателя он наполовину лишний.
  • Решение без срока уходит в вечное «обсудим», а документу без владельца перестают верить раньше, чем он реально устареет.

Практика

  1. Шапка-контракт. Возьмите свой документ за последние три месяца и допишите reader, decision, deadline, owner, review_by. Если decision не заполняется без слов «ознакомить» и «зафиксировать» — этот документ стоило написать иначе.
  2. Тест на удаление. Выпишите пять документов команды и честно ответьте, кто заметит их пропажу и через какое время; сверьтесь с телеметрией просмотров.
  3. Переписанный абзац. Перепишите первый абзац последнего дизайн-дока так, чтобы первое предложение содержало решение и адресата, и покажите обе версии коллеге, не говоря, какая новая: «какое решение от тебя тут ждут?»

Отдельная привычка: начинать документ со строки «читателю X нужно решить Y к сроку Z» — её потом можно удалить, но текст, написанный после неё, получается другим.

Источники

Мини-итог

  • Документ существует ради решения конкретного читателя. Нет читателя и решения — нет документа: есть черновик мышления, который не нужно публиковать.
  • Читателей несколько, главный один: вступление пишется под того, кто решает. Шапка-контракт (reader, decision, deadline, owner, review_by) стоит восемь строк и снимает половину проблем ещё до написания текста.
  • Читатель тратит секунды: вывод в начале, цена и риски рядом, детали ниже; документ конкурирует с чатом и встречей, а не с идеальной документацией.
  • Устаревание — симптом отсутствия адресата; лечится структурно: близость к коду, генерация, исполняемые примеры, владелец, срок жизни, меньше страниц, записи решений.
  • Часть документов пишется ради процесса: распознаются тестом на удаление и тестом на решение, лечатся поиском настоящего адресата, разделением слоёв и автоматизацией.

Что дальше

Мы выяснили, для кого и ради чего пишем. Следующий вопрос — как разложить материал внутри документа, чтобы читатель дошёл до нужного места за секунды: инвертированная пирамида, слои детализации, заголовки, по которым ищут, и почему хронологический порядок почти всегда плох.

Структура: как расположить материал, чтобы его прочли

Нашли неточность? Выделите фрагмент текста — рядом появится жучок.

Нужен разбор именно вашей ситуации?

Статья описывает общий случай. Если у вас частный — можно разобрать его отдельно, платно. А если не хватает целого материала, предложите тему: её оплачивают вскладчину, и она выходит открытой для всех.

Доска запросов