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

the*_*Dmi 9 domain-driven-design equality

当我开始使用DDD时,我Equals()在我的实体中创建了比较实体ID的方法.因此,具有相同ID的两个实体对象将被视为相等.

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

然后,我在马克·西曼(Mark Seemann)的写作中偶然发现了这个答案

如果它们的ID彼此相等,则实体是相等的.

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

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

Mik*_*eSW 6

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

使实体与众不同的是它的Id.id的目的是说'尽管具有相同的属性/值,但这个实体与其他实体不同'.

话虽这么说,在域您可能需要比较一个概念与另一个实例的实例.根据Bounded Context(或甚至Aggregate)特定的Domain规则进行比较.涉及实体并不重要,它也可能是一个价值对象.

基本上,'比较'应该是一个域用例,它可能作为一种服务实现.这与对象的Equals方法无关,这是一个技术方面.

在做DDD时,不要像程序员(即技术方面)那样思考像建筑师(高级别).代码,编程语言等只是一个实现细节.


Gia*_*sio 6

问题是双重的.首先,你真正想知道的是

当我用它编写域模型时,如何处理X语言(或Y框架)所强加的术语?

例如,C#强加给你,你定义的任何新概念都会继承一组公共方法.Java包含更多方法.

我从来没有听过域专家谈论哈希代码或实例相等,但这是当埃文斯适用的(通常被误解的)引用"不与框架对抗"的情况之一:只是教导开发人员不要使用它们它们不属于域的接口.

然后,你想知道的是

什么是实体?它与自己的身份有何关系?

从为什么开始!您知道实体是可识别的普遍存在的语言的术语.

为什么呢?

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

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

作为一个例子,想想你:你是一个有名字的人; 我们用你的名字来传达你在生活中与世界其他地方的互动; 不过,你不是那个名字.

问问自己:为什么我需要比较域实体?领域专家是这样说的吗?或者我只是使用DDD用语来描述与关系数据库交互的CRUD应用程序?
对我而言,实际实施Equals(object)GetHashCode()进入实体的需要看起来像是基础设施不足的气味.


Dav*_*ers 5

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

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

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

        if (Object.ReferenceEquals(entityA, entityB))
        {
            DoSomething();
        }
Run Code Online (Sandbox Code Playgroud)