12

When I started using DDD, I created Equals() methods in my entities that compared the ID of the entity. So two entity objects with the same ID would be considered equal.

At some point I thought about that and found that two entities in different states should not be considered equal, even when they describe the same thing (i.e. have the same ID). So now I use reference equality for my entities.

I then stumbled over this answer by Mark Seemann, where he writes

Entities are equal if their IDs equal each other.

Now, of course, I'd like to know which approach is better.

Edit: Note that the question is not whether having two instances of the same entity at the same time is a good idea. I'm aware that in most situations it is probably not.

Community
  • 1
  • 1
theDmi
  • 17,546
  • 6
  • 71
  • 138
  • Why you have the same entity in two different states? – BAD_SEED Jul 21 '15 at 07:55
  • 1
    How can the same instance be at a different state at the same time? – Roumelis George Jul 21 '15 at 07:57
  • @marianoc84 That could happen e.g. in a desktop application where objects typically live longer than in a web app. The user could update an entity in memory, and reading it again from the DB returns the old version. – theDmi Jul 21 '15 at 07:59
  • 1
    @RoumelisGeorge Of course they would not be the same instance, otherwise the whole discussion would not make much sense. – theDmi Jul 21 '15 at 08:00
  • So your question is about whether you should treat an out-of-date entity as equal with the updated version of it. I think that an entity is defined by it's id by definition. – Roumelis George Jul 21 '15 at 08:06
  • I believe that it depends on why you are comparing the two instances? Why does it matter in your use case? Entities are usually not used directly as view models. Therefore, it makes very little sense to keep them around after a command gets processed and within that scope, you would never have two instances of the same entity. – plalx Jul 21 '15 at 14:48

3 Answers3

8

The question is twofold. First, what you really want to know is

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

C# for example imposes you that any new concept you define inherit a certain set of public methods. Java includes even more methods.

I've never heard a domain expert talking about hash codes or instance equality, but this is one of those situations when the (often misunderstood) quote "don't fight the framework" from Evans apply: just teach developers to not use them when they do not belong to domain's interfaces.

Then, what you want to know is

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

Start with why! You know that entities are terms of the ubiquitous language that are identifiable.

But WHY?

Plain simple: entities describe concepts whose evolution in time is relevant in the context of the problem we are solving!

It is the relevance of the evolution that defines the entity, not the other way around! The identity is just a communication tool to keep track of the evolution, to talk about it.

As an example think about you: you are a person with a name; we use your name to communicate about your interactions with the rest of the world during your life; still, you are not that name.

Ask yourself: why I need to compare domain entities? Is the domain expert talking this way? Or I'm just using a DDD parlance to describe a CRUD application that interact with a relational database?
To me, the need to actually implement Equals(object) or GetHashCode() into an entity looks like a smell of an inadequate infrastructure.

Giacomo Tesio
  • 7,144
  • 3
  • 31
  • 48
  • 1
    Now this answer contains some thorough reasoning, that's what I was looking for! – theDmi Jul 24 '15 at 10:12
  • +1, could you explain what you mean by: "a smell of inadequate infrastructure"? I have asked a similar question here if you would like to answer: "https://softwareengineering.stackexchange.com/questions/364895/entity-and-value-object-are-not-part-of-the-ubiqtious-language-should-this-stop" – w0051977 Jan 30 '18 at 14:37
  • @w0051977 [this answer](https://softwareengineering.stackexchange.com/a/364909/83461) summarize well my opinion. I distinguish contracts (entities' interfaces, exceptions, value objects, domain services' interfaces) in a dll, implementations (entities' poco/pojo) in another and infrastructure (orm mappings, event stores and often domain services' implementations) in another one. This for each bounded context. If you want some info about my methods give a look at the [Epic's manual](http://epic.tesio.it/doc/manual/manual.html). – Giacomo Tesio Jan 31 '18 at 21:31
6

Entities shouldn't be compared like that, in the first place. There is no valid use case (outside testing, but then again the assertion library should handle this for you) to see if 2 entities are equal using the object's Equals method.

What makes an Entity unique is its Id. The purpose of the id is to say 'this very entity is different from other entities despite having identical properties/values'.

That being said, in a Domain you might need to compare a concept instance with another instance. The comparison is done according to Bounded Context (or even Aggregate) specific Domain rules. It doesn't matter an entity is involved, it could have been a value object as well.

Basically the 'comparison' should be a Domain use case which will be probably implemented as a service. This has no relation to an object's Equals method, which is a technical aspect.

When doing DDD, don't think like a programmer (i.e technical aspects) think like an architect (high level). Code, programming language etc is just an implementation detail.

MikeSW
  • 16,140
  • 3
  • 39
  • 53
5

I think it's bad idea to have the two separate instances of the same entity in different states. I can't think of a scenario where that would be desirable. Maybe there is one? I believe there should only ever be one instance of a given entity with a particular ID.

In general I'd compare their equality using their IDs.

But if you wanted to check if they are the same object reference then you could just use:

        if (Object.ReferenceEquals(entityA, entityB))
        {
            DoSomething();
        }
David Masters
  • 8,069
  • 2
  • 44
  • 75
  • I agree that it is not a desirable situation to have two instances of the same entity. But then, why bother and creating an Equals implementation that compares by ID? – theDmi Jul 21 '15 at 08:13
  • I think the reason for doing so is to make a distinction between value objects and entities when you are comparing them. For example, when you compare value objects like: `if (vo1 == vo2)` then it should be comparing the values of their properties. But if you did the same for entities: `if (e1 == e2)` then it should check IDs. If you didn't implement the equals overrides, then the calling developer would need to know whether to manually check IDs or property values depending on the object type (entity or value). But by implementing the overrides, they don't need to worry. – David Masters Jul 21 '15 at 08:24