In DDD, Entities have a value that uniquely identify them i.e. the identity. Sometimes this identity is generated by the server, sometimes is obtained from another BC, sometimes is provided by the user, and so on. Let's assume we are working in the scenario where the user provides the identity.
Let's pretend that there is a business process exclusively done on paper and not-to-be-migrated-to-computer-soon where the Process Owner decides the new name for a thing called a Resource. The name is always following a fixed schema like PROD-<today's date>-<short random string>
and is always validated between Very Important Team Members. The chosen and validated name is PROD-2021-01-04-KAH14564YUDO
, the last character being an " O " (the letter) and not a " 0 " (the number).
Let's say that an operator registers this new Resource in the system, providing the given identity but mistakingly spelling the last character as a zero, perhaps because of bad handwriting. The Entity is inserted, some other Entities are linked to it via its identity, and then someone detects the error in the identity. What should happen now?
We know that the identity of an Entity should be unique and immutable, but here it seems we need to correct (and so change) it. Introducing a surrogate identity to avoid this bad insert problem is not correct since the identity provided by the PO and validated by the Very Important Team Members is actually unique and is not to be changed, it was only inserted with an error in the management system; moreover there is no concept in the business of this surrogate identity related to the Resource.
Where is the error in this scenario?
Interesting situation. I'm assuming that you cannot add validation to the Identity
as it's just a random string entered by the user.
Let's start with the question Where is the error in this scenario?. It's an error prone mechanism or workflow in the Domain
that you are in. When you build a system for a specific domain you will have to deal with nasty stuff from that domain. You just have to catch these nasty rules or mechanisms as early as possible and design the system in a way to handle them.
Let's see how you can handle this scenario.
One thing you can do is to use another ID (an auto-generated GUID
for example) used by the system and hidden from the users. You can use it to link other entities to this one. This way if an error is detected to the Identity
entered by the user you won't have to update the whole system as the Identity
will not be used anywhere else. If you need it from another part of the system you should just make a query contains the GUID
to get the Identity
back. This will unsure that the ID is indeed immutable. Depending on the system it may be a good solution or it may complicate some parts of it and it's not always a viable solution.
If using another ID only for system use is not an option, then you just have to design it in a way to handle these situations. You will have to include updating the Identity
from the user as a use-case. Add handling of Identity
updates from every part of the system that uses this Identity
. In some cases these errors will have nasty consequences. One example is if this Identity
is send to another system or a person by e-mail and is already used somewhere else that your system doesn't have control of. In this case it's not the systems fault, it's in the Domain
and the people who use it. The only way to fix this is to change the rules and mechanisms in the Domain
. This isn't possible most of the time, but sometimes you can raise this issue and a more robust mechanism can be implemented. It's a nasty situation to be in but that's life.
Example for using natural keys
/ identity
instead of GUID.
If you have a network of systems that operate with natural keys
and their generation is robust you can use them. For example, banking systems use the International Bank Account Number (IBAN). These numbers are generated by a special schema that is robust. They are not just some random string entered by a user. In this case, the Domain has a robust mechanism that ensures that these natural keys
are valid. In this case, it's almost impossible to send a GUID to another banking system to exchange for an IBAN.
When sending money to a bank account, this IBAN is validated, so errors are easily detected. This way a person cannot send money to a non-existing bank account thus losing them just for making a typo.