25 сент. 2025 г.·6 мин чтения

Переведите описание фичи в доменный код до начала разработки

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

Переведите описание фичи в доменный код до начала разработки

Почему описание фичи всё ещё оставляет команду в неведении

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

Возьмём строку вроде "Клиент запрашивает возврат со страницы биллинга." Один человек представляет мгновенный возврат. Другой ожидает проверки со стороны поддержки. Третий считает, что приложение блокирует возвраты по истечении 30 дней. Все читают один и тот же бриф и каждый может защитить своё понимание.

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

Когда команда начинает кодить, эти пробелы не остаются пустыми. Инженеры заполняют их. Продукт тоже. Дизайнеры закладывают свои предположения в интерфейс. QA обнаруживает другой набор предположений позже. Поддержка находит остальное, когда реальные пользователи попадают в случаи, о которых никто не говорил.

Та же самая проблема всплывает снова и снова. Что запускает действие и кто может это сделать? Какое правило разрешает или блокирует его? Что система записывает после произошедшего? Что делать, если что‑то провалилось или пришло дважды?

Эти детали часто проявляются поздно, потому что бриф на первый взгляд кажется полным. Он звучит ясно, пока кто‑то не спросит: «А что если платёж уже зачислен?» или «Уведомляют ли пользователя до проверки или после одобрения?»

Именно поэтому команде стоит перевести описание фичи в доменный код до того, как инженеры откроют редактор. Не в программный код, а в доменный код на бизнес‑языке: команда, которую кто‑то посылает, правило, которое система проверяет, и событие, которое система фиксирует.

Без этого шага команды строят на догадках. Некоторые догадки будут разумны. Некоторые — дорогими. Цена проявляется в переработках, исправлениях багов, изменённых тестах и напряжённых совещаниях после того, как QA или поддержка сообщают о непредсказанном поведении.

Что такое доменный код простыми словами

Доменный код — это часть софта, описывающая, как работает бизнес. Это не оформление страницы, не цвет кнопки и не порядок полей формы. Это поведение за действиями, которые важны людям: оформление заказа, приостановка подписки или запрос на возврат.

Когда команда переводит бриф в доменный код, разговор смещается от экранов. Бриф, говорящий «добавить кнопку возврата и модал подтверждения», пропускает реальную суть. Суть в том, что клиент просит бизнес сделать, что бизнес разрешает и какой факт должна записать система.

Команда — это запрос. Она говорит системе, что кто‑то хочет, чтобы произошло. Названия вроде RequestRefund, PauseSubscription или ApproveDiscount работают, потому что и не‑инженеры могут их прочесть и понять.

Правила решают, примет система команду или отклонит. Это бизнес‑проверки. Возврат может быть разрешён только в течение 14 дней, только для оплаченных счетов и только если на аккаунте нет метки мошенничества. Если правило не проходит, система должна объяснить причину.

События — это факты о прошлом. Они фиксируют то, что уже произошло: RefundRequested, RefundApproved или SubscriptionPaused. Это важно, потому что команды могут тестировать факты, аудировать их и обсуждать без углубления в UI‑детали.

Имена важнее, чем команды ожидают. Если поддержка говорит «запрос на возврат», а инженеры называют процесс ReversePaymentWorkflow, люди начинают говорить на разных языках. Держите имена близко к словам, которые бизнес уже использует в звонках продаж, тикетах поддержки, политике и командных встречах.

Это небольшое смещение экономит время. Инженеры начинают с более ясными намерениями, продукт раньше замечает пропущенные правила, и все тратят меньше времени на споры о значении фичи.

Соберите исходные материалы прежде чем что‑то мапить

Бриф редко рассказывает всю историю. Заметки продукта живут в одном документе, вопросы поддержки — в чате, а крайние случаи скрыты в старых тикетах. Если команда начинает моделировать поведение слишком рано, эти пробелы превращаются в плохие предположения.

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

Затем отметьте язык, который уже используют люди. Ищите существительные, названия бизнес‑объектов, действия, которые выполняют люди, лимиты, которые блокируют или разрешают шаг, и даты, влияющие на разрешения. Это самый быстрый способ перевести бриф в доменный код без догадок.

