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()
看起来像是基础设施不完善的味道。
当我开始使用 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()
看起来像是基础设施不完善的味道。