Я участвовал во множестве совещаний, где кто-нибудь говорил: «Подождите, почему мы сделали это именно так?», только чтобы обнаружить, что ответ был спрятан в 47-страничном RFC 2019 года, который никто никогда не открывал. Звучит знакомо?
Ирония заключается в том, что документы RFC должны предотвращать этот хаос. Вместо этого многие команды создают RFC, которые бегло просматриваются, неправильно понимаются или, что ещё хуже, полностью игнорируются. Но вот в чём дело: хорошо составленный RFC — это как хороший фильм. Ему не обязательно быть длинным, чтобы произвести впечатление. Ему просто нужно знать свою аудиторию и уважать её время.
Поработав с командами, которые борются с документацией, и с теми, кто её освоил, я заметил чёткую закономерность: люди читают те RFC, в которых понимают, что волнует их читателей. Эта статья расскажет вам, как именно писать такие RFC.
Почему RFC важны (и почему большинство людей их пропускают)
Прежде чем говорить о структуре, позвольте мне быть откровенным: никто не читает RFC для развлечения. Ваша команда читает их, потому что они должны это делать — или потому, что вы сделали их настолько интересными, что они хотят это делать.
Вот что на самом деле делает отличный RFC:
- Убеждает автора, что его мышление тщательное и охватывает крайние случаи.
- Убеждает команду, что решение обосновано и их обратная связь имеет значение.
- Убеждает заинтересованные стороны, что работа имеет смысл и команда берёт её на себя.
- Помогает будущим разработчикам понять, почему были приняты решения (не только то, что было решено).
Проблема в том, что большинство RFC терпят неудачу по первому пункту. Автор наполовину пишет его, команда бегло просматривает, заинтересованные стороны путаются, а будущие разработчики ничего не находят. Все проигрывают.
Когда на самом деле следует писать RFC?
Не каждое решение требует RFC. Если вы меняете имена переменных или исправляете цвет кнопки интерфейса, вам, вероятно, не нужен формальный документ. Но вот когда RFC становится необходимым:
Вам нужен RFC, когда:
- Решение затрагивает несколько систем или команд.
- Вы предлагаете значительное архитектурное изменение.
- Есть несколько жизнеспособных решений, и вам нужно согласовать одно из них.
- Реализация займёт несколько недель или больше.
- Это затрагивает инфраструктуру компании, безопасность или соответствие требованиям.
- Вы устанавливаете новый шаблон или стандарт, которому ваша команда будет следовать неоднократно.
Подумайте об этом как о разнице между проверкой кода и проверкой дизайна. Проверки кода происходят после того, как вы написали код. RFC происходят до того, как кто-либо прикоснётся к кодовой базе. Вы хотите согласования, пока ещё дёшево вносить изменения.
Структура RFC, которая действительно работает
Вот где большинство команд ошибается: они начинают с решений. Они погружаются в технические детали, не установив почему они решают эту проблему. Это как начинать фильм с кульминации — никому ещё не интересно.
Основание: начните с метаданных
Прежде чем написать хоть один абзац фактического содержимого, установите основы:
Метаданные:
Дата: ГГГГ-ММ-ДД
Автор: Ваше имя
Статус: Черновик/На рассмотрении/Принят/Отклонён
Номер RFC: RFC-001 (необязательно, но полезно)
Теги: архитектура, производительность, хранение
Заинтересованные стороны: Руководители команд, владельцы затронутых сервисов
Сроки: Ожидаемая дата принятия решения
Мне нравится подход с нумерацией. Когда кто-то говорит: «Помните тот RFC о распределённом отслеживании?», вы можете ответить: «О, RFC-047?» вместо неопределённых жестов руками. Это придаёт RFC ощущение полноценных артефактов.
Крючок: сначала напишите обзор
Это должно быть 2–3 предложения. Максимум. Это ваш краткий обзор.
Подумайте об этом как о трейлере к фильму. Захочется ли кому-нибудь после него посмотреть фильм? Вот плохой вариант: «Этот RFC посвящён улучшению нашей стратегии кэширования». Вот лучший вариант: «Мы теряем 30% выручки из-за промахов кэша в часы пик. Этот RFC предлагает двухуровневую стратегию кэширования, которая уменьшает промахи кэша на 85% с минимальными изменениями кода».
Видите разницу? Одно — утверждение. Другое создаёт срочность.
Контекст: описание проблемы (это критически важно)
Здесь большинство RFC спотыкается, но именно здесь они имеют наибольшее значение. Я повторю это, потому что это так важно: чёткое описание проблемы упрощает всё остальное.
Вот структура, которая работает:
- Начните с краткого резюме (1 предложение).
- Дайте контекст (Какова текущая ситуация? Какие метрики важны?).
- Чётко сформулируйте проблему (Почему это не работает? Какое влияние это оказывает?).
Качественное описание проблемы выглядит так:
«В настоящее время мы обрабатываем обратные вызовы платежей синхронно, что блокирует наш обработчик запросов на 2–5 секунд. Во время событий с высокой нагрузкой это приводит к тайм-аутам подключений, в результате чего 3–5% транзакций терпят неудачу. Это обходится примерно в 50 тысяч долларов в час в пиковые периоды и создаёт плохой опыт для клиентов».
Заметьте, что мы сделали здесь? Мы сделали проблему реальной. Не абстрактной. Деньги. Время. Влияние на клиентов. Измеримое.
Основное: предложенное решение
Теперь вы можете рассказать о своём решении. Включите:
- Что вы на самом деле предлагаете? (Будьте конкретны. «Лучшая производительность» — не предложение.)
- Как это решает проблему? (Сделайте ссылку на описание проблемы напрямую.)
- Почему это решение предпочтительнее альтернативных? (Признайте, что вы рассмотрели другие подходы.)
Для примера с оплатой:
«Мы предлагаем реализовать асинхронную очередь обратных вызовов, используя Redis и пул фоновых работников. Обратные вызовы записываются в Redis (< 100 мс), запрос возвращается немедленно, и работники обрабатывают обратные вызовы партиями. Это отделяет критический путь от обработки обратных вызовов».
Затем объясните: почему Redis? Почему не использовать RabbitMQ? Почему пакетирование? Покажите своё мышление.
Проверка реальности: плюсы и минусы
Здесь честность укрепляет доверие. У каждого решения есть свои компромиссы. Если вы сделаете вид, что у вашего их нет, вы сразу потеряете аудиторию.
Плюсы:
- Устраняет блокировку на критическом пути
- Горизонтальная масштабируемость (добавляйте работников по мере необходимости)
- Простая реализация с использованием существующей инфраструктуры Redis
- Легко отслеживать и отлаживать
Минусы:
- Добавляет операционную сложность (управление работниками)
- Обратные вызовы теперь асинхронные (типичная задержка 6–10 с)
- Требует тщательной обработки ошибок для неудачных обратных вызовов
- Redis становится более критичным для здоровья системы
Читатели ожидают минусов. Они ищут доказательства того, что вы действительно подумали об этом. Когда вы признаёте компромиссы, это показывает зрелость. Когда вы делаете вид, что их нет, вы выглядите наивно.
План действий: этапы реализации
Здесь вы придаёте своему предложению конкретику. Разбейте его на конкретные, последовательные этапы:
Этап 1: Инфраструктура (недели 1–2)
- Настроить кластер Redis с высокой доступностью
- Создать информационные панели для глубины очереди и задержки обработки
- Провести нагрузочное тестирование пропускной способности очереди
Этап 2: Реализация (недели 3–4)
- Реализовать очередь обратных вызовов в платёжной службе
- Создать фонового работника с логикой повтора
- Добавить метрики для показателей успешности/неуспешности
Этап 3: Развёртывание (недели 5–6)
- Развёртывание в промежуточной среде, проведение нагрузочных тестов
- Постепенное развёртывание в рабочей среде (5% → 25% → 50% → 100%)
- Мониторинг регрессий
Этап 4: Очистка (неделя 7)
- Удалить старый синхронный код обратных вызовов
- Документация и план действий для команды
Заметьте конкретику? Это не пустые мечты. Это то, что на самом деле нужно сделать, в определённом порядке, с приблизительными сроками. Теперь ваша команда может на самом деле взять на себя обязательства.
Влияние: что произойдёт, если вы это сделаете?
Конкретизируйте преимущества:
Ожидаемые результаты:
- Снизить частоту сбоев платежей с 3–5% до < 0,5%
- Улучшить время отклика API в среднем на 2–4 секунды
- Восстановить ~50 тысяч долларов в час в периоды пиковой нагрузки
- Позволить обработку обратных вызовов в 10 раз превышающую текущий объём
Риски, если мы этого не сделаем:
- Мы потеряем масштабируемость выручки (не сможем справиться с ростом)
- Качество обслуживания клиентов ухудшится во время всплесков трафика
- Технически задолженность увеличивается (больше патчей, больше сложности)
Ловушки: соображения и открытые вопросы
Здесь вы обращаете внимание на безопасность, соответствие требованиям, операционные проблемы:
Соображения:
