Я хочу написать свое первое приложение (электронная коммерция) в стиле DDD, и я хотел бы знать, все ли я делаю правильно, поэтому мне нужно ваше мнение о моем моделировании - как его можно улучшить, что я должен искать и т. д. каждый отзыв будет принят с благодарностью.
Я разделил свое приложение на несколько ограниченных контекстов (каталог, покупки, заказ), и приведенный ниже пример основан на покупках. Я также пытаюсь использовать CQRS (таким образом, команда AddProductToCart
).
Мои бизнес-требования следующие:
- Клиент должен иметь возможность добавить товар в корзину
- Цена на добавленный продукт должна быть индивидуальной для пользователя и основываться на нескольких факторах: (глобальные скидки, скидки для пользователей и страна покупателя (в некоторых странах базовые цены снижены).
Я распознал следующих актеров (обратите внимание на комментарии к методам и классам):
/**
* A customer (Aggregate Root) having an unique cart
*/
class Customer
{
/**
* @var int
*/
private $customerId;
/**
* @var string
*/
private $country;
/**
* @var Cart
*/
private $cart;
/**
* @var PriceProvider
*/
private $priceProvider;
/**
* Adds product to customers cart with user-specific price
*
* @param $productId
* @return CartLine
*/
public function addProductToCart($productId)
{
$price = $this->priceProvider->priceForProduct($productId, $this->customerId, $this->country);
return $this->cart->addLine($productId, $price);
}
}
/**
* Simple CartLine object for persisting purposes
*/
class CartLine
{
public $productId;
public $price;
public $cartId;
function __construct($cartId, $productId, $price)
{
$this->cartId = $cartId;
$this->price = $price;
$this->productId = $productId;
}
}
class Cart
{
private $cartId;
public function addLine($productId, $price)
{
return new CartLine($this->cartId, $productId, $price);
}
}
/**
* Provides price for specific country
*/
class PriceProvider
{
public function priceForProduct($productId, $userId, $country)
{
// Logic for determining product price for customer
// Based on available global discounts, user discounts and country
}
}
/**
* Command for adding product to cart
*/
class AddProductToCart
{
public $customerId;
public $productId;
}
/**
* An application service to bind everything together
*/
class CustomerService
{
public function addProductToCart(AddProductToCart $command)
{
/** @var Customer $customer */
$customer = $this->customerRepository->customerOfId($command->customerId);
$cartLine = $customer->addProductToCart($command->productId);
$this->cartLineRepository->save($cartLine);
}
}
Это правильный подход? Нарушаю ли я здесь какие-либо принципы DDD? Могу ли я что-то улучшить?