domain-driven-design - DDD : keep a link to an entity inside an aggregate root, 仅用于报告

标签 domain-driven-design entity-relationship aggregate ddd-repositories aggregateroot

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

我有一个 Store,其中包含 ProductOption 列表和 Product 列表。一个 ProductOption 可以由多个 Product 使用。这些实体似乎非常适合 Store 聚合。

然后我有一个 Order,它暂时使用 Product 来构建其 OrderLine:

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 之外没有任何意义,并且不需要任何存储库;我觉得很奇怪。

欢迎任何评论!

最佳答案

尽管它只是用于“报告”,但仍然具有业务/域的含义。我认为你的设计很好。尽管我不会通过存储 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 订单”。

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

关于domain-driven-design - DDD : keep a link to an entity inside an aggregate root, 仅用于报告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7429515/

相关文章:

Laravel ER 图生成器 getAllModelsFromEachDirectory()

database - 多值属性可以具有复合属性吗?

elasticsearch - 如何使用ElasticSearch处理聚合?

MongoDB Aggregate如何配对相关记录进行处理

r - 合并矩阵中具有相同列名的列

java - session 和邀请/如何在 DDD 上下文中建模邀请机制?

model - 域逻辑泄漏到其他层?

domain-driven-design - 值对象可以有行为吗?

c# - 此 DDD 应用程序中有哪些聚合?