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

Почему это кажется сложнее, чем должно быть
Моделирование предметной области кажется большим делом потому, что большинство советов написано для крупных компаний. Вы читаете про bounded contexts, общий язык и формальные диаграммы, и начинает казаться, что перед релизом нужна целая церемония проектирования.
Противоположная ошибка кажется легче. Небольшая команда может быстро двигаться с обработчиками маршрутов, сервисными файлами и парой проверок в базе. Некоторое время это работает. Затем одно правило биллинга живёт в API‑эндпоинте, другая версия — в фоновой задаче, а третья проверка прячется в интерфейсе. Команда всё ещё релизит, но никто не знает, где находится реальная защита.
Вот в чём проблема. Слишком малая структура прячет рискованные правила в случайных файлах. Слишком большая — тормозит доставку и превращает простую работу в дебаты о названиях. Ясное правило в одном очевидном месте легко доверять. То же правило, похороненное под слоями мелких классов, обычно вызывают меньше доверия.
Представьте двухчленную SaaS‑команду, добавляющую апгрейды аккаунта. Один разработчик меняет лимиты плана. Другой меняет расписание выставления счетов. Ни один из них не видит правила, которое не даёт пользователю получить премиум‑доступ до подтверждения оплаты. Никто не действовал безрассудно — правилу просто не дали ясного дома.
Большинству команд не нужна идеальная модель всего бизнеса. Им нужна небольшая структура вокруг правил, которые действительно могут им навредить: движение денег, права доступа, условия контрактов, лимиты бронирований, проверки соответствия, распределение запасов. Эти правила заслуживают повышенного внимания, потому что баги там стоят дороже, чем неаккуратная вспомогательная функция.
Цель проста: меньше дорогостоящих ошибок. Если модель делает одно рискованное правило лёгким для поиска, простым для тестирования и труднопроходимым, она выполняет свою задачу. Всё остальное может оставаться обычным кодом, пока реальность не покажет обратное.
Что заслуживает модель
Модель оправдана, когда ошибка в правиле может стоить денег, нарушить обещание или создать юридические проблемы. Если клиент может быть заряжен дважды, сохранить доступ после отмены или получить возврат, которого быть не должно, такое правило не должно жить разрозненно по приложению. Дайте ему понятное имя и одно место.
То же касается обещаний клиентам. Если на странице с ценами написано «возвраты доступны в течение 14 дней» или «только админы могут экспортировать данные», этим правилам нужна структура. Они влияют на доверие. Когда команда случайно меняет их, быстро появляются тикеты в поддержку.
Изменения состояния часто тоже заслуживают модели. Если один статус меняет то, что человек может делать дальше, зафиксируйте это в коде как реальную концепцию. Счёт‑фактура, переходящая из draft в sent в paid, — это не просто текст на экране. Каждый статус разрешает или блокирует действия, и там любят прятаться баги.
Также моделируйте те термины, вокруг которых команда всё время спорит. Если люди спрашивают «Когда триал становится активным?» или «Что считается неудачной попыткой оплаты?» чаще одного раза, язык нечёткий. Небольшая модель вынудит команду согласовать значения, и это само по себе может сэкономить часы переработки.
Повторяющиеся правила — ещё один сильный сигнал. Если правило по скидкам используется при оформлении заказа, в счетах и в админских отчётах, оно должно вести себя одинаково везде. Общие правила требуют одного источника правды, не трёх похожих версий.
Быстрый фильтр:
- Ошибка попадёт по доходам, соответствию требованиям или доверию клиента?
- Управляет ли правило тем, что происходит далее?
- Люди используют разные слова для одного и того же?
- То же правило встречается в нескольких частях продукта?
- Скорее всего новый разработчик реализует это по‑другому без указаний?
Если «да» повторяется больше одного раза, это правило, вероятно, заслуживает модели.
Что можно оставить обычным кодом
Не каждая логика требует особого отношения. На самом деле, большинство логики должно оставаться простым кодом.
Простые вычисления — хороший пример. Если функция просто преобразует входы в выходы, оставьте её функцией. Подитог, форматтер даты, оценка доставки или процент прогресса обычно не требуют специального доменного типа.
Проверки только для экрана должны жить рядом с экраном. Если форма регистрации рисует красную рамку, дизейбит кнопку или предупреждает, что пароль слаб, это правило принадлежит UI, если сервер на него не полагается. Отправлять каждую UI‑проверку в модель быстро создаёт шум.
Эксперименты должны оставаться лёгкими, пока они движутся. Небольшая команда может тестировать новый шаг онбординга, сообщение триала или порядок сортировки и менять это три раза в неделю. Формальная структура слишком рано просто замедлит изменения.
Клей‑код должен оставаться скучным, когда он только двигает данные. Сопоставление полей из API в базу, переименование значений для экспорта или формирование JSON для очереди обычно не доменная работа. Это становится доменной работой, когда шаг также навязывает рискованное бизнес‑правило.
Логика отчётности часто остаётся простой. Если вы добавляете колонку для дашборда или месячного экспорта, запрос или view обычно достаточны. Если то же поле позже начинает контролировать скидки, возвраты или лимиты аккаунтов, ему нужно больше внимания.
Небольшой магазин даёт понятный пример. Показ «предполагаемых очков» на странице товара может оставаться обычным кодом, если это просто превью. Момент, когда эти очки влияют на оплату, возвраты или балансы клиентов, переводит правило в модель.
Задайте один прямой вопрос: если этот код ошибётся, что сломается? Если ответ «одна страница выглядит странно» или «одно число в отчёте смещено», оставьте всё простым.
Пятишаговый фильтр для маленьких команд
Маленьким командам чаще помогает фильтр, чем грандиозный дизайн. Если каждое правило кажется особенным, вы в итоге смоделируете всё, и модель станет лишней работой.
Используйте простой проход.
- Начните с правил, которые люди повторяют. Слушайте планёрки, чаты поддержки, репорты багов и обзоры релизов. Если одно и то же правило всплывает каждую неделю, запишите его одной простой фразой.
- Отметьте правила, которые могут стоить денег или повредить доверию. Неправильные возвраты, дублирующие счета, ошибки доступа, сломанные утверждения и опоздавшие отправки — сюда. Правило по цвету или порядку кнопок обычно нет.
- Проверьте, где каждое правило встречается. Если то же правило появляется в оформлении заказа, админ‑инструментах, действиях поддержки и отчётах, оно склонно к дрейфу.
- Дайте каждому рискованному правилу короткое имя и один реальный пример. «Право на возврат» понятно. «Логика справедливости клиента» — нет. Добавьте конкретный кейс, например: «Клиент имеет право на полный возврат в течение 14 дней, если товар не использовался.»
- Моделируйте только то, что проходит этот фильтр. Если правило рискованно, повторяется и легко объясняется реальным примером, дайте ему маленький дом в коде. Это может быть один тип, один модуль или одна хорошо покрытая тестами политика.
Интернет‑магазин показывает это просто. Налоговые правила, окна возврата и проверки на мошенничество часто заслуживают модели, потому что ошибки ведут к чарджбекам, разгневанным письмам или юридическим проблемам. Правило вроде «показывать похожие товары под основным изображением» может оставаться обычным кодом.
Такой обзор не займёт много времени. Для небольшого бэклога часто хватает 30 минут, чтобы отделить реальные бизнес‑правила от шума.
Простой пример: возвраты в интернет‑магазине
Запрос на возврат кажется простым, пока два нюанса не изменят ответ: когда клиент попросил и что он купил. Пуловер, возвращённый через 5 дней, — один кейс. Загрузимый шаблон, открытый сразу, — другой. Риск денег сидит в этих различиях, а не в кнопке «Запросить возврат».
Вам не нужна модель всего магазина. Нужна небольшая модель возврата, покрывающая правила, которые могут стоить денег, вызвать чарджбеки или споры в поддержке.
Где правила действительно находятся
«Передумал» и «товар повреждён» не должны идти по одному пути. Если клиент передумал, магазин может разрешать возврат только в течение 14 дней и только после возврата товара. Если товар повреждён, магазин может возместить доставку, пропустить возврат для недорогих товаров или попросить фото первым делом.
Это бизнес‑правила. Они решают, разрешён ли возврат, сколько денег возвращается и какие доказательства нужны.
Несколько терминов тоже должны иметь точное значение. «Кредит магазина» — это не наличный возврат. «Частичный возврат» — не полный возврат с последующим добавлением купона. «Финальная распродажа» может означать разные вещи для физичных товаров, цифровых продуктов и кастомной работы. Если эти имена остаются туманными, поддержка, финансы и инженерия будут принимать разные решения.
Небольшая модель может держать только те части, которые меняют исход:
- причина возврата
- тип товара
- дата покупки
- требует ли товар возврата
- тип решения: наличный возврат, частичный возврат или кредит магазина
Этого достаточно, чтобы ответить на трудный вопрос: допустим ли этот возврат и на каких условиях?
Текст письма клиенту не требует такого же отношения. Формулировка, приветствие и макет могут оставаться обычным кодом или шаблоном. Эти части важны для подачи, но они не решают риск.
Если вы начнёте слишком широко, команды застрянут, моделируя корзины, заказы, инвентарь и профили клиентов, прежде чем исправят реальную проблему. Начните с допустимости возврата. Дайте рискованным случаям ясные имена. Остальное оставьте простым, пока не начнёт болеть.
Как держать модель маленькой
Маленькая модель должна объяснять риск, а не копировать всё приложение. Если у вас в кодовой базе есть классы для каждой таблицы, каждого поля запроса и каждого API‑ответа, вы не моделируете бизнес — вы копируете структуру одного слоя в другой.
Используйте имена, которые люди уже произносят вслух. «Возврат», «триал», «утверждённый заказ» и «чарджбэк» несут смысл. «OrderEntity» или «PaymentPayload» обычно нет. Бизнес‑термины помогают продукту, поддержке и инженерам говорить об одном и том же без перевода.
Поставьте каждое рискованное правило в одно место. Если правило может лишить денег, создать юридическую проблему или сломать доверие клиента, команда должна знать, где оно живёт. Не разбивайте одно и то же решение между контроллером, хелпером и тремя проверками в базе. Такой набор никогда не спасёт время, когда что‑то пойдёт не так.
Примеры держат модель честной. Рядом с каждым правилом напишите два‑три простых случая, показывающих, что должно происходить. Короткая заметка типа «Возврат после 30 дней отклоняется, если только товар не был повреждён при доставке» делает больше работы, чем страница абстрактного текста. Новые коллеги читают примеры быстрее и замечают плохие предположения раньше.
Короткая самопроверка:
- Имя соответствует бизнес‑термину, а не термину хранения.
- Рискованное правило живёт в одном месте.
- Коллега может найти пример за минуту.
- Последний добавленный класс изменил реальное решение, а не форму данных.
Последний пункт важен. Прекратите добавлять структуру, когда новые типы и слои перестают менять решения. Если команда всё ещё спорит об одних и тех же краевых случаях после добавления классов, дополнительная модель — украшение.
Пересматривайте модель после реальных инцидентов, а не потому, что календарь говорит сделать это каждую неделю. Проваленный возврат, ошибка в цене или случай в поддержке с реальными издержками дают повод её ужесточить. Очистка по расписанию часто превращается в аккуратные диаграммы, которыми никто не пользуется.
Ошибки, которые тратят время зря
Маленькие команды обычно теряют время по двум причинам: моделируют слишком рано или моделируют не то.
Одна распространённая ошибка — слепо копировать книжные паттерны, пока не ясно, где сидит реальный риск. Команда читает про агрегаты, события и слоистые правила, а затем строит всё это в продукте, который меняется каждую неделю. Если вы ещё не знаете, какая ошибка может стоить денег, доверия или привести к юридическим проблемам, тяжёлая структура лишь замедлит работу.
Ещё одна ловушка — превращать каждое существительное в модель, потому что оно упомянуто в разговоре с продажами или поддержкой. Клиенты говорят про планы, места, команды, рабочие пространства, утверждения, роли, приглашения и исключения. Это не значит, что каждое слово заслуживает глубокую модель. Большинство из них — просто ярлыки вокруг простой логики. Если никакое рискованное правило не зависит от них, обычного кода достаточно.
Команды также теряют время, смешивая поток экрана с бизнес‑правилами. Страница оформления может иметь пять шагов, но правило может быть таким: нельзя отправлять товар, пока не подтверждена оплата. Экран может измениться в следующем месяце. Правило, скорее всего, нет.
Переименование вещей — ещё один простой способ потерять неделю. Команды спорят, это «аккаунт», «рабочее пространство» или «организация», в то время как реальное правило остаётся нечётким. Начните с правила: кто что может делать, когда и с каким лимитом? Как только это станет ясно, имя обычно найдётся само.
Старые абстракции тоже тихо вредят. Стартап добавляет логику реселлеров, партнёрские уровни или состояния утверждения для одной сделки, а затем сохраняет их долго после изменений в продукте. Через полгода каждая новая фича должна огибать мёртвые идеи. Удаляйте чаще.
Быстрый тест:
- Если правило защищает деньги, безопасность, соответствие или доверие клиентов — модельте его.
- Если оно лишь отражает текущий поток страницы или формулировку — оставьте простым.
- Если никто не может объяснить, зачем абстракция ещё существует — удалите её.
Что делать дальше
Перестаньте смотреть на весь продукт сразу. Выберите один рабочий процесс, который уже вызывает трения — например возвраты, изменения планов, утверждения доступа или правки счетов. Как правило, этого достаточно, чтобы выявить важные правила.
Запишите только те правила, которые могут стоить денег или повредить доверию. Если неправильное решение может привести к неверному списанию, сломанному обещанию или потоку тикетов в поддержку, дайте правилу ясное имя и чёткое место в коде.
Практический первый проход выглядит так:
- Выберите один запутанный рабочий процесс, с которым команда сталкивалась в последний месяц.
- Перечислите решения, которые могут вызвать потерю дохода, возвраты, споры по оплате или разгневанные письма.
- Превратите эти решения в явные правила с тестами.
- Оставьте связывание форм, текст и одноразовые хелперы простым кодом.
Этот последний шаг важнее, чем кажется. Многие команды перестраивают безвредные части. Если функция только мапит поля для экрана, форматирует текст или обрабатывает одноразовый кейс — пусть она остаётся скучной. Обычный код легче читать, менять и обычно дешевле сопровождать.
Используйте обращения в поддержку и ошибки биллинга как цикл ревью. После следующей проблемы в поддержке или ошибке в счёте вернитесь к своему списку и спросите: «Произошло ли это потому, что бизнес‑правило жило только в чьей‑то голове?» Если да — вынесите его в модель. Если нет — оставьте как есть.
Небольшой пример проясняет разделение. «Возврат после 30 дней требует утверждения» — это бизнес‑правило. «Показывать причину возврата под кнопкой» — интерфейсный код. Команды экономят много времени, когда перестают относить оба случая к одному уровню риска.
Если команде нужна вторая точка зрения, Oleg Sotnikov на oleg.is работает с стартапами как fractional CTO и советник, часто помогая командам определить немногие рискованные правила, которые заслуживают реальной структуры. такого обзора обычно достаточно, чтобы не построить огромную модель, о которой вы пожалеете через шесть месяцев.
Часто задаваемые вопросы
Малым командам действительно нужно моделирование предметной области?
Нет. Большинству маленьких команд нужен модель только для нескольких рискованных правил, а не для всего продукта. Начинайте с того, где ошибки могут стоить денег, лишить доступа или создать проблемы в поддержке.
Что стоит моделировать в первую очередь?
Выберите правило, которое может навредить быстрее всего. Правила по допустимости возврата, лимитам планов, статусу платежа, контролю доступа и правилам утверждения обычно требуют внимания раньше, чем поток экрана или текст на странице.
Что может оставаться обычным кодом?
Оставляйте простые вычисления, форматирование, сопоставление полей и поведение, зависящее только от интерфейса, как обычный код. Если баг просто «одна страница выглядит странно» или «одно число в отчёте чуть не сходится», не добавляйте лишнюю структуру.
Как понять, что правилу нужен единый источник правды?
Когда одно и то же правило появляется при оформлении заказа, в админке, в фоновых задачах и в отчётах, оно начнёт расходиться, если у него нет единого владельца. Дайте такому правилу один дом и заставьте остальные части вызывать его, а не переписывать.
Должна ли валидация UI жить в модели?
Чаще нет. UI‑валидация обычно остаётся рядом с экраном, если сервер не полагается на то же самое правило. Предупреждение о слабом пароле может жить в форме, но очистка платежа или лимиты на возврат должны быть в модели.
Насколько маленькой может быть модель?
Очень маленькой. Один модуль, один тип или одна политика могут быть достаточны, если они удерживают решение, которое действительно важно. Если вы добавляете классы, а команда всё ещё не может ясно объяснить правило — остановитесь и уменьшите модель.
Можно ли моделировать только один рабочий процесс вместо всего бизнеса?
Да, и зачастую это лучший ход. Выберите один запутанный рабочий процесс, например возвраты или изменения планов, назовите рискованные решения внутри него и оставьте остальное в покое, пока не появятся реальные проблемы.
Какие ошибки чаще всего отнимают больше всего времени?
Чаще всего команды торопятся, копируя большие паттерны раньше времени или моделируя каждое существительное, которое услышали. Они также смешивают поток страницы с бизнес‑правилами и тратят время на имена и слои, пока рискованное решение остаётся разбросанным по файлам.
Как тестировать эти правила?
Пишите тесты вокруг решений, которые могут стоить вам денег или доверия. Используйте реальные примеры — например возврат после 30 дней или доступ премиум‑аккаунта до подтверждения оплаты — чтобы новый разработчик быстро увидел правило и мог безопасно его изменить.
Когда стоит просить внешнюю помощь?
Привлекайте помощь, когда одна и та же проблема с биллингом, правами или рабочим процессом повторяется, и никто не знает, где должно жить правило. Короткий обзор от опытного CTO или советника может уберечь вас от построения большой модели вокруг неверной проблемы.