当我开始使用DDD时,我在我的实体中创建了Equals()
方法,比较了实体的ID。因此,具有相同ID的两个实体对象将被视为相等。
在某些时候我想到了这一点,发现不同状态的两个实体不应该被认为是相同的,即使它们描述相同的事物(即具有相同的ID)。所以现在我对我的实体使用引用相等。
然后我在马克·西曼(Mark Seemann)偶然发现了this answer,他写道
如果实体的ID彼此相等,则实体是相等的。
现在,当然,我想知道哪种方法更好。
编辑:请注意,问题不是是否同时拥有同一实体的两个实例是个好主意。我知道在大多数情况下可能不是。
答案 0 :(得分:6)
首先,不应该像这样比较实体。没有有效的用例(外部测试,但是断言库应该再次处理这个),使用对象的Equals方法查看2个实体是否相等。
实体的独特之处在于其ID。 id的目的是说'尽管具有相同的属性/值,但这个实体与其他实体不同'。
话虽如此,在域中您可能需要将概念实例与另一个实例进行比较。比较是根据Bounded Context(或甚至Aggregate)特定的域规则完成的。涉及实体并不重要,它也可能是一个价值对象。
基本上,'比较'应该是一个域用例,它可能作为服务实现。这与对象的Equals
方法无关,这是一个技术方面。
在做DDD时,不要像程序员(即技术方面)那样思考像建筑师(高级别)。代码,编程语言等只是一个实现细节。
答案 1 :(得分:6)
问题是双重的。首先,你真正想知道的是
例如,C#强制要求您定义的任何新概念都继承certain set of public methods。 Java包括even more methods。如何处理X语言(或Y框架)在使用它编写域模型时所强加的术语?
我从来没有听过域专家谈论哈希码或实例平等,但这是其中一种情况,当时(通常被误解的)引用“不与埃文斯的框架”相对应:只是教开发人员不要当他们不属于域的接口时使用它们。
然后,你想知道的是
什么是实体?它与自己的身份有何关系?
从为什么开始!您知道实体是可识别的普遍存在的语言的术语。
但为什么?
简单明了:实体描述了我们正在解决的问题的上下文中时间演变 相关的概念!
定义实体的进化的相关性,而不是相反的方式!身份只是一种沟通工具,可以跟踪进化,谈论它。
作为一个例子,想想你:你是一个有名字的人;我们用你的名字来传达你在生活中与世界其他地方的互动;不过,你不是那个名字。
问问自己:为什么我需要比较域名实体? 领域专家是这样说的吗?或者我只是使用DDD用语来描述与关系数据库交互的CRUD应用程序?
对我而言,实际将Equals(object)
或GetHashCode()
实施到实体中的需要看起来像是基础设施不足的气味。
答案 2 :(得分:4)
我认为将同一实体的两个独立实例放在不同的状态是个坏主意。我无法想到一个可取的方案。也许有一个?我相信应该只有一个具有特定ID的给定实体的实例。
一般情况下,我会使用他们的ID来比较他们的平等。
但是如果你想检查它们是否是同一个对象引用,那么你可以使用:
if (Object.ReferenceEquals(entityA, entityB))
{
DoSomething();
}