Короткая заметка может раскрыть многое. Если в брифе написано «владельцы рабочего пространства могут приостанавливать биллинг один раз в год до даты продления», у вас уже есть большая часть исходного материала. «Владелец рабочего пространства» показывает, кто инициирует действие. «Приостановить биллинг» даёт название действия. «Один раз в год» — ограничение. «До даты продления» — правило по времени.

Спрашивайте, кто запускает каждое действие и кто утверждает его. Не предполагайте, что одно и то же лицо делает и то, и другое. Клиент может запросить изменение, поддержка — подтвердить детали, а финансы — одобрить финальный шаг.

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

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

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

Превратите одну историю в команды, правила и события

Возьмите одно действие из истории и заморозьте остальное. Если пытаться мапить всю фичу сразу, имена расплывутся и люди начнут спорить о крайних случаях слишком рано.

История обычно скрывает несколько действий. Разбейте их. Если в истории сказано, что клиент может приостанавливать, возобновлять и отменять подписку, начните только с одного.

Сначала напишите команду. Держите форму «глагол + объект», потому что так её легко читать и тестировать. «Pause subscription» — понятно. «Subscription pause flow» — уже нет; это звучит как название проекта.

Затем опишите правила, которые должны быть верны до выполнения команды. Это бизнес‑проверки, не UI‑детали. Они отвечают на простой вопрос: когда система должна разрешить это действие?

Для небольшой истории карта может выглядеть так:

  • Действие пользователя: клиент хочет приостановить подписку
  • Команда: Pause subscription
  • Правила: подписка активна, клиент является владельцем, следующий цикл биллинга ещё не начался
  • Событие успеха: Subscription paused
  • Исходы неудачи: подписка уже приостановлена, клиент не имеет права, окно биллинга закрыто

Событие важно, потому что оно говорит всем, что изменилось после успеха. Оно должно звучать как факт, а не как просьба. «Subscription paused» работает. «Pause accepted» слабее, потому что не говорит, что система фактически сделала.

Называйте причины неудач простым языком. Избегайте расплывчатых меток вроде «validation error», когда есть конкретная причина. Инженеры затем сопоставят эти имена с кодовыми ошибками, но на воркшопе текст должен быть читабельным для продукта, поддержки и QA.

Переходите к следующему действию и повторяйте паттерн. Одна команда, небольшой набор правил, одно событие успеха и явные ошибки. Такой ритм удерживает разговор в рамках и даёт инженерам доменный код, который они могут реализовать до обсуждения экранов, эндпоинтов или таблиц в базе данных.

Простой пример: запрос на возврат в SaaS‑приложении

Turn Stories Into Decisions
Oleg can help your team turn feature requests into clear business behavior.

Запрос на возврат кажется простым, пока команда не задаст базовый вопрос: что приложение должно делать пошагово?

Клиент открывает страницу биллинга, нажимает опцию возврата и ожидает быстрый ответ. История короткая, но поведение всё равно нужно назвать. Чтобы перевести бриф в доменный код, превратите действие клиента в команду RequestRefund. Это название сразу подсказывает, что приложение пытается сделать в этот момент.

Затем приложение проверяет правила. Заказ должен существовать. Платёж должен быть завершён. Окно для возврата должно ещё быть открыто.

Эти правила предотвращают расплывчатые споры позже. Если заказа нет, приложение должно об этом сказать. Если платёж ещё в ожидании или период возврата закончился вчера, команда может сослаться на правило, а не спорить о намерении.

Когда все три проверки проходят, приложение фиксирует RefundRequested. Это событие — факт, а не заглушка для будущей работы. Оно означает, что система приняла запрос на возврат в тот момент.

После этого поток может разветвляться. Сотрудник поддержки, финансист или автоматическая политика могут отправить ApproveRefund или RejectRefund. Эти команды создают новые факты: RefundApproved или RefundRejected.

Если одобрение приводит к фактической выплате, запишите отдельное событие RefundPaid. Такая декомпозиция оправдана: одобрение могло произойти в 10:02, а процессор выплат завершит перевод через несколько часов.

Теперь представьте, что клиент пишет в поддержку в пятницу: «Мне сказали, что возврат одобрили. Где деньги?» Трейл событий отвечает быстро. Если поддержка видит RefundApproved, но не RefundPaid, это значит, что кейс всё ещё в работе. Если видит RefundRejected, значит система уже приняла решение и можно объяснить причину.

В этом и заключается смысл команд, правил и событий. Расплывчатая история «клиент просит возврат» превращается в поведение, которое команда может тестировать, обсуждать и строить без догадок.

