How to validate command before executing on aggregate when validation needs to query data

aggregatecqrsdomain-driven-design

In a DDD designed application with CQRS principle how do we handle the case when a command needs to be validated before it is executed on an aggregate and the validation needs to query the existing data?

For instance, in my system I have Customer, Project and Ticket aggregates. A Project belongs to a specific Customer and a Ticket is opened for a specific Project.

A CreateTicket command is issued by the current customer. The system populates the command's payload with the customer_id and project_id.

Before the commands is executed on the Ticket aggregate, I need to validate that the command's project indeed belongs to the command's customer.

Another case is this. A command to create a new Department in the system is issued. A Department has a title property. Before the department is created I need to verify that there is no other department with the same title in the system. The aggregate repository does not query data. It only fetches by id, and stores aggregates.

How do we handle such cases?

Best Answer

In a DDD designed application with CQRS principle how do we handle the case when a command needs to be validated before it is executed on an aggregate and the validation needs to query the existing data?

If you need to query existing data that is already part of the aggregate, don't. Just pass the command to the aggregate, and put the logic for evaluating the current data into your domain code.

If you need to query data that exists somewhere else, then you normally will pass to the domain model something like a domain service, which gives the model the ability to access a copy of the data that it needs.

A command to create a new Department in the system is issued. A Department has a title property. Before the department is created I need to verify that there is no other department with the same title in the system.

The general term for this problem is Set Validation. Priority one is to make sure that you understand the business impact (how much does it cost the business to have a duplicate department title in your database for a minute?)

Domain models enforce set invariants by including the entire set in a single "aggregate", so that membership changes always have the data that they need to check them. In systems where the set members are being stored in a relational database, it may make sense to have the database, rather than the domain model, enforce the invariant.

When there is only a single field that you need to worry about being unique, and if for that entity the value of the field will never change, a possibility is to use that field to compute the identifier (ensuring that all requests for a specific unique key get mapped to the same instance of the aggregate).

(That's probably not a good option for something like a department name, because re-orgs are so foreseeable).