13

Edit

To further clarify my initial problem, I rewrote the question with more 'DDD'-termini, common patterns and discussion arguments. The orginal version can be found under revisions.


Where and how are identities for entities/aggregate roots being generated inside the domain when correctly applying DDD?

I need to assign unique identities to my entities, either upon creation or persisting. Those identities can come in several styles

  • Computed (based on the characteristics of an entity, hence based on business requirements)
  • Natural (based on a certain set of rules, hence based on business logic)
  • Surrogates (based on randomly generated values with no business meaning)

There are many approaches for the task of generation and assignment of identities, from using factories to create identities, delegation to the infrastructure using ORM or database generation etc. However, if correctly applying DDD, where and how should identities be generated, considering that we don't want anemic domain models and injection of services into entities?

Requirements as declared above

  • No anemic domain models
  • No dependency injection of services into entities

Possible approaches

  • Factories
  • Double dispatch (can this be used for identity generation?)
  • Generation inside repositiories
  • Generation inside infrastructure (e.g. ORM or database)
  • Injection services into entities
xvdiff
  • 2,179
  • 2
  • 24
  • 47

2 Answers2

14

Vaughn Vernon author of Implementing Domain Driven Design advocates creating unique ids in repositories like this:

   public TenantId nextIdentity() {
        return new TenantId(UUID.randomUUID().toString().toUpperCase());
    }

TenantId is a value object that wraps the identity of the Entity.

Songo
  • 5,618
  • 8
  • 58
  • 96
  • I like this solution, would it be correct to replace TenantId with a simple integer value, then use a sequence table as described [here](http://stackoverflow.com/a/21267168/1271691) to get the next number ? – Jonathan Jan 21 '16 at 17:01
  • 2
    @Jonathan generally speaking using a sequence generator to return an id isn't wrong. Vaughn Vernon actually lists this as an alternative to my solution in his book. One drawback though is that you are now dependent on a certain database to generate an id. What if you decide to move to a database that doesn't have sequences or move to a noSql solution? This could all be abstracted correctly by encapsulating the call to generate the id correctly of course, so you have to weigh the pros and cons. – Songo Jan 22 '16 at 00:08
  • We have considered using GUIDs/UUIDs as IDs, however, this may not be a good choice if the underlying DB is a relational one. A lot has been written about the fragmentation GUID primary keys can cause, due to these values not being sequential, e.g. [here](https://www.sqlskills.com/blogs/kimberly/guids-as-primary-keys-andor-the-clustering-key/). Our DBAs feel quite strongly about it. – kamilk Feb 20 '20 at 10:42
12

I would place it in a factory. Generating id shouldn't be a part of domain logic in my opinion, because it's really an infrastructure matter. You can take id from DB or generate it with uuid or whatever. It's a detail. Also remember that only interface of a factory belongs to domain layer, not its implementation.

About your doubts for factory, if you use factory to create entities then you should use it everywhere. This is how I do it.

Rafał Łużyński
  • 7,083
  • 5
  • 26
  • 38
  • You have been downvoted by some user, but he (as usual) didn't left a comment. What do you think is the reason behind it? – xvdiff Sep 09 '14 at 13:12
  • 2
    +1, this is also how we do it. We're almost exclusively using UUID-based identities (wrapped in a `PersonId` class etc) everywhere now, since that spares a roundtrip to the database, i.e., they can quickly be generated from the UI side as well - really helps when you are also applying CQRS. – Alexander Langer Sep 09 '14 at 13:36
  • @xvdiff Dunno. I might be wrong with some statements, but I'm almost sure that factory is a right place for it. – Rafał Łużyński Sep 09 '14 at 14:25
  • @RafałŁużyński But then you might end up creating anemic domain models (*property bags*), e.g. when your entity does not carry any other domain logic. Also, identity generation could be specific for a single entity, so shouldn't the task of generating a certain identity be as close to the entity as possible, if not in the entity itself? – xvdiff Sep 09 '14 at 14:42
  • I don't get how id generation can be specific to one entity? You mean one type, or one instance? Factories are also specific for one entity type. Anyway, entities shouldn't have access to repositories because of SRP (single responsibility rule), so you can't really check if your id is unique in entity method, you have to check that outside. Id generating isn't a domain logic, so if your entities are anemic then it's your modelling issue. Can you provide some real model example? – Rafał Łużyński Sep 09 '14 at 15:15