Пишите имена, которые можно тестировать и обсуждать

Хорошее доменное имя звучит как язык бизнеса. Если поддержка говорит «выписать возврат», а продажи — «апгрейдить план», ваши команды и события должны использовать те же слова. Команды работают быстрее, когда имена уже знакомы.

Имена рушатся, когда они берутся из интерфейса, а не из работы. Слова вроде кнопка, модал, вкладка и экран относятся к дизайну, а не к доменному коду. Экран может измениться на следующей неделе. Бизнес‑действие обычно остаётся тем же.

Поэтому OpenRefundModal — слабое доменное имя, а ApproveRefund или RejectRefund дают людям конкретику для обсуждения. Одно описывает клик. Другое — решение.

Короткие узкие команды легче тестировать. Если кто‑то не может объяснить команду в одном предложении, скорее всего она делает слишком много. Классический пример — ProcessOrder. Зарядить карту? Забронировать товар? Отправить чек? Всё вместе?

Более конкретные имена выглядят так:

  • ChargeInvoice вместо ProcessBilling
  • SuspendAccount вместо HandleUserStatus
  • SendTrialEndingReminder вместо RunNotifications
  • MarkContractSigned вместо UpdateDeal

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

Прочитайте имена вслух перед началом кодирования. Десятиминутный просмотр с одним представителем поддержки, продаж или операций обычно быстро ловит расплывчатые формулировки. Если двое дают разный смысл для одной команды, переименуйте её прямо на месте.

Этот маленький шаг реально экономит время и делает автоматизацию безопаснее. Чёткие имена дают людям и инструментам точное намерение, а не заставляют угадывать.

Ошибки, которые возвращают инженеров к брифу

Reduce Rework On New Features
Review the domain flow first and give your team a clearer starting point.

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

Один из быстрых способов запутать команду — смешать команды и события в одном списке. Команда — это запрос, например «approve refund». Событие — факт, например «refund approved». Если оба лежат рядом без разделения, никто не знает, что должно идти первым, что система решает, и что фиксируется после решения.

Правила тоже создают проблемы, когда их пишут как цели, а не как проверки. «Предотвратить неверные возвраты» звучит хорошо, пока кто‑то не спросит, что считать неверным. Правило должно иметь чёткое условие «проходит/не проходит». «Отклонять запросы на возврат для счетов старше 14 дней» гораздо лучше, потому что инженеры могут это реализовать, а QA — протестировать.

Временные рамки часто теряются в расплывчатых формулировках. Это создаёт реальные баги. Если клиент может запросить возврат только в течение 14 дней, запишите это число. Если поддержка должна ответить в течение одного рабочего дня — запишите и это. Ограничения по времени меняют поведение, права и граничные случаи.

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

Объединённые команды особенно дороги, потому что скрывают пути отказа. Возврат может пройти, а письмо — упасть. Отмена может требовать одобрения, а возврат — нет. Разделённые команды делают эти ветви видимыми.

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

Быстрая проверка перед началом разработки

Clean Up Delivery Decisions
Sort rules, roles, and edge cases early with hands on CTO advice.

Бриф может выглядеть ясным и всё же оставлять пробелы, когда люди начинают строить. Быстрее всего это обнаружить, если прочитать команды, правила и события небольшой смешанной группе: продукт, инженеры, QA и кто‑то из поддержки или операций. Если только инженеры могут объяснить список, имена всё ещё слишком близки к экрану и недостаточно близки к бизнесу.

Каждая команда должна иметь смысл без упоминания кнопок, форм или потока страниц. Неинженер должен объяснить, что значит Submit refund request или Approve trial extension простыми словами. Если для объяснения нужен мокап — имя, вероятно, слабое.

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

Случаи отказа важны не меньше. Назовите те, которые пользователь реально заметит: дублированный запрос, истёкший план, отсутствие одобрения, превышение лимита, аккаунт заблокирован. Вам не нужны все технические крайние случаи на этом этапе, но нужны те, которые изменяют пользовательский интерфейс, тесты QA и объяснения поддержки.

Обычно быстрая проверка сводится к пяти вопросам:

  • Может ли кто‑то вне инженерии объяснить каждую команду в бизнес‑терминах?
  • У каждой команды есть правила и одно событие успеха?
  • Названы ли ошибки, которые заметят пользователи?
  • Может ли QA превратить список в тест‑кейсы без догадок?
  • Может ли поддержка проследить трекинг событий и объяснить клиенту, что произошло?

