Subdomain и Bounded Context: как не перепутать границы
Из статьи вы поймёте разницу между Subdomain и Bounded Context и получите практический способ проверить границы моделей в своём проекте.
Subdomain и Bounded Context легко перепутать: оба понятия описывают границы, часто получают одинаковые названия и выглядят на схемах как одинаковые прямоугольники. Поэтому сложно понять, где заканчивается часть бизнеса и начинается архитектурное решение.
Путаница становится практической проблемой, к примеру, когда «Заказы» обозначают одновременно бизнес-процесс, модуль, таблицу и будущий микросервис. Команда делит систему по структуре кода и протаскивает одну модель туда, где одинаковые термины имеют разные значения.
Из статьи вы поймёте разницу между Subdomain и Bounded Context и получите способ проверить границы моделей в своём проекте.
Поддомены и контексты описывают разные области
Subdomain. Часть бизнеса с собственной задачей и правилами. Для платформы доставки это может быть приём заказов, назначение курьеров или расчёт выплат. Поддомен существует независимо от архитектуры: после замены монолита сервисами бизнес-задача остаётся.
Bounded Context. Явная граница, внутри которой термины и правила модели имеют согласованное значение. Это проектное решение. Контекст можно реализовать модулем монолита, отдельным сервисом или несколькими компонентами под общим владением. Отдельная база данных не обязательна.
Поддомены описывают бизнес, Bounded Context — границы моделей. Основной ориентир — соответствие 1:1.
Верхняя часть схемы описывает бизнес, нижняя — границы моделей в программном решении.
Один термин, разные модели
Один объект можно моделировать по-разному, если меняются цели и правила. Для бухгалтерии сотрудник получает зарплату, для службы безопасности — имеет права доступа. Обе модели называются Employee и используют один Id, но содержат разные данные и поведение.
Одинаковый идентификатор связывает данные, но правила и модели остаются разными.
Без контекстов. Команда получила бы общий Employee с зарплатой, бонусом, признаком активности, уровнем доступа и сроком действия пропуска. Часть полей не нужна каждому сценарию, а изменение правил безопасности заставляет проверять код расчёта выплат. Похожие признаки IsActive и IsSuspended описывают разные причины, но в общей модели легко начинают влиять друг на друга.
Вот модель Employee в контексте Payroll. Она хранит только состояние, которое влияет на выплату: оклад, бонус и признак действующего трудового договора.
namespace Payroll;
public sealed record Employee(
Guid Id,
decimal MonthlySalary,
decimal MonthlyBonus,
bool IsActive)
{
public decimal CalculateMonthlyPay()
{
if (!IsActive)
{
return 0m;
}
return MonthlySalary + MonthlyBonus;
}
}
Метод отвечает на один вопрос Payroll: сколько начислить сотруднику за месяц.
А это Employee в контексте Access Control. Здесь важны уровень доступа, блокировка пропуска и срок его действия.
namespace AccessControl;
public enum AccessLevel
{
Office,
ServerRoom
}
public sealed record Employee(
Guid Id,
AccessLevel Level,
bool IsSuspended,
DateTime AccessValidUntil)
{
public bool CanEnterServerRoom(DateTime now)
{
return !IsSuspended
&& Level == AccessLevel.ServerRoom
&& now <= AccessValidUntil;
}
}
Метод отвечает на вопрос Access Control: можно ли пропустить сотрудника в серверную сейчас. Payroll не зависит от правил пропуска, а Access Control — от формулы начисления. При обмене контексты передают Id и необходимые факты, а не общий класс Employee.
Поддомены обнаруживают, контексты проектируют
Поддомены ищут через бизнес-цели, решения, правила, события и конфликты терминов. Признаки границы:
меняется бизнес-цель;
меняются эксперты и владельцы правил;
то же слово получает другой смысл;
у процесса свой ритм изменений и ограничения;
события образуют отдельный связный процесс.
Интервью, пользовательские сценарии и Event Storming дают гипотезу о поддоменах, которую проверяют с экспертами. Результат — карта бизнес-возможностей, а не список сервисов.
Границы поддоменов находят в бизнесе, границы контекстов проектируют в решении.
Затем команда проектирует Bounded Context с учётом продуктовых команд, транзакций и стоимости интеграции. Хорошая граница сохраняет модель согласованной, а большинство изменений — локальными.
Соответствие 1:1 как рабочая гипотеза
В современной практике поддомен и Bounded Context чаще соответствуют друг другу 1:1. Компания делится на продуктовые команды, и каждая команда отвечает за бизнес-возможность, её модель, данные и контракты. Поэтому граница модели естественно следует за границей ответственности команды.
Один поддомен всё же может поддерживаться несколькими контекстами. Это оправдано, если внутри него есть модели с разными правилами, экспертами, жизненными циклами или требованиями к согласованности.
В продуктовой организации основной вариант — 1:1. Несколько контекстов нужны для действительно разных моделей.
Такое разделение увеличивает число интеграций и переводов между моделями. Поэтому начинайте с 1:1, а несколько контекстов внутри поддомена вводите только для явно различающихся моделей. На карте фиксируйте поддомен, контексты, команды-владельцы и контракты между ними.
Практический алгоритм выделения границ
Определите домен и цель системы. «Система заказов» слишком узка, если продукт управляет всей доставкой.
Соберите бизнес-сценарии, события, решения и правила.
Сгруппируйте связанные возможности в поддомены и проверьте их с экспертами.
Отметьте слова с несколькими значениями. «Заказ» для продавца, курьера и бухгалтера может требовать разных моделей.
Предложите Bounded Context для каждой модели. Начните с 1:1, затем учтите команды, транзакции и частоту изменений.
Зафиксируйте события, API, владельцев контрактов и правила перевода данных на Context Map.
Проверьте границы на недавнем требовании. Если небольшое изменение проходит через всю систему, границы стоит пересмотреть.
Не обязательно сразу создавать микросервисы. В монолите можно разделить пространства имён, модели, схемы данных и зависимости. Это даст обратную связь дешевле, чем раннее физическое разделение.
Итоги
Subdomain описывает часть бизнеса, а Bounded Context — границу модели в программном решении.
Поддомены обнаруживают вместе с экспертами, контексты проектируют.
Начинайте с соответствия 1:1 и проверяйте границы на реальных изменениях.