Hey,
It's good to see that you have a separate Product entity in the the different bounded contexts. That shows you understand the importance of linguistic boundaries
One page 414 the Bus.Send() call is happening inside an event handler that lives in the service layer. This is an external event that is published between bounded contexts. We recommend publishing external events from the service layer, but you can do it multiple ways....
If you want to publish external events from the domain, but you don't want to publish an internal event using the Domain Events pattern, you can create a domain service contract as shown on page 394. Using this approach, you would have an interface in the domain, perhaps something like IProductDeactivatedNotifier. But the implementation will live in the service layer. There's an example on page 398 of using a domain service in the domain.
There are challenges involved when you want to inject a domain service into an entity though. This is also discussed from page 398 onwards in the section "In the Domain".
Quote:
|
Your suggestion in the previous response to send the 'ProductDeactivated' in the app service will help to move the infrastructure concern out of the domain. This has a side effect because you have to go to the app service to see what happens next. I would rather prefer using Bus.Send in the Product.Deactivate method to send a ProductDeactivated event.
|
I'd just like to back up and discuss the concern you raise here. Your point is valid, but you can look at this configuration in multiple ways. Since the event is external it is handled by other bounded contexts, so it isn't part of the workflow inside the bounded context that sends it. Basically, there's nothing that comes after it inside this domain model. So, it's worth reconsidering. Adding Bus.Send to your domain to send an external event is really starting to clutter the domain with technical concerns.
Quote:
|
1. In the Purchase BC, who should handle the ProductDeactivated event? Is it the app service or the domain service or the product? Please see the next question.
|
The most common approach is that initially the event will be handled by an NServiceBus handler that is implemented within your service layer. That would then invoke an application service that would load an entity from the domain and call a method on it.
I think Figure 25-1 could be a useful visual indication of what I am suggesting. It shows how external events are sent from an application service in bounded context A to an application service in bounded context B.
If you imagine bounded context B is your Purchasing bounded context, assume there is an application service in there that handles the message from the application service in bounded context A and invokes the application service in bounded context B.
Quote:
|
2. There will be Product.StopBuying() method which sets a flag. This should happen inside a Handle(ProductDeactivated product). Where this handler should be implemented? In the app service or domain service? Or the Product itself? Note: The product entity in the purchase BC and the catalog BC are different.
|
Since this handler is handling an external event it should live in the service layer. Going back to Figure 25-1, it is the handler that receives the message from bounded context A, and it invokes the application service in bounded context B. Therefore it lives in the service layer of bounded context B (your purchasing bounded context).
Note: I refer to the "service layer" which is also known as the application service layer or the application layer. In Figure 25-1 it is labelled the application layer.
Thanks for you questions. This is fun. Let me know if I can provide any further assistance.