【问题标题】:DDD - denormalized entities as value objects with IDs?DDD - 将非规范化实体作为具有 ID 的值对象?
【发布时间】:2020-03-03 17:19:12
【问题描述】:

假设我们在仓库上下文中有一个 Order。我们有一个获得该订单的客户

虽然在 DB 中 Client 有一个 ID 和一堆参数,但我在我的 Order 中将它建模为一个值对象:

class Order extends AggregateRoot {
    private client: Client;
    private shipping: Shipping;
    private items: Array<OrderItem>;
}

class Client extends ValueObject {
    public readonly name: string;
    public readonly contactPhone: string;
    public readonly contactEmail: string;
}

我将其建模为 值对象 的原因很简单——我认为仓库并不关心客户是谁。这些数据主要用于预订快递员,在这种情况下,客户无法真正更改他的姓名或联系方式 - 这将需要调整快递员预订(此时,不妨将其视为完全不同的客户) .

现在我想知道客户端 ID(用于某些分析或可追溯性)实际上会很好。简单:

class Client extends ValueObject {
    public readonly name: string;
    public readonly contactPhone: string;
    public readonly contactEmail: string;
    public readonly clientId: DomainID; // or ClientID, not essential
}

然而,令人困惑的一点是:现在这看起来像一个实体(毕竟,我本质上是将不同上下文中的 entity 非规范化为一个 值对象 )。 “身份”在这里没有真正意义,因为在检查 Client 是否相等时,我不会关心 clientId

换句话说:出于所有实际目的,仓库关心客户身份。此外,仓库不能更改任何客户详细信息。但是,存在隐含的理解,即我们正在运送给同一个客户 - 具有相同身份的客户。

我可以将Client 建模为值对象吗?这是一个常见的陷阱吗?我只是将“值对象优于实体”规则提升到绝对水平?

【问题讨论】:

  • 它不是实体,你的想法是正确的。这只是订单创建时的一些记录细节。

标签: model domain-driven-design denormalization value-objects


【解决方案1】:

通常的答案是您通过 id 引用客户端,而不是缓存其属性

class Order extends AggregateRoot {
    private clientId: DomainID; // or ClientID, not essential
    private shipping: Shipping;
    private items: Array<OrderItem>;
}

如果您需要其他客户端属性的缓存副本来维护订单本身的完整性,您只会提取它们。

Order 中的 clientId 为您提供了在需要时获取客户端数据副本所需的钩子。这个钩子通常可以通过拥有一个域服务来实现,该服务了解如何从客户端 ID 中找到您需要的数据副本。

【讨论】:

  • 谢谢。我开始编写带有附加信息的大型编辑,并在此过程中意识到了很多事情。例如,ClientClientID 实际上可能不相关(想象为别人订购礼物)。我会将clientId 放入Order 聚合中,并将receiverClient 作为值对象。 (并与商界人士讨论命名)
【解决方案2】:

另一种方法是,您还可以在订单 AR 中保留客户字段的副本。

你可能会问为什么?

因为订单(但业务需求可能会有所不同)是在单个时间点发生的事情。如果订单在给定时间点发生在CustomerId: 1 上,则此时该客户拥有name: John DoecontactPhone: 555-abc-xyz。这才是真正重要的事情(同样:业务需求可能会有所不同,请咨询您的领域专家)。

如果客户更改他/她的namecontactPhone,您可以(也可以不 - 取决于用例)为客户的PENDING订单更新它,但不要为已完成 订单(因为为几周或几年前发生的订单更新电话号码是没有意义的)。

【讨论】:

    猜你喜欢
    • 2012-06-23
    • 1970-01-01
    • 2010-10-04
    • 2012-07-08
    • 2012-04-01
    • 1970-01-01
    • 2012-11-26
    • 2016-02-24
    • 1970-01-01
    相关资源
    最近更新 更多