Последний пункт часто упускают. Поддержке не нужны глубокие системные детали, но нужен чистый рассказ: запрос получен, проверка правоспособности, действие одобрено, клиент уведомлён. Когда цепочка событий читается так, инженерам обычно достаточно ясности, чтобы начать строить без сюрпризов.

Что делать дальше с командой

Начните с одной фичи, которая уже вызывает трения. Выберите то, что люди читают по‑разному: возвраты, изменения доступа или апгрейды плана. Такие функции быстро выявляют скрытые предположения, поэтому они лучше всего подходят для опробования метода.

Короткой проверки достаточно. Соберите продукт, инженеров и поддержку в комнате на 30 минут и работайте с брифом, а не с кодом. Поддержка обычно знает, где пользователи путаются, продукт знает намерение, а инженеры обнаружат отсутствующее поведение прежде, чем кто‑то построит не то.

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

Держите первый черновик небольшим. Часто одной страницы достаточно. Если пытаться учесть все крайние случаи в первый день, команда застрянет и снова вернётся к расплывчатому языку брифа.

После релиза обновите документ. Сравните запланированные команды, правила и события с тем, что реально произошло во время доставки, QA и тикетов поддержки. Такое исправление важно, потому что превращает разовую практику в командную привычку.

Если хотите переводить брифы в доменный код без замедления команды, используйте одинаковый формат каждый раз. Сохраняйте структуру простой: история, команда, правило, событие, открытый вопрос. Последовательность упрощает планирование, и люди перестают спорить о форме документа.

Некоторым командам нужен внешний ревьюер на первые несколько раз. Это помогает, когда брифы грязные, роли пересекаются или никто не отвечает за финальную формулировку. Oleg Sotnikov делает такие обзоры как fractional CTO, и работа на oleg.is связана с тем, чтобы сделать доставку понятнее ещё до начала кодирования.

Попробуйте это на одной запутанной фиче на этой неделе. Если встреча завершилась с меньшим количеством открытых вопросов и более понятными именами, сохраните формат и применяйте его к следующему брифу.

Часто задаваемые вопросы

What does domain code mean?

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

Why is a feature brief not enough on its own?

История рассказывает, чего хочет пользователь, но часто пропускает сроки, права доступа, ошибки и передачи между людьми. Когда эти детали остаются расплывчатыми, инженеры, QA и поддержка заполняют пробелы по‑разному.

When should we translate a brief into commands, rules, and events?

Сделайте это до того, как кто‑то начнёт писать код. Короткий семинар на раннем этапе экономит время и снижает доработки, потому что команда заранее соглашается по поведению системы.

What is the difference between a command, a rule, and an event?

Команда отправляет запрос — команда. Правило проверяет, следует ли его принять, например «платёж прошёл». Событие фиксирует факт уже произошедшего, например RefundRequested.

How detailed should the rules be?

Пишите только те правила, которые меняют результат. Указывайте лимиты, даты, права и проверки, которые блокируют или разрешают действие, но не описывайте детали интерфейса вроде текста кнопки или последовательности модальных окон.

How should we name commands and events?

Используйте те слова, которые уже употребляет бизнес в тикетах, звонках и правилах. ApproveRefund или PauseSubscription понятнее и стабильнее, чем расплывчатые метки типа ProcessFlow.

What mistakes cause the most confusion?

Не смешивайте в одном списке запросы и факты. Избегайте объединённых команд, расплывчатых правил вроде «предотвратить неверные возвраты» и не забывайте указать, кто выполняет каждое действие.

Who should review this before engineers build it?

Соберите продукт, инженеров, QA и кого‑то из поддержки или эксплуатации. Такая группа быстро ловит неясности, потому что у каждого своё представление о проблеме.

How do we handle approvals or manual steps?

Проговорите ручной шаг вслух и явно укажите его в последовательности. Если сначала нужна проверка поддержки или финансистов, оформите это как отдельную команду и событие, а не как невидимую логику системы.

What is the easiest way to start using this with my team?

Начните с одной спорной фичи, например возвратов или смены тарифа. Если хотите внешнюю помощь по поведению продукта и доставке, опытный fractional CTO может проверить формулировки и упростить процесс до начала кодирования.