2

I'm just learning DDD and a question raised in my mind about unique identifiers in an entity.

Consider this simple method that checks the uniqueness of an entity to prevent duplication:

    private bool IsDuplicate(BoardGame boardGame)
    {
        //It's either this
        if (Games.Any(x => x.Id == boardGame.Id)) return true;

        //Or this
        if (Games.Any(x => x.Name == boardGame.Name && x.Price == boardGame.Price)) return true;

        return false;
    }

The first method is very clean and readable. The problem is we usually don't have the value of Id before the item is persisted somehow because it is handled by the ORM.

The second method is the way how an object is considered unique from a domain point of view. We can evaluate this uniqueness before persisting the object But the downside is it gets messy when an entity's uniqueness becomes more complicated.

Now the question is, isn't that Id field redundant? don't we have to check this uniqueness with domain perspective anyway? why not having, say, a composite/compound key in ORM/Persistence side?

Of course this is an example. The name or price could change, but remember, I said that in the domain perspective, the name should be unique.

Consider having a Member entity, with his/her SSN as a unique identifier.

2
  • The question is, why should ID be compared to determine whether 2 boards are equals? Equals and same are semantically different comparisions. IDs are (IMO) implementation details inherited by the persistence.
    – Laiv
    Jun 15, 2019 at 22:06
  • The uniqueness of an object is rarely something relevant to one's domain. What does your domain do with a BoardGame that requires it to be unique? If the only answer to that question is "persist/retrieve it", then are we really talking about our domain anymore? Identity is a term that is most relevant when we are talking about storage. Between the moment when a BoardGame is retrieved and the moment it is persisted (i.e. during our business logic), it's uniqueness is nothing more than a persistence artifact. Methods like IsDuplicate are usually an indicator of incomplete design. Jun 18, 2019 at 20:17

2 Answers 2

1

I'm just learning DDD and a question raised in my mind about unique identifiers in an entity.

Identity, especially identity of real world objects, is much more subtly difficult than the DDD literature suggests.

In most cases, identity is really correlation. How do I get my car back from the valet? I show the valet a ticket stub with a number that matches the number he has attached to my car keys. Since the numbers match, this must be the "same" ticket, and therefore I must be the person that has claim to the car.

Gregor Hohpe's patterns work includes a discussion of correlation identifiers.

Correlation identifiers are often domain data, not something arbitrarily created by the ORM. We produce some distinguishing identifier at the beginning of a conversation, and then use that same identifier to track other contributions to the same conversation.

And yes, when you are in a domain where these identifiers may be re-used, there is the extra burden of keeping track of which "entity" the identifier is supposed to represent.

Now the question is, isn't that Id field redundant?

Only if the fields you are comparing to are immutable. Entities tend not to be immutable, but instead transition from one state to another during their lifetimes. Halloway's Perception and Action is a good overview.

1
  • Entities tend not to be immutable, Correct, but not their identities. this gets philosophical, but if I change my name, or my SSN changes, am I still the same person? in my perspective, yes, I am. but what about the services that used my name or SSN? so it depends on the domain to identify some aspects of the entity as it's identity. the broader question is, should we fetch an entity's identity from a storage just to see we have that, or we have to know its uniqueness right after creating it? Jun 18, 2019 at 19:47
0

The id uniquely identifies the BoardGame instance, and it does so independently of any data field values. Composite keys are good for maybe two reasons: readability and platform independence. As sources of identity, they are inferior in almost every other way. They take up too much storage space, and they complicate the indexing process (among other things).

Social Security Numbers are not unique. Uniqueness, and the ability to retain that uniqueness despite business rule changes and name changes, is a very difficult problem that is definitively solved by using surrogate keys instead of composites.

You can overcome the platform independence problem by using GUID strings as surrogates. As a bonus, these keys are globally unique, and you can generate them client-side.

Finally, DDD doesn't really have anything to say about your key structure, other than it should uniquely identify each entity. Key structure is an implementation detail, not a DDD design choice.

All that said, if you really want to use composites and you can get your team to agree, then by all means, make the choice and go for it.

5
  • They take up too much storage space, and they complicate the indexing process (among other things) curiously, we could say the same about GUID and UUID, at least when it comes to their respective storage.
    – Laiv
    Jun 15, 2019 at 21:58
  • @Laiv: Yep. But the benefits of GUIDs far outweigh their costs. Jun 15, 2019 at 22:44
  • @Laiv Often it is useful to apply both Jun 17, 2019 at 14:55
  • so basically, we should not COMPLETELY think about the domain and logic, persistence ignorant? Also, using GUIDs does not give us the same outcome as using those composite keys. creating a BoardGame instance gives us a new GUID, which is not the same as the name or other concerns in the domain are. Am I missing something? Jun 18, 2019 at 19:39
  • @AliBordbar: Not sure what you're trying to say there. To reiterate, keys are an implementation detail. That means that how you implement them is entirely up to you. DDD couldn't care less how you implement them. Jun 18, 2019 at 22:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.