在阅读DDD - Modifications of child objects within aggregate和Update an entity inside an aggregate之后,我仍然对聚合中实体更改的实现仍然感到困惑。据我了解,聚合根代表整个(或整个聚合),并将“命令”的更改委托给其余部分。 最后一部分,委托给其余部分,会引起一些问题。在下面的示例中,我想更改特定订单行的数量。我正在处理根“订单”,并告诉它更改由本地标识符标识的订单行的数量。 当满足所有业务规则时,可以创建一个事件并将其应用于聚合。目前,所有事件都应用于聚合根,并且我认为这是一个好习惯,因此所有命令都针对根,这会更改聚合状态。同样,聚合根是唯一一个创建事件,让世界知道发生了什么。 但是,当我应用此实现时,我遇到了一个问题,因为您注意到检查$ quantity值的业务规则位于两个类中。这是有目的的,因为我不太了解最佳地点。该规则仅适用于OrderLine类,因此不属于Order。但是,当我从Order中删除此事件时,将创建无法应用的事件,因为并非所有业务规则都得到满足。这也是不想要的。 我可以在OrderLine类中创建一个方法,例如: 将OrderLine中的方法更改为: 现在我可以将Order类中的方法更改为: 确保业务逻辑在其中,而不是在两个地方。这是一个选择,但是如果复杂度增加并且模型变大,我可以想象这些做法会变得更加复杂。 现在我要提问:
(1)您如何应对从根开始的聚合中的深层变化?
(2)当业务规则增加时(例如,最大数量为10,但在星期一增加3,对于产品X,最大数量为3)。在聚合根上为验证这些业务规则的域服务提供每个命令/方法是否是一种好习惯? 答案 0 :(得分:0) 我有一个问题,因为您注意到检查$ quantity值的业务规则位于两个类中。 从“面向对象”的角度来看, 所以这里的代码: 是消息验证的示例,您正在检查数量是否在允许的值范围内,因为通用 使用强类型语言的域建模人员通常会在这里引入一种新的类型,又名 在轻松的情况下,class Order extends AggregateRoot
{
private $orderLines = [];
public function changeOrderLineQuantity(string $id, int $quantity)
{
if ($quantity < 0) {
throw new \Exception("Quantity may not be lower than zero.");
}
$this->applyChange(new OrderLineQuantityChangedEvent(
$id, $quantity
));
}
private function onOrderLineQuantityChangedEvent(OrderLineQuantityChangedEvent $event)
{
$orderLine = $this->orderLines[$event->getId()];
$orderLine->changeQuantity($event->getQuantity());
}
}
class OrderLine extends Entity
{
private $quantity = 0;
public function changeQuantity(int $quantity)
{
if ($quantity < 0) {
throw new \Exception("Quantity may not be lower than zero.");
}
$this->quantity = $quantity;
}
}
public function canChangeQuantity(int $quantity)
{
if ($quantity < 0) {
return false;
}
return true;
}
public function changeQuantity(int $quantity)
{
if ($this->canChangeQuantity($quantity) < 0) {
throw new \Exception("Quantity may not be lower than zero.");
}
$this->quantity = $quantity;
}
public function changeOrderLineQuantity(string $id, int $quantity)
{
$orderLine = $this->orderLines[$event->getId()];
if ($orderLine->canChangeQuantity($quantity)) {
throw new \Exception("Quantity may not be lower than zero.");
}
$this->applyChange(new OrderLineQuantityChangedEvent(
$id, $quantity
));
}
1 个答案:
Order::changeOrderLineQuantity($id, $quantity)
是消息。消息具有架构,并且架构限制任何给定字段中允许的值范围是很正常的。public function changeOrderLineQuantity(string $id, int $quantity)
{
if ($quantity < 0) {
throw new \Exception("Quantity may not be lower than zero.");
}
int
基元太宽容了。ValueObject
,该模型使用范围限制对数据进行建模。// Disclaimer: PHP is not my first language
class Quantity {
public function __construct(int $quantity) {
if ($quantity < 0) {
throw new \Exception("Quantity may not be lower than zero.");
}
$this.quantity = quantity
}
// ...
}
Quantity
所理解的Orders::changeOrderLineQuantity(...)
与Quantity
是相同的域概念,OrderLineQuantityChangedEvent(...)
所理解的与{{1 }},如Quantity
所理解,因此您可以在任何地方重复使用相同的类型;因此,类型检查器可确保满足正确的约束条件。