Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як обрати розмір агрегату і чому інші агрегати посилаються лише за ідентифікатором?

Велика спокуса - зробити агрегат «як в реальному світі»: клієнт з усіма замовленнями, замовлення з товарами, товари з категоріями. Вон Вернон у серії «Effective Aggregate Design» сформулював правила, чому так робити не варто.

Правило 1. Агрегат - для інваріантів, а не для зручності навігації. До агрегату входить лише те, що потрібно для перевірки правил, які мають виконуватися миттєво й разом. Якщо правило «замовлення має позиції з сумою, що дорівнює total» - позиції входять. Якщо «клієнт має не більше 3 неоплачених замовлень» - це не обов'язково причина робити всі замовлення частиною агрегату клієнта.

Правило 2. Маленькі агрегати. Великий агрегат:

  • завантажується цілком при кожній зміні - повільно;
  • блокує конкурентні зміни: два менеджери редагують різні замовлення клієнта, а оптимістичне блокування агрегату «клієнт» відхиляє одну зі змін;
  • зростає з часом - клієнт з 10 000 замовлень.

Правило 3. Посилання на інші агрегати - за ідентифікатором:

// погано: агрегат тримає інший агрегат
class Order { private Customer $customer; }

// добре
class Order { private int $customerId; }

Так межі агрегатів чіткі: змінюючи замовлення, неможливо «випадково» змінити й зберегти клієнта. Кожен агрегат завантажується й зберігається окремо.

Правило 4. Між агрегатами - кінцева узгодженість. Правило, що охоплює кілька агрегатів, виконується не в тій самій транзакції, а через доменну подію:

OrderPlaced → слухач (окрема транзакція) → оновити лічильник у Customer

Якщо бізнес погоджується, що лічильник оновиться за секунду, - це правильна межа.

Як знайти правильну межу - питання до бізнесу: «що станеться, якщо ці дві речі будуть неузгоджені кілька секунд?». Якщо «нічого страшного» - різні агрегати. Якщо «гроші списано двічі» - один агрегат чи явне блокування.

Практика в Laravel: зв'язки Eloquent ($order->customer) зручні для читання, але змінювати інші агрегати через них у методах кореня не варто. Читання - через зв'язки й запити; зміни - через корінь відповідного агрегату.

Докладніше в документації: Vaughn Vernon: Effective Aggregate Design

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання