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-тести: р95/пікове навантаження на кордоні (сервер подій/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).

Натискаючи кнопку, ви погоджуєтесь на обробку даних.