Oop 购物情境建模
我想以DDD的方式编写我的第一个应用程序(电子商务),我想知道我是否一切正常,所以我想知道你对我的建模的意见-如何改进,我应该寻找什么等。每一个反馈都将非常感谢 我已经将我的应用程序划分为几个有界上下文(目录、购物、订购),下面的示例基于购物上下文。我也在尝试使用CQRS(因此Oop 购物情境建模,oop,design-patterns,domain-driven-design,modeling,cqrs,Oop,Design Patterns,Domain Driven Design,Modeling,Cqrs,我想以DDD的方式编写我的第一个应用程序(电子商务),我想知道我是否一切正常,所以我想知道你对我的建模的意见-如何改进,我应该寻找什么等。每一个反馈都将非常感谢 我已经将我的应用程序划分为几个有界上下文(目录、购物、订购),下面的示例基于购物上下文。我也在尝试使用CQRS(因此AddProductToCart命令) 我的业务要求如下: 客户应该能够将产品添加到他的购物车中 添加产品的价格应针对用户,并基于以下几个因素:(全球折扣、用户折扣和客户国家(一些国家降低了基准价格) 我认识了以下参与
AddProductToCart
命令)
我的业务要求如下:
- 客户应该能够将产品添加到他的购物车中
- 添加产品的价格应针对用户,并基于以下几个因素:(全球折扣、用户折扣和客户国家(一些国家降低了基准价格)
/**
*具有唯一购物车的客户(聚合根)
*/
类客户
{
/**
*@var int
*/
私人$customerId;
/**
*@var字符串
*/
私人$国家;
/**
*@var-Cart
*/
私人$cart;
/**
*@var PriceProvider
*/
私人供应商;
/**
*以用户特定的价格将产品添加到客户购物车
*
*@param$productId
*@returncartline
*/
公共函数addProductToCart($productId)
{
$price=$this->priceProvider->priceForProduct($productId,$this->customerId,$this->country);
返回$this->cart->addLine($productId,$price);
}
}
/**
*用于持久化目的的简单CartLine对象
*/
类CartLine
{
公共$productId;
公帑(元);;
公费$cartId;
函数构造($cartId,$productId,$price)
{
$this->cartId=$cartId;
$this->price=$price;
$this->productId=$productId;
}
}
班车
{
私人$cartId;
公共函数addLine($productId,$price)
{
返回新的CartLine($this->cartId,$productId,$price);
}
}
/**
*提供特定国家/地区的价格
*/
类价格提供者
{
产品的公共函数价格($productId、$userId、$country)
{
//为客户确定产品价格的逻辑
//基于可用的全球折扣、用户折扣和国家/地区
}
}
/**
*用于将产品添加到购物车的命令
*/
类AddProductToCart
{
public$customerId;
公共$productId;
}
/**
*将所有内容绑定在一起的应用程序服务
*/
类客户服务
{
公共函数addProductToCart(addProductToCart$命令)
{
/**@var Customer$Customer*/
$customer=$this->customerRepository->customerfid($command->customerId);
$cartLine=$customer->addProductToCart($command->productId);
$this->cartLineRepository->save($cartLine);
}
}
这是一种正确的方法吗?我是否违反了DDD原则?我可以改进一些东西吗?CQRS通常涉及命令处理程序
命令与“命令式”动词相关联。
CustomerService
过于宽泛,因此不代表“命令”的意图
我将通过AddProductToCart
更改CustomerService
:
class AddProductToCart
{
public function handle(AddProductToCartCommand $command) {
...
}
}
顺便说一句,通过将您的各种功能拆分为适当的命令,您可以在需要时为一个特定命令制作多个版本。因此,以稀疏顺序排列(部分取决于编程语言):
- 您的聚合根应该被显式标记(例如使用IAggregateRoot接口),因此如果您的语言支持泛型,那么您只能实现聚合根的存储库
- 您的构造函数应始终是私有的,请改用factory。仅在初始化问题上使用构造函数。在下一个将来,
客户的构建规则可能会增加复杂性,factory将允许您灵活使用
- 不变逻辑是域逻辑。依赖于用例的逻辑是应用程序逻辑(即,
r与域逻辑无关)PriceProvide