TGViewer
Beer::Code🍺 Beer::Code🍺 @beerphp · 3.64K subscribers
Post #121 3.2K
Bounded Context

Перший крок — варто уникати створення єдиної, монолітної доменної моделі для всієї системи. Намагайтесь розділити модель і ваші обʼєкти на менші частини, кожна з яких відповідає за конкретний сценарій або контекст. Наприклад, якщо у нас є система для обробки замовлень інтернет магазину, то є обʼєкт (Order), але в різних частинах системи це слово означає різне:

Для створення замовлення важливі товари й ціна
Для оплати — номер картки й статус транзакції
Для доставки — адреса й дата

Обмежений контекст — це коли ми ділимо модель на маленькі шматочки, кожен із яких живе окремо і відповідає за конкретну задачу.

⁉️ Як це працює?

Cтворюємо окремі класи для кожного контексту. Наприклад:

OrderCreation — для створення замовлення
OrderPayment — для оплати
OrderDelivery — для доставки

Кожен із них має тільки те, що йому потрібно, і не знає про існування інших.

[golang] [php] [python] [nodejs]
final readonly class OrderCreation {

/**
* @param OrderItem[] $items
*/
public function __construct(
private OrderId $orderId,
private UserId $userId,
private array $items
) {
}

}

// Контекст оплати замовлення
final readonly class OrderPayment {
public function __construct(
private OrderId $orderId,
private Money $sum
)
{
}
}

// Контекст доставки
final readonly class OrderDelivery {
public function __construct(
private OrderId $orderId,
private Address $address
)
{
}
}

// Використання
$orderCreation = new OrderCreation(
new OrderId($this->orderIdGenerator->generate()),
new UserId($this->userId),
[
new OrderItem(new ProductId('notebook'), $quantity),
new OrderItem(new ProductId('gamepad'), $quantity),
]
);

$orderPayment = new OrderPayment(
$orderCreation->orderId(),
new Money($this->total)
);

$orderDelivery = new OrderDelivery(
$orderCreation->orderId(),
new Address(
$this->city,
$this->street,
$this->house
)
);


📍Моделі (обʼєкти, сервіси, ентіті, хендлери і т.д.) в одному обмеженому контексті мають бути тісно пов’язані (cohesion) й працювати разом для однієї мети. Наприклад, у контексті OrderCreation це може бути додавання, видалення й оновлення товарів в замолені, бо це одна бізнес-здібність.

📍В той же час контекст не має сильно залежати від інших (loose coupling). Наприклад, OrderDelivery оперує саме OrderId а не цілим Order і зовсім нічого не знає про деталі оплати.

Переваги такого підходу:
1. Код стає простішим: кожен клас маленький і зрозумілий.
2. Легше тестувати: можна окремо перевіряти кожну частинку, не чіпаючи іншу.
3. Передаємо менше даних. Наприклад, OrderPayment випадково не потягне за собою адресу доставки, бо вона йому не потрібна.

❗️ Розділені контексти - це не раз і назавжди. З часом, коли проект росте, ви можете і маєте переглядати їх. В моноліті кордони між контекстами можуть бути малопомітні, адже виклик сервіса із сусідньої папки не викликає ніяких проблем. Проте варто за цим слідкувати. Як мінімум впровадити архітектурні тести (deptrac) з описаними правилами, котрий буде запускатись разом з тестами і статичним аналізатором.

#backend #architecture #middle #source
  • 👍 31
  • 🔥 5
More from @beerphp
  1. Sep 22, 2026Anthropic випустила Opus 5.5 За словами Anthropic, на більшості задач вона працює на рівні…
  2. Sep 21, 2026Доречі, цього тижня буду проводити НОВИЙ воркшоп Harness Engineering - 24 і 26 вересня. Од…
  3. Sep 21, 2026Хочу поділитись своєю мотивацією На тому тижні був воркшоп Agentic Engineering Workflow Ко…
  4. Sep 20, 2026Post #198
  5. Sep 14, 2026Не можу не поділитись, вчора отримав такий відгук Це прям паливо заради якого хочеться про…
  6. Sep 13, 2026І знову я зі своїм воркшопом 🙂 Але перед цим - попереджаю і кажу чесно, канал і соцмережі…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →