Reputation: 15221
Situation:
We have a classic Order
with OrderLine
s. Each OrderLine
has reference to the ProductId
.
Each Product
has its RelatedProduct
. For example, product
class Product {
string Id;
string Name;
string RelatedProductId;
decimal RelatedProductQuantity;
.
.
.
}
There is a business rule that whenever Product
is added to Order
with new OrderLine
then Product
with id=RelatedProductId
should also be added in a quantity=RelatedProductQuantity
.
Questions:
How to keep this rule within the domain so it doesn't spill over to application service but at the same time keep Order
aggregate clean in a sense not to poison it by injecting repository or any data-fetching thing?
Should we use domain service? And if so, can domain service have repository injected, prepare all the data, create OrderLine
(for both, base and related products), fill in the aggregate and save it to repository?
If none of the above, what's the best way to model it?
Upvotes: 1
Views: 490
Reputation: 57249
There are two common patterns that you will see here:
The second option is your classic "domain service" approach, where you use a "stateless" instance to fetch a copy of "global" state.
But, with the right perspective you might recognize that the first approach is the same mechanism - only it's the application code, rather than the domain code, that fetches the copy of the information.
In both cases, it's still the domain model deciding what to do with the copy of the information, so that's all right.
Possible tie breakers:
If the information you need to copy isn't local (ie: you are dealing with a distributed system, and the information isn't available in a local cache), then fetching that information will have failure modes, and you probably don't want to pollute the domain model with a bunch of code to handle that (in much the same way that you don't pollute your domain code with a bunch of database related concerns).
When it's hard to guess in advance which arguments are going to be passed to fetch the data, then it may make sense to let the domain code invoke that function directly. Otherwise, you end up with the application code asking the domain model for the arguments, and the passing the information back into the model, and this could even ping pong back and forth several times.
(Not that it can't be done: you can make it work - what's less clear is how happy you are going to be maintaining the code).
If you aren't sure... use the approach that feels more familiar.
Upvotes: 1