Разработчик пишет гораздо чаще, чем кажется. Commit message объясняет изменение будущему читателю истории Git. Pull request просит коллег проверить решение. Issue фиксирует проблему. Proposal предлагает потратить время и деньги. Письмо в рассылку пытается получить решение от нескольких людей.
У всех этих текстов одна типичная проблема: автор показывает путь, которым пришёл к выводу, вместо самого вывода. Читатель получает хронологию исследований, детали реализации и только в конце узнаёт, зачем всё это было написано.
Принцип пирамиды Минто предлагает обратный порядок: сначала ответ, затем основные аргументы, затем подтверждающие факты.
Главный вывод
│
┌──────────────┼──────────────┐
│ │ │
Аргумент 1 Аргумент 2 Аргумент 3
│ │ │
Факты Факты Факты
Для IT-коммуникации это можно сократить до трёх вопросов:
- Что произошло или что нужно сделать?
- Почему это правильный вывод?
- Какие факты его подтверждают?
Зачем переворачивать привычный порядок
Во время работы мы мыслим снизу вверх: собираем логи, читаем код, проверяем гипотезы и постепенно приходим к ответу. Поэтому первый черновик часто повторяет ход исследования:
Коротко: исследуйте снизу вверх, сообщайте сверху вниз.
Сначала мы посмотрели метрики, потом сравнили два релиза, заметили рост latency, изучили запросы к базе и нашли новый N+1 query. Поэтому релиз нужно откатить.
Читателю удобнее двигаться сверху вниз:
Нужно откатить релиз 2.18: новый N+1 query увеличил p95 latency API с 180 до 640 мс. После отката исправим загрузку связей одним batch-запросом и повторим нагрузочный тест.
Второй вариант сразу сообщает требуемое действие, причину и следующий шаг. Руководитель может принять решение по первой строке. Разработчик, который будет исправлять проблему, продолжит читать детали.
Это не означает, что детали не нужны. Они просто находятся на том уровне, где отвечают на возникший у читателя вопрос.
Как устроена пирамида
Один главный вывод
Вершина должна выражать законченную мысль, а не называть тему.
Слабая вершина:
Redis для rate limiting.
Сильная вершина:
Перенесём состояние rate limiter из памяти приложения в Redis, чтобы лимит оставался общим для всех реплик.
«Redis» - тема. «Перенесём состояние» - предложение, которое можно принять, отклонить или обсудить.
Практичная формула для первой строки:
[Решение / результат / запрос], потому что [главная причина].
Если текст должен привести к действию, добавьте владельца и срок:
[Кто] делает [что] к [когда], потому что [почему].
Каждый уровень отвечает на вопрос предыдущего
Первая строка неизбежно вызывает вопросы: «Почему?», «Как?», «Откуда это известно?» Следующий уровень должен отвечать именно на них.
Нужно перейти с cron-задачи на очередь.
│
├── Почему? Cron создаёт пики нагрузки и не даёт управлять повторными попытками.
├── Как? Продюсер публикует задания, воркеры обрабатывают их с backoff.
└── Каков риск? Появляется новая инфраструктурная зависимость.
Если абзац не поддерживает мысль над ним, его нужно перенести, переписать или удалить.
Идеи одного уровня должны быть одного типа
Плохая группа смешивает причины, действия и наблюдения:
- PostgreSQL перегружен;
- добавить индекс;
- p95 вырос в три раза.
Лучше разделить наблюдения и план:
- Диагноз: p95 вырос в три раза, CPU базы достиг 90%, в slow query log появился последовательный scan.
- Действие: добавить составной индекс, проверить план запроса и повторить нагрузочный тест.
Элементы одного уровня можно организовать:
- дедуктивно: правило → наблюдение → вывод;
- по времени: сначала → затем → после этого;
- по структуре: клиент → API → база данных;
- по важности: критично → существенно → желательно.
Выберите один принцип сортировки и не меняйте его внутри группы.
MECE: без пересечений и существенных пробелов
MECE - Mutually Exclusive, Collectively Exhaustive: элементы группы не дублируют друг друга и вместе покрывают вопрос настолько полно, насколько это необходимо для решения.
Например, причины задержки запроса можно разделить по участкам пути:
- клиент и сеть;
- приложение;
- база данных;
- внешние сервисы.
Такое деление полезнее списка «медленная сеть, backend, инфраструктура, PostgreSQL»: в последнем «backend» пересекается с базой, а «инфраструктура» может означать почти всё.
MECE - не требование создать идеальную классификацию мира. Для рабочего текста достаточно не повторять один аргумент под разными именами и не пропускать категорию, которая способна изменить решение.
SCQA: как подвести к вершине
Иногда ответ без контекста звучит слишком резко или непонятно. Для введения Минто использует структуру SCQ; ответ A становится вершиной пирамиды:
- Situation - знакомая читателю ситуация;
- Complication - изменение или проблема;
- Question - вопрос, который естественно возникает;
- Answer - ответ автора.
Пример для архитектурного proposal:
Situation: сейчас сервис принимает до 500 заданий в минуту и обрабатывает их синхронно.
Complication: новый клиент увеличит поток примерно до 5 000 заданий, а внешний API периодически отвечает429.
Question: как выдержать рост и не потерять задания?
Answer: отделить приём заданий от обработки с помощью очереди и масштабируемых воркеров.
В готовом тексте не обязательно оставлять эти метки. Обычно достаточно короткого введения:
Сейчас задания обрабатываются синхронно. После подключения нового клиента поток вырастет примерно в десять раз, а внешний API не гарантирует постоянную пропускную способность. Предлагаю отделить приём заданий от обработки с помощью очереди и масштабируемых воркеров.
SCQA особенно полезна для proposal, RFC, postmortem и длинного письма. В commit message или небольшом issue такой разгон обычно избыточен.
Практика: сначала построить, потом написать
1. Определите читателя и нужное решение
До начала текста ответьте:
- кто будет читать;
- что читатель уже знает;
- какое решение или действие от него требуется;
- какой главный вопрос у него возникнет.
Один и тот же инцидент по-разному описывается в сообщении для on-call инженера, postmortem для команды и письме клиентам.
2. Напишите вершину одним предложением
Не начинайте с введения. Сначала сформулируйте вывод. Если это невозможно, вероятно, вывод ещё не созрел или в тексте смешаны несколько независимых сообщений.
3. Выпишите 2–4 опорные мысли
Спросите: «Почему читатель должен согласиться?» или «Что ему нужно знать, чтобы действовать?» Ответы станут вторым уровнем.
Четыре пункта - не жёсткое ограничение, но длинный список часто означает, что идеи ещё не сгруппированы.
4. Проверьте вертикальную и горизонтальную логику
Вертикальная проверка:
Доказывает ли нижний уровень мысль над ним?
Горизонтальная проверка:
Однородны ли соседние пункты, не пересекаются ли они и понятен ли порядок?
Полезно прочитать только заголовки. Если из них складывается связный конспект, структура, скорее всего, работает.
5. Добавьте факты и удалите дневник расследования
Метрики, логи, ссылки на код, результаты экспериментов и ограничения усиливают аргумент. Но читателю редко нужны все попытки, которые ни к чему не привели.
История поиска важна, если она:
- подтверждает воспроизводимость;
- исключает вероятную альтернативу;
- предупреждает повторение ошибки;
- необходима для аудита.
В остальных случаях оставьте её в рабочих заметках.
Примеры из IT-коммуникации
Commit message
Commit message - очень маленькая пирамида. Заголовок сообщает результат, тело объясняет причину и важные следствия. Пересказывать diff не нужно: его и так видно.
Плохо:
fix payments
Лучше:
payments: ignore duplicate webhook deliveries
Persist the provider event ID before scheduling fulfillment.
Return success for an event that has already been processed.
The provider retries webhooks when our response times out, so the same
payment could previously create two fulfillment jobs.
Пирамида здесь выглядит так:
- Результат: повтор webhook больше не создаёт повторное задание на исполнение заказа.
- Реализация: сохраняем ID события и распознаём уже обработанные события.
- Причина: провайдер повторяет доставку после timeout.
Для очевидного изменения достаточно заголовка. Принцип Минто не требует превращать каждое переименование переменной в эссе.
Pull request
Описание PR должно помогать ревьюеру понять намерение изменения, оценить выбранный подход и быстро найти зоны риска.
Плохо:
В этом PR несколько изменений в checkout. Я сначала попробовал mutex, но потом переделал. Ещё обновил миграцию и тесты. Посмотрите, пожалуйста.
Лучше:
## Результат
Этот PR делает создание заказа идемпотентным и предотвращает дубли
при повторной отправке запроса клиентом.
## Как это работает
- API принимает `Idempotency-Key` и сохраняет его вместе с заказом.
- Повторный запрос с тем же ключом возвращает созданный заказ.
- Уникальный индекс разрешает гонку между параллельными запросами.
## Почему так
Проверка только в приложении оставляет race condition между чтением и записью.
Ограничение в базе делает инвариант атомарным для всех реплик.
## Риски и проверка
- Миграция создаёт индекс без блокировки таблицы.
- Добавлены тесты на последовательные и параллельные повторы.
- Проверен старый клиент без `Idempotency-Key`: его поведение не меняется.
## Просьба к ревьюеру
Особенно прошу проверить контракт повторного ответа и порядок миграции.
Первая секция даёт ответ. Следующие секции раскрывают устройство, обоснование и доказательства. Отдельная просьба направляет ограниченное внимание ревьюера туда, где оно ценнее всего.
Issue или bug report
В issue вершиной может быть наблюдаемая проблема, а вторым уровнем - влияние, доказательства и условия воспроизведения.
Плохо:
Иногда импорт не работает. В логах что-то про CSV. Файл приложил.
Лучше:
## Проблема
Импорт CSV отклоняет корректные файлы с Windows-переносами строк (`CRLF`).
Из-за этого 18% импортов партнёра Acme завершились ошибкой за последние сутки.
## Как воспроизвести
1. Экспортировать шаблон в Excel для Windows.
2. Добавить одну валидную запись.
3. Загрузить файл в `/imports`.
Ожидается: создана одна запись.
Фактически: `invalid character '\r' in column 7`.
## Диагностика
- Файл с `LF` импортируется успешно.
- Ошибка воспроизводится на production и staging.
- Парсер удаляет `\n`, но оставляет `\r` в последней колонке.
## Критерии готовности
- Файлы с `LF` и `CRLF` дают одинаковый результат.
- Существующий импорт не меняется для остальных файлов.
Заголовок самого issue также должен быть выводом: CSV import rejects CRLF files, а не Problem with import.
Proposal или RFC
Proposal существует ради решения, поэтому не прячьте рекомендацию после десяти страниц анализа.
# Перенести фоновые задания из PostgreSQL в managed queue
## Рекомендация
Использовать managed queue для новых фоновых заданий, а текущие очереди
в PostgreSQL переносить постепенно. Это отделит рост очереди от основной
базы и даст встроенные retry и dead-letter queue.
## Почему сейчас
1. Очередь создаёт до 35% записей в основной базе.
2. Во время пиков очистка таблицы конкурирует с пользовательскими запросами.
3. Новому процессу требуется независимое масштабирование воркеров.
## Рассмотренные варианты
1. **Оставить PostgreSQL и секционировать таблицу.** Дешевле краткосрочно,
но не устраняет конкуренцию за ресурсы базы.
2. **Развернуть собственный брокер.** Даёт больше контроля, но добавляет
круглосуточную операционную ответственность.
3. **Managed queue - рекомендуется.** Закрывает требования без поддержки
нового stateful-компонента командой.
## Последствия
- Плюсы: независимое масштабирование, retry, DLQ, меньше записей в БД.
- Минусы: стоимость сервиса, eventual consistency, новый способ локальной разработки.
## План и критерии успеха
Сначала перенести один некритичный тип заданий. Продолжить миграцию, если
за две недели доля потерянных заданий равна нулю, а p95 постановки в очередь
не превышает 200 мс. Откат - вернуть продюсер на запись в PostgreSQL.
Порядок важен: рекомендация → аргументы → варианты → последствия → реализация. Читатель сначала понимает, что ему предлагают, а затем проверяет качество решения.
Письмо в командную рассылку
В письме тема - вершина, первые строки - решение или запрос, остальной текст - обоснование.
Плохо:
Тема: Обновление по логам
Всем привет!
Мы уже некоторое время обсуждаем стоимость хранения логов. Я посмотрел
несколько дашбордов и поговорил с командами. Есть разные варианты, и,
кажется, нам стоит что-то поменять...
Лучше:
Тема: Решение до 24 июля: сократить хранение debug-логов с 30 до 7 дней
Предлагаю с 1 августа хранить debug-логи 7 дней вместо 30. Это снизит
ежемесячную стоимость логирования примерно на 22% без изменения срока
хранения audit- и error-логов.
Почему:
- за последние 90 дней 96% обращений к debug-логам приходились на первые 5 дней;
- требования compliance относятся к audit-логам и не меняются;
- нужный диапазон можно временно увеличить для конкретного сервиса.
Риски:
- расследование редкого старого инцидента может потерять часть контекста;
- командам нужно проверить экспорт важных логов в cold storage.
Прошу владельцев сервисов ответить до 24 июля, если есть сценарий,
которому необходимы debug-логи старше 7 дней. При отсутствии возражений
платформенная команда применит новую политику 1 августа.
Такое письмо можно понять по теме и первому абзацу. В нём явно указаны решение, границы изменения, основания, риск, требуемое действие и срок.
Сообщение об инциденте
Для оперативной коммуникации вершина должна отвечать на вопросы «что сломано», «каково влияние» и «что происходит сейчас»:
Checkout недоступен примерно для 30% пользователей в EU с 14:20 UTC.
Причина локализована в исчерпании пула соединений; команда откатывает
релиз 2.18. Следующее обновление - в 14:45 UTC.
Факты:
- US-регион не затронут;
- чтение каталога работает;
- подтверждённой потери данных нет.
Не начинайте статус инцидента с подробной временной шкалы. Сначала дайте текущую картину, затем подтверждения и хронологию.
Где принцип не стоит применять механически
Пирамида - инструмент ясности, а не универсальный литературный закон.
- Короткий вопрос не нуждается в трёх уровнях аргументов.
- Мозговой штурм может начинаться без готового ответа, но его итог стоит структурировать.
- Обучающий материал иногда ведёт читателя от наблюдения к открытию, чтобы тот самостоятельно построил модель.
- Художественный или личный текст может намеренно сохранять интригу.
- Плохие новости требуют не только логики, но и эмпатии: нельзя прятать влияние на людей за безличной структурой.
Есть и другая опасность: хорошо построенная пирамида делает слабую идею убедительной на вид. Структура не заменяет достоверные данные, рассмотрение альтернатив и честное описание неопределённости.
Главное
Принцип пирамиды Минто можно свести к простой дисциплине: не заставляйте читателя заново проходить весь путь вашего исследования.
Сначала сообщите ответ. Под ним сгруппируйте несколько независимых аргументов. Под аргументами разместите факты. Для сложного контекста используйте SCQA, для проверки групп - MECE. Масштабируйте глубину структуры под формат: одна строка для простого commit, несколько секций для PR, полноценное дерево аргументов для proposal.
Хороший технический текст экономит внимание. Читатель быстро понимает вывод, может проверить основания и знает, какое действие требуется дальше.
Источники
- Barbara Minto - The Minto Pyramid Principle
- The Pyramid Principle, Barbara Minto - Pearson
- Barbara Minto: “MECE: I invented it, so I get to say how to pronounce it” - McKinsey
Комментарии в Telegram-группе!