GH GambleHub

Bounded Context и границы домена

Bounded Context (BC) — это четкая граница, внутри которой действует единый Ubiquitous Language, согласованные модели и инварианты. Внутри границы термины однозначны («Ставка», «Клиент», «Лимит»), а наружу контекст общается контрактами (событиями/командами) и не тянет внутрь чужие смысловые «хвосты». Грамотно выбранные границы снижают связность, упрощают масштабирование и ускоряют эволюцию продукта.

1) Зачем нужны границы

Снижение когнитивной нагрузки. Команда работает с одной моделью и одним языком, а не с «всем бизнесом сразу».
Изоляция инвариантов. Критичные правила (баланс ≥ 0, уникальность логина) живут в одном месте и защищены агрегатами.
Управление изменениями. Эволюция схемы/правил внутри BC не ломает соседа — есть явные контракты.
Производительность и надежность. Внутри BC можно выбрать подходящую модель согласованности и хранилище; снаружи — асинхронные проекции.

2) Как выявлять Bounded Context

Быстрый метод (workshop 2–4 часа):

1. Event Storming: выпишите доменные события «что произошло», затем команды «что просим сделать», затем агрегаты «кто гарантирует правило».

2. Кластеры языка: где слова и правила стабильно совпадают — потенциальный BC. Где слово «Клиент» значит разное (плательщик vs игрок) — там явно разные контексты.

3. Инварианты и ownership: что нельзя нарушить и кто отвечает? Инвариант → внутрь того BC, который может его гарантировать.

4. Поток ценности: сгруппируйте шаги, которые часто меняются вместе — это кандидаты на один BC.

5. Орг-структура: если одну часть делает отдельная команда с отдельными KPI — вероятно, это отдельный BC (но не наоборот: оргструктура не должна слепо диктовать модель).

Сигналы границы:
  • Спор о терминах («ставка», «билет», «раунд» — разные смыслы).
  • Самый горячий инвариант «протекает» через сервисы.
  • Разные SLO и темп изменений.
  • «Dual-write» между модулями ради атомарности.

3) Типичные контексты (пример предметной области)

Identity/KYC — регистрация, уровни верификации, статусы ограничений.
Wallet/Ledger — балансы, проводки, резервы, валюты.
Betting/Orders — прием, котировки, расчет.
Game/Round — жизненный цикл раунда, результаты.
Bonus/Promo — начисления, вейджер, конверсия.
Payments — депозиты/выводы, статусы платежных шлюзов.
Compliance/Reporting — отчеты, аудит, регуляторные витрины.
Catalog/Provider Integration — игры, версии, статусы провайдеров.
Analytics/Read Models — проекции и материализованные представления.

💡 Это не микросервисы «по одному классу». Один BC может быть одним сервисом или модульным монолитом с четким интерфейсом.

4) Context Map: как BC взаимодействуют

Карта контекстов фиксирует тип отношений:
  • Customer–Supplier. Один BC (Supplier) поставляет события/данные, другой (Customer) подстраивает свои модели.
  • Conformist. Customer принимает язык и модель Supplier как есть (например, нормативный реестр).
  • Partnership. Два BC синхронно эволюируют язык и контракты (часто – одна команда/roadmap).
  • Shared Kernel. Общий минимальный подъязык/библиотека, версионируется совместно; использовать осторожно.
  • Anti-Corruption Layer (ACL). Защитный слой, переводящий чужие модели в свой язык.
  • Open Host Service / Published Language. Публичные протоколы/схемы, версионируемые и документированные.

Практика: по умолчанию используйте ACL и асинхронные события; Conformist — только если провайдер диктует стандарт, Shared Kernel — минимально и осознанно.

5) Граница = язык + модель + инварианты + хранилище

Внутри BC определите:
  • Ubiquitous Language. Словарь терминов с примерами.
  • Агрегаты и инварианты. Кто «держит» правила и какие операции разрешены.
  • Модель согласованности. Strong/CP для денег, EC/causal для витрин.
  • Хранилище и индексы. Выбираются под инварианты и SLO.
  • Контракты выхода. События/команды, версии схем, SLO доставки.

Снаружи: никаких прямых SQL/табличных зависимостей. Общение — через контракт.

6) Границы и согласованность (PACELC)

Внутри BC: выбирайте модель под инварианты (Wallet — Strong, Betting — Strong на приеме).
Между BC: чаще всего eventual через события и проекции. Если нужна синхронная проверка — явная команда с дедлайном и отказом при недоступности (не «скрытый» REST-зов).

7) Антикоррупционный слой (ACL)

Задача ACL: не пустить чужой язык и «грязные» данные внутрь BC.

Маппинг схем: внешнее `PaymentStatus=SETTLED` → внутреннее `LedgerEntry(type=Credit, reason=PsPSettle)`.
Валидация и обогащение: проверка инвариантов, нормализация таймзон, валют.
Версионирование: поддержка `schema_version` внешнего контракта, обратная совместимость.
Идемпотентность: по `external_id`/`operation_id`.
Наблюдаемость: трейс-теги `source`, `schema_version`, `mapping_id`, DLQ для «ядовитых» сообщений.

8) Границы и данные: владение, проекции, API

Ownership: кто владеет «истиной»? Только владелец меняет запись. Остальным BC — read-модели и ссылки.
Проекции: денормализованные таблицы под чтения; обновляются из событий.
API: команды (мутируют у владельца) и запросы (читают проекции). Никаких «сквозных» апдейтов чужих данных.

