Suppose I have an Order
Aggregate root, and when I receive command to create Order
, I should check other orders on some condition, and decline creation, if these conditions met. Checking this conditions is definitely business logic, but I should not create order at first place, while conditions are not met.
So how to implement this check that complies with DDD principles?
Is it part of domains service, application service?
EDIT:
There is TableId property in Order
.
For example I need to check if table is already taken, and if it is, decline order creation. This table service may reside in another AppDomain, and network call maybe needed.
I'm using Event sourcing, CQRS, Command Handlers. Sorry I can't post a code.
So how to implement this check that complies with DDD principles?
"It depends".
If you don't need everything to be perfectly consistent, then you can give your aggregate a cached copy of the other data to compute its logic. There are different patterns people use for this; using a domain service to fetch the data for you is one, returning control to the application to obtain the data for you is another...
----> create order
<---- here is a list of other information I need
----> the other information
<---- here's the order
It's something to take to the business experts -- if the other data is one second old, is the calculation accurate enough?
On the other hand, if you need everything to be perfectly consistent, then you need to be able to lock the other information, so that nobody can change those details while you are working on your calculation.
That lock can be pessimistic (lock the data, then do the calculation), or optimistic (get a copy of the data, perform the calculation, then lock the data and make sure it hasn't changed).
Here's the "bad" news: the mechanism that defines locks in the domain driven design patterns is the aggregate. An aggregate is an expression of the coarse grained lock pattern; when you need to lock a bunch of data, that is the business telling you that the data should all be part of the same aggregate.
It will sometimes happen that you have a pretty domain model, with aggregates that express a bunch of obvious domain concepts, when you discover that the business rules don't line up with those boundaries at all, and you have to re-organize your data boundaries to get the rules to work.
It's often a good idea to begin your model design imagining your aggregates to be processes, and to group together those processes that need to be able to lock each other's data.
For example I need to check if table is already taken, and if it is, decline order creation. This table service may reside in another AppDomain, and network call maybe needed.
When the authoritative data lives somewhere else, then forget about locking. Think in terms of best effort, exception reports, and conflict mitigation.