Uniqueness validation in CQRS Architecture

Note: This post is copied almost verbatim from a comment I left on Jérémie Chassaing’s blog, my apologies if you’ve seen it there already!

I’ve really enjoyed reading a series of posts on CQRS written by Jérémie Chassaing. One  I particularly like the idea that there is no such thing as global scope:

Even when we say, “Employee should have different user names”, there is a implicit scope, the Company.

What this gives us is the ability to identify potential Aggregate Roots in a domain – in the above relationship, there is potentially a Company Aggregate Root in play.

Another observation Jérémie’s post really got me thinking.

Instead of having a UserName property on the Employee entity, why not have a UserNames key/value collection on the Company that will give the Employee for a given user name ?

If I’ve understood Udi’s posts on CQRS, I think he’d probably advocate the collection of Usernames being part of the Query-side, rather than the Command side. I’ve heard him mention before that the query side is often used to facilitate the process of choosing a unique username – the query store may check the username as the user is filling in the "new user" form, identifying that a username already exists and suggesting alternatives.

Of course this approach isn’t bullet-proof, and it will still remain the responsibility of another component to handle the enforcing of the constraint.

The choice of WHERE to put this logic is a question that is commonly debated.

Some argue that since uniqueness of usernames is required for technical reasons (identifying a specific user) rather than for business reasons, this logic falls outside of the domain to handle.

Others may argue that this logic should fall in the domain – perhaps under a bounded context responsible managing user accounts.

In either case, since we have a technical problem (concurrency conflicts) and  we have several possible solutions, the decision of whether on not they are suitable should probably constrained in conjunction with the expected frequency of the problem occurring. This sounds to me like the kind of thing that would appear in a SLA.

The solution chosen to enforce the uniqueness constraint will then depend on the agreed SLA. Perhaps it is acceptable that a command may fail (perhaps due to the RDBMS rejecting the change) on the few cases of concurrency conflicts – it might only be on a 0.0001% of cases.

Alternatively we may decide that it is unacceptable to allow this to occur due to the frequency of this occurring. We could choose to maintain the list of usernames in the Company aggregate, but scale out our system such that all "new user" requests in the username range A-D are handled by a specific server. If we decide to enforce this constraint outside of our domain, we can offload this work to occur with the command handlers.

What do you think?

Advertisements

About craigcav

Craig Cavalier works as a Software Developer for Liquid Frameworks in Houston Tx, developing field ticketing and job management solutions for industrial field service companies.

Posted on July 1, 2010, in Uncategorized. Bookmark the permalink. 1 Comment.

  1. Although I understand the idea of uniqueness within a context, it feels like a work-around for a limitation of CQRS, and would leave you with a number of specialised aggregate roots which are little more than indexes.

    Uniqueness is not really an issue for the Domain, as we always have a machine readable unique value: the Id. So generally speaking, uniqueness is for human readable values, and is therefore a concern for the read store.

    For most issues we could introduce the concept of nearly unique values. The user would be able to use nearly unique, human readable keys, and whenever the system detects a violation of uniqueness it would insert a disambiguation page. The user then has the option of either resolving the ambiguous references or proceeding with the machine readable id.

    This would handle most uniqueness situations, such as human-readable URLs or lookups.

    Uniqueness is also contextual. The disambiguation of a username, for example, would be perfectly acceptable when an admin is performing a lookup, but not acceptable when a user is trying to login, as the feedback could be useful to hackers. So again, this feeds the argument that this should be handled in the SLA. Even for the latter example there is an answer that is in the read store. We can combine the username and password before handling ambiguity, within the context of the login operation. Ambiguity will then be handled by only allowing the oldest record to proceed. Newer records will be forced to be renamed, and made to go through the login process again to resolve any other possible ambiguities caused by the rename.

    None of this has required we handle ambiguity in the domain, and therefore has completely removed the problems it causes.

    What do you think of that?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: