Specification, business rules satisfaction and event sourcing.

Hi.
In enterprise applications there are many cases when we need to do or omit actions in dependence of existence in the system aggregates with certain state(s).
For example, one allowed to register customer only when last one doesn’t exist, what is identified by according set of fields.

But when we use event sourcing we can not do the query into the “business DB” and load(check existence) of aggregates with needed state. Of course we can load all aggregates of type that we need and check them using Specification (DDD pattern) but it will be performance bottleneck. We also can use reporting part of application but in such way we introduce high coupling between reporting and business parts and even more if we use asynchronous events such approach will not help us.

So may be event sourcing is not good enough for enterprise applications ?

Hi Andrey,

I strongly believe that CQRS has most value in larger “enterprise” applications.

The problem you describe is in my opinion not directly related with event sourcing, but more with pure CQRS. If you need information about the state of an aggregate, you do a query. If you want to change an aggregate, you use a command. One of the base principles of CQRS, is that there is no such thing as a single view on a domain model. In practice, that means that you can easily have multiple query databases that store the same information, but in different formats. One of these formats can be very useful to verify preconditions for executing commands.

In your example, a command handler would receive a “RegisterCustomerCommand”. Based on the information in that command, it will do a query to make sure that the customer does not already exist. If it already exists, the command handler either returns in silence, or it reports a failure (depending on your business case). If none is found, a new Customer aggregate is created, and stored in the command repository. From that, a “CustomerRegisteredEvent” is generated, which causes an entry in the query database to be created. Next time the same customer is created, it is found in the query database.

Depending on you architecture, it is (theoretically) possible that an aggregate is created twice, as the (optional) asynchronous nature of CQRS could cause a short delay between the generation of events and the query database being updated. If that really, really, really (always ask your domain expert three times :wink: ) is a problem, then you could decide to use a single aggregate that contains all the customers. The most important feature of an aggregate is that it maintains full consistency at all times.

In short, the response to the remark “CQRS/Event Sourcing is not suitable for enterprise applications” would be: it surely is, but it only requires you to look for solutions in a different way than when you use (e.g) a layered architecture. Some of these solutions might look weird at first, but once you get used to them, you notice their real potential.

The aspects I described above are also the main subject in the CQRS workshop I give at the end of next month. There is a link to the workshop page on www.axonframework.org with more information.

I hope this helps.

Cheers,

Allard

What would happen if a duplicate account is created?

Really what you're asking is "What would happen if a duplicate account
is created in the window of time that it takes the transaction side to
update the query side?" Or, how much development time do you want to
invest in the case where two people attempt to register the same
account within ~250ms.

The Yahoo DDD forum waxes philosophical about this as does the DDDCQRS
Google Group.

I'm pretty new to CQRS, but my decision was to make a database table
to enforce set constraints. I have a SetConstraint interface which has
one method checkAndInsert(scope,field,value). Scope may be 'system',
or finer grained (no duplicated accounts on the system, no duplicate
phone numbers in address book, etc). I have an InMemorySetConstraint
I inject for integration tests, and a DatabaseBackedSetConstraint I'm
planning on using in production.

Callers are *required* to check the query side first, then issue the
command. The domain uses the SetConstraint to ensure uniqueness; but
the database table could be emptied any time all the event and command
queues in the system are empty.

   JAmes

Hi, Allard/JAmes.
Thank you for your answers, time and hints.
I understand your point. We will try to invent/reuse solution of this problem from this point of view.