Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DDD - Validation of unique constraint

In DDD you should never let your entities enter an invalid state. That being said, how do you handle the validation of a unique constraint?

The creation of an entity is not a real problem. But let say you have an entity that must have a unique name and there is a thousand instances of this entity type - they are not in memory but stored in a database. Now let say you want to rename an instance.

You can't just use a setter... the object could enter an invalid state - you have to validate against the database.

How do you handle this scenario in a web environment?

like image 819
W3Max Avatar asked Apr 18 '10 02:04

W3Max


2 Answers

A uniqueness constraint can be reduced to a persistence exception, rather than being seen as an "invalid state". It's not an invalid state until the object is persisted. Uniqueness only makes much sense in the context of persistence. Realistically, you can put this kind of rule in your validation mechanism to help reduce the likelihood of this error, but in any real multiuser system, you can't be guaranteed of uniqueness until a successful unit of work completes the persistence action.

So you may want this in your validation mechanism, but you must enforce it in your persistence layer.

I'm generally a fan of DDD as a methodology, but I think that the "don't allow objects to get into invalid states" can require some tortuous abstractions. In a web application, having a separate "View Model" is one possible solution, as an intermediary layer before persistence, but I don't usually do that until I'm convinced it will cause me less pain than the simpler alternative.

like image 80
JasonTrue Avatar answered Sep 19 '22 13:09

JasonTrue


In search for an answer to your question I came across this article: https://thinkbeforecoding.com/post/2009/10/28/Uniqueness-validation-in-CQRS-Architecture.

In essence: Look for the scope of the uniqueness and store an authoritative list of unique values inside an aggregate root representing that scope.

For example, given the use case "when registering a new user, the requested login must be unique" this would be: A login has to be unique whithin a tenant (or company, or country, ...). Store the information about given logins within a list in the aggregate root representing the tenant.

This way you can make sure, that the tenant never enters an invalid state.

like image 44
Timo Verhoeven Avatar answered Sep 20 '22 13:09

Timo Verhoeven