2

我正在使用 DDD 重构一个项目,但我担心不要让太多实体成为自己的聚合根。

我有一个Store,它有一个ProductOptions 列表和一个Products 列表。AProductOption可以被几个Products 使用。这些实体似乎Store非常适合总体。

然后我有一个Order,它暂时使用 aProduct来构建它OrderLine的 s:

class Order {
    // ...
    public function addOrderLine(Product $product, $quantity) {
        $orderLine = new OrderLine($product, $quantity);
        $this->orderLines->add($orderLine);
    }
}

class OrderLine {
    // ...
    public function __construct(Product $product, $quantity) {
        $this->productName = $product->getName();
        $this->basePrice = $product->getPrice();
        $this->quantity = $quantity;
    }
}

目前看来,DDD 规则受到尊重。但我想添加一个要求,这可能会违反聚合规则:商店所有者有时需要检查包含特定产品的订单的统计信息。

这意味着基本上,我们需要在 OrderLine 中保留对 Product 的引用,但这绝不会被实体内的任何方法使用。在查询数据库时,我们只会将此信息用于报告目的;因此,由于此内部引用,不可能“破坏” Store 聚合中的任何内容:

class OrderLine {
    // ...
    public function __construct(Product $product, $quantity) {
        $this->productName = $product->getName();
        $this->basePrice = $product->getPrice();
        $this->quantity = $quantity;

        // store this information, but don't use it in any method
        $this->product = $product;
    }
}

这个简单的要求是否要求 Product 成为聚合根?这也将级联到 ProductOption 成为聚合根,因为 Product 对它有引用,因此导致两个聚合在 Store 之外没有任何意义,并且不需要任何存储库;我觉得很奇怪。

欢迎任何评论!

4

2 回答 2

3

即使它是用于“仅报告”的,那里仍然有业务/领域的含义。我觉得你的设计很好。虽然我不会通过存储OrderLine -> Product参考来处理新要求。我会做一些类似于你已经对产品名称和价格所做的事情。您只需要在订单行中存储某种产品标识符 ( SKU ?)。此标识符/SKU 稍后可以在查询中使用。SKU 可以是 Store 和 Product 自然键的组合:

class Sku {
    private String _storeNumber;
    private String _someProductIdUniqueWithinStore;
}

class OrderLine {
    private Money _price;
    private int _quantity;
    private String _productName;
    private Sku _productSku;
}

这样您就不会违反任何聚合规则,并且可以安全地删除产品和商店,而不会影响现有或存档的订单。而且您仍然可以收到“来自 StoreY 的 ProductX 订单”。

更新:关于您对外键的关注。在我看来,外键只是一种在数据库级别强制执行长期域关系的机制。由于您没有域关系,因此您也不需要执行机制。

于 2011-09-16T03:43:03.977 回答
0

在这种情况下,您需要与聚合根无关的报告信息。

因此,最适合它的地方是服务(如果它与业务相关,则可以是域服务,或者更好地与应用程序服务相关,例如查询所需数据并将它们作为可定制的 DTO 返回以供演示或消费者使用。

我建议您创建一个统计服务,使用只读存储库(或更好的查找器)查询所需数据,该存储库返回 DTO,而不是使用查询模型破坏域。

检查这个

于 2011-09-15T11:58:11.807 回答