DDD 实体应该通过引用还是通过 ID 进行比较?

Should DDD entities compare by reference or by ID?

当我开始使用 DDD 时,我在我的实体中创建了 Equals() 方法来比较实体的 ID。所以两个具有相同ID的实体对象会被认为是相等的。

在某些时候,我想到了这一点,发现处于不同状态的两个实体不应被视为相等,即使它们描述的是同一事物(即具有相同的 ID)。所以现在我对我的实体使用引用相等性。

然后我偶然发现了 Mark Seemann 的 this answer,他在其中写道

Entities are equal if their IDs equal each other.

现在,当然,我想知道哪种方法更好。

编辑:请注意,问题不是同时拥有同一实体的两个实例是否是个好主意。我知道在大多数情况下可能不是。

我认为让同一实体的两个不同实例处于不同状态是个坏主意。我想不出一个理想的场景。也许有一个?我相信应该只有一个具有特定 ID 的给定实体的实例。

一般来说,我会使用他们的 ID 来比较他们的平等性。

但是如果你想检查它们是否是相同的对象引用那么你可以使用:

        if (Object.ReferenceEquals(entityA, entityB))
        {
            DoSomething();
        }

首先,不应该那样比较实体。没有有效的用例(在测试之外,但断言库应该再次为您处理)使用对象的 Equals 方法查看 2 个实体是否相等。

让实体独一无二的是它的 ID。 id的目的是说'this very entity is different from other entities despite having identical properties/values'.

也就是说,在域中,您可能需要 比较 一个 概念 实例与另一个实例。比较是根据限界上下文(甚至聚合)特定的域规则完成的。涉及实体并不重要,它也可能是一个值对象。

基本上 'comparison' 应该是一个域用例,它可能会作为一项服务来实现。这与对象的 Equals 方法无关,这是一个技术方面。

在做 DDD 的时候,不要像程序员(即技术方面)那样思考,像架构师(高层次)那样思考。代码、编程语言等只是一个实现细节。

这个问题是双重的。首先,你真正想知道的是

How to handle terms that the X language (or Y framework) impose when I code a domain model with it?

例如,C# 强制您定义的任何新概念继承 certain set of public methods. Java includes even more methods.

我从未听过领域专家谈论哈希码或实例相等性,但这是 Evans 的(经常被误解的)引述 "don't fight the framework" 适用的情况之一:教开发人员不要使用当它们不属于域的接口时。

那么,你想知道的是

What is an entity? How it relates to its own identity?

从为什么开始!您知道实体是可识别的通用语言的术语。

但是为什么

简单明了:实体描述的概念在上下文随时间的演变相关我们正在解决的问题!

定义实体的是进化的相关性,而不是相反!身份只是一种沟通工具,可以跟踪演变,谈论它。

举个例子想想你:你是一个有名字的人;我们使用您的名字来传达您一生中与世界其他地方的互动;不过,你不是那个名字。

问问自己:为什么我需要 比较 域实体? 领域专家是这样说话的吗?或者我只是用 DDD 的说法来描述与关系数据库交互的 CRUD 应用程序?
对我来说,需要在实体中实际实施 Equals(object)GetHashCode() 看起来像是基础设施不完善的味道。