9) Эволюция и версии

События и API — с `schema_version` и политикой совместимости (additive + fallback).
Blue/Green по BC: новый контракт `v2` публикуется параллельно `v1`, трафик переводится постепенно.
Миграции: для серьезных изменений — новая проекция/сервис, «двухфазный свитч» чтений.

10) Тестирование границ

Contract tests: проверка, что BC соблюдает публикуемый контракт (producer tests) и корректно понимает чужой (consumer tests).
Property-based: инварианты агрегатов внутри BC (баланс, лимиты, уникальности).
Chaos на интеграциях: задержки, out-of-order, дубликаты, schema-evolution; наличие DLQ и безопасного редрайва.
NFR-тесты: p95/пиковая нагрузка на границе (сервер событий/ACL).

11) Наблюдаемость и SLO по границам

Метрики: throughput событий/команд, `projection_lag_ms`, `dlq_rate`, ошибки маппинга, p95 API.
Трейсинг: обязательные теги `bc`, `tenant_id`, `event_id`, `operation_id`, `schema_version`.
Алерты: превышение лага проекций, рост отказов команд, «флап» схемы (много `schema_mismatch`).

12) Мульти-тенант и регионы

`tenant_id` — в ключах всех событий и проекций на границе.
Fairness: лимиты на публикации/редрайв per tenant, чтобы «шумный» не срывал SLO соседей.
Residency: данные BC живут в «домашнем» регионе; кросс-регионально — агрегаты/отчеты.

13) Анти-паттерны (к чему приводит размытая граница)

Гигантский «core-service». Все в одном месте → борьба за транзакции, длинные релизы, низкая автономность.
Табличные интеграции. Прямые SELECT в чужие таблицы → хрупкость и coupling по схеме.
Dual-write. Одновременно писать в два BC «для удобства» → расхождения и саботаж инвариантов.
Conformist по умолчанию. «Приняли чужую модель как есть» → утечка чужих смыслов, невозможность эволюции.
Скрытые синхронные вызовы. REST-зов «где-то внутри» без явного контракта и дедлайна → неожиданная зависимость по доступности.

14) Пример контуров (словесная схема)


[Wallet/Ledger] <--CP, Leader, Transactions-->
publishes: WalletReserved/Committed v
[Betting] <--CP on bid taking-->
events: BetPlaced/Settled v
[Read Models/Analytics] <--EC projection-->

[Payments] --ACL--> [Wallet/Ledger]
[Provider Integration] --ACL--> [Game/Round]
[Compliance] <-events - [KYC/Identity], -> reports [Reporting]

15) Мини-гайд по выбору границы

1. Сформулируйте инварианты и определите, кто их может гарантировать.
2. Опишите словарь (10–20 терминов) и проверьте, что у команды одно понимание.
3. Нарисуйте Context Map и типы отношений.
4. Решите модель согласованности внутри и на стыках.
5. Спроектируйте контракты (события/команды) и ACL.
6. Запланируйте наблюдаемость (метрики/трейсинг/алерты) и DLQ/редрайв.
7. Проведите contract-tests и «шторма» (chaos) для интеграций.
8. Зафиксируйте governance: кто владеет языком/схемой, как вносятся изменения.

16) Чек-лист перед продом

  • У каждого BC есть словарь, агрегаты и инварианты.
  • Определены отношения на Context Map и документированы контракты.
  • Интеграции через события/команды и ACL, нет прямых SQL-зависимостей.
  • Идемпотентность команд/событий; есть outbox/inbox и DLQ.
  • Модель согласованности (внутри/между BC) зафиксирована и протестирована.
  • Версионирование схем и стратегия совместимости (v1/v2).
  • Метрики лага/ошибок/производительности и алерты настроены.
  • Политики мульти-тенантности и data-residency соблюдены.
  • Операционные плейбуки: schema-mismatch, redrive, rebuild проекций.

17) Быстрые рецепты

Деньги и лимиты: отдельный BC с CP и транзакциями, API только командами, события как исход истины для чтений.
Фиды/каталоги: BC с EC, проекции и кэш, явный `freshness`.
Интеграции с внешними провайдерами: всегда через ACL, события/команды, версионирование схем.
Рост команды: один BC — одна команда, у команды есть «владелец языка» и «хранитель инвариантов».
Рефакторинг монолита: сначала контракты и ACL, потом физическое разделение.

Заключение

Bounded Context — это не только диаграмма, а рабочий договор о языке, правилах и способе эволюции. Четкие границы уменьшают связность, ускоряют изменения и делают систему предсказуемой в эксплуатации. Разделяйте по смыслу и инвариантам, защищайте границы ACL и контрактами, измеряйте все метриками — и ваша архитектура останется гибкой и надежной даже при стремительном росте домена и команды.

Contact

Свяжитесь с нами

Обращайтесь по любым вопросам или за поддержкой.Мы всегда готовы помочь!

Telegram
@Gamble_GC
Начать интеграцию

Email — обязателен. Telegram или WhatsApp — по желанию.

Ваше имя необязательно
Email необязательно
Тема необязательно
Сообщение необязательно
Telegram необязательно
@
Если укажете Telegram — мы ответим и там, в дополнение к Email.
WhatsApp необязательно
Формат: +код страны и номер (например, +380XXXXXXXXX).

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