what if we make the aggregate fields expose to outside of domain

Hi,
There are times user did an operation by mistake. Then application need provided a feature to let him cancel the operation he did. In cqrs world, we need have an event for that cancel operation.
For example:XOperationDoneEvent,XOperationCancelledEvent
Lets’s say because of XOperation, 5 fields of aggregate changed. Then after cancel XOperation, we expect the 5 fields of aggregate change backed to prior value, the view(read model) change back to prior value. Here comes the question:
Where can I get the prior value for the view(read model)?
Should I just put all the 5 fields and its prior value in the XOperationCancelledEvent? Or I design the view very careful, and lets the view capable of get the prior value from the view itself?

If I put 5 fields and it’s prior value in the XOperationCancelledEvent,Then there will be a chance that in future 6 fields(a new field defined because new business rule) need be changed back by this event. Then we may need a way(upcasting/fixing) to add that new fields to those “XOperationCancelledEvent” in the event store.

if we make the view capable of got the prior value, then there must be a lot of duplicated logic with the domain.

Seems neither way is perfect. So I start to wondering(am i crazy?), what if we make the aggregate fields expose to outside of domain (read only public getter), and read model can access those property to update the view?

Best regards,

Keats

From E.Novation

Hi Keats,

there are multiple ways to approach this problem. What you describe, is one of them, namely cancelling an operation. But in general, we don’t really talk about cancelling an operation, but to take a compensating action. There is a slight difference between the two, especially in the way you approach them.

In de first, you try to undo something. In real life, undo doesn’t exist. Fortunately, computers open a world that doesn’t need to stick to the rules of real life. One way to implement this is using the Memento pattern. The aggregate could keep track of its own history (which is not the same thing as using event sourcing). When an action is undone, it emits an event with the new relevant state. Don’t just say “actionUndoneEvent”, because that will offload much complexity to your view model. And that’s not the place where you want complexity.

The other approach is compensating transactions. They don’t use the word “undo”. Instead, they just do something that is “opposite” of the other thing. For example, if you “add” an item to a collection, the compensating action would be to “remove” that item. Where “undo” is a rather technical thing, compensating actions are very functional. Unfortunately, this also means that you need domain knowledge to identify them. So that’s something I cannot help you with at this point.

Cheers,

Allard

Hi Allard,
Thank you for the reply.
You are right, I shouldn’t simply name it as “actionUndoneEvent”. When I think the cancel action as a conpensation action, then it became a regular action.No difference with others.

But I still have some question remained with event design which I will create another post.

Best regards,

Keats

From E.Novation