I'm trying to implement an event sourced system with dddd. Currently I'm struggling how and where my events are crossing the boundaries of the bounded contexts.
Imagine there are two bounded contexts:
- Product Management
- Logistics System
Product Management has all the knowledge about the products. For simplification it is just "Name". The logistics system also has products, but has no knowledge about their meta data. For them it is mostly only a physical box with an Id. But when somebody scans this product, they want to show the name either. So the ProductManagement BC should inform the Logistics BC, that a product is registered and a name has changed. So I will end up with the events in ProductManagement, raised from inside the ProductAggregate:
ProductManagement.Events.ProductRegistered
ProductManagement.Events.ProductNameChanged
When I got it correctly these are the events which I will save into the event store. And these are also the events which will be published into the message bus. So at the logistics side I will subscribe to these events. So far so good.
The problem now is: How will I work with this event on the Logistics side? Vaughn Vernon said in a talk, that it is best practice to have an event handler there, which is in the application layer, so it will basically be an application service. He also said, that it would be best to transform it to one or several commands. Do I save all received events on the logistics side again? Do I also save the commands? How can I reproduce my current state if something went wrong? Or how will I know, that it is not the fault of the processing in the receiving Bounded Context, but rather a wrong event. What will I do if my transformed commands getting rejected?
I know that there are no calculations or changes in aggregates on logistics side. But I think this doesn't really matter for my questions.
First, you have to ask the domain experts if that event will cause a side effect that impact the LS context. Only in this case, you have to subscribe to this event and send the related command to the LS Aggregate that will change and commit its state or, if you choose to event-source this aggregate too, another event.
An event is a representation of something happened, so it can't be "wrong". Anyway, commands triggered by an event can fail. Which type of failure are you talking about? Technical or domain specific? In the first case, the source event will stay in the bus for a future retry (maybe after some bug fix). In the second case, if the PM aggregate needs to be informed about the result, the LS Aggregate should emit an appropriate event which, in turn, will be handled by the PM aggregate.