Привет!
На небольшом pet-проекте изучаю премудрости DDD. Итак, имеется некий аналог магазина: каталог, страница товара, корзина, и т.д. Размышляя, пришёл к выводу, что понятие "Товар" в системе явно имеет как минимум два значения. В контексте каталога это больше репрезентативная модель - название, описание, картинки и т.д. В контекте покупки это уже цены, всякие программы лояльности, скидки и проч. По большому счёту, первый контекст вообще скорее обычный блог с набором страниц. Поэтому я решил выделить два независимых контекста (Bounded Context):
1. Catalog
2. Shop
В обоих контекстах есть понятие Product, реализованный одноимённым классом
namespace Acme\Catalog;
class Product {
private $id; // Это идентификатор продукта в контексте каталога
private $name;
private $description;
private $poster;
// ...
}
namespace Acme\Shop;
class Product {
private $id; // Это идентификатор продукта в контексте продаж
private $sku;
private $price;
// ...
}
Контекст Shop опирается на Catalog, поэтому ключ $id в продукте в контексте Shop суррогатный и всегда можно получить его на основе $id из контекста Catalog. Что то типа:
namespace Acme\Shop
class ShopService {
public function fromCatalogProduct($id) {
// тут строим идентификатор на основе каталожного
}
}
В принципе, такой подход вполне себе работает, когда нужно показать одну карточку товара
class ProductPageController
{
// ...
public function pageAction($id) {
$catalogProduct = $catalogRepo->get($id);
$shopId = $shopService->fromCatalogProduct($id);
$shopProduct = $shopRepo->get($shopId);
// Дальше рендерим страницу, опираясь на оба контекста
}
}
Конечно, лишний запрос дело не ахти. И при бОльшем числе контекстов, задействованных для отображения, число запросов будет расти. Но пока, например, терпимо.
А вот как поступить, когда надо отобразить страницу каталога, где много товаров. По идее, мне так же нужны оба контекста. Решения видятся такими:
- В лоб - сначала из контекста Catalog запрошиваем продукты, а потом для каждого из них из контекста Shop дёргаем цену. Минусы очевидны.
- Получше - сначала из контекста Catalog запрошиваем продукты, а потом пакетно из контекста Shop дёргаем цены. Всё равно как то не ахти смотрится.
- Отдельная модель чтения для каталога. После создания или редактирования товаров в обоих контекстах, данные сливаются в какую нибудь MongoDB базу, откуда забирается уже готовый агрегат. Тут CQRS в помощь, даже без Event Sourcing'а вроде бы. Вопрос только в создании модели чтения и поддержании её на плаву.
Есть ли у уважаемых участников сообщества мысли по этому поводу?