3

Does this make sense or what is wrong with this approach?

enter image description here

So instead of using event store, we may use aggregate repository to update the aggregate based on values contained in published event.

Slimer
  • 217
  • 1
  • 9
  • What if the Aggregate publish more events in the same method call and the second fails to be applied? – Constantin Galbenu Oct 02 '17 at 14:44
  • The whole aggregate operation(s) should be covered by Application Service that handles transaction scope. So in this case, all notifications are done under one transaction, hence all events would be rolled back. For notifying another bounded context, there should be additional mechanism out of this transaction scope to preserve consistency. – Slimer Oct 02 '17 at 14:53
  • So the repository will know how to create the state based on the events? – Constantin Galbenu Oct 02 '17 at 15:00
  • Yes, repository can match particular event and run update based on e.g match (e) { case e1.. case e2.. } – Slimer Oct 02 '17 at 15:30
  • but why would you strip the Aggregate of that behavior? – Constantin Galbenu Oct 02 '17 at 15:32
  • What behaviour we're talking about? – Slimer Oct 02 '17 at 15:37
  • The behaviour of projecting the stream of events to a state that it is used again in the Aggregate to validate the commands that will follow – Constantin Galbenu Oct 02 '17 at 15:40
  • Also, there is this particular case of emitting multiple events, but they need to be applied to the state one by one – Constantin Galbenu Oct 02 '17 at 15:43
  • In standard approach you would store this event to event store and using event souring you'd replay events on aggregate to get the current state. What I'm thinking is to instead of storing events and doing event sourcing, I used repository to load aggregate from let's say bunch of tables and instead of storing, its current state, just do update on it based of published event...It's just a theory and I'm glad we're talking about it.. – Slimer Oct 02 '17 at 17:05
  • I'm glad too and I need to understand better in order to give an example. What you are talking until now is CQRS without Event sourcing. – Constantin Galbenu Oct 02 '17 at 17:07
  • Almost, but not exactly, since query model is this still this Aggregate. But yeah, what I'm trying to achieve is CQS or "Tell, don't ask" – Slimer Oct 02 '17 at 17:18
  • CQS is not the same as "Tell don't ask" – Constantin Galbenu Oct 02 '17 at 17:34
  • In terms of commands it's practically the same..both principles returns void and mutates state, CQS though provides also a query methods.. but sure ... In general it's not. – Slimer Oct 02 '17 at 17:45
  • They are orthogonal. For example if you have an object that keeps a counter that should be incremented. You could query it for the current value, add 1 then set back the new value: you are breaking TDA; but if you add a new method named `increment` that just increments the value you are not breaking TDA; if you return the old value then you break CQS and if you don't return the old value you don't break CQS. – Constantin Galbenu Oct 02 '17 at 17:55
  • We're moving out of topic a bit – Slimer Oct 02 '17 at 18:43

3 Answers3

4

Does this make sense or what is wrong with this approach?

At surface level, the diagram looks pretty broken. It's hard to say, because your diagram doesn't describe the context of the publish call.

What the diagram appears to imply is that, instead of copying the in memory state of the aggregate directly to the repository, we're going to first decompose that state into events, copy them to a message transport layer, addressed to the repository, who will then rebuild a copy of the state of the aggregate that we originally started with?

That's a lot of complexity to introduce - where do you think the payoff is going to happen?

What you might be looking for is Udi Dahan's approach to handling domain events, which writes the events and the updated aggregate state into the database together.

His approach doesn't really change the basic pattern very much - the application component uses the repository to obtain a local copy of the state to interact with, and when done attempts to commit its changes to the repository. It's the repository code at that point that extract both the state and domain events from the aggregate before writing them to the database.

Note that, in Udi's pattern, the publish of the event happens after the durable write the database has succeeded.

Aggregate -->
Repository -->
DataStore -->
Domain Event Publisher -->
Subscribers

would be the more usual flow; that might possibly include the repository (or the application) publishing the domain events after the data store as confirmed the successful commit of the transaction.

In any event, I don't recognize from your diagram a problem that you should be trying to solve; it looks like an improvisation from the usual patterns, and without more context it is difficult to diagnose whether there is a fundamental misunderstanding or a really unusual set of constraints that are distorting the solution.

It might be worth opening a new question describing the problem you are trying to solve, and the constraints that need to be satisfied, to see if anyone is aware of relevant literature.

VoiceOfUnreason
  • 32,131
  • 2
  • 42
  • 79
  • Basically, I'm not going to rebuild the aggregate, but updating database directly without need to load aggregate again. Probably it's not best approach, maybe it's just complication or even bad idea. Payoff would be "Tell, don't ask" on aggregate.. CQS principle.. – Slimer Oct 02 '17 at 16:47
2

Updating data from events even when you are not using event sourcing is fine, your approach is fine. But your approach depends entirely on your needs and what exactly the updates are. The reason why people use event sourcing is to have the event log. But you usually do not need the event log for every single thing in your project, as you have already noticed.

When you are not using event sourcing and are not going to be using the event log at all, you should ask yourself whether you needs events at all?

For the simple update you are demonstrating here, the event is pretty much meaningless and the update can be made by using values from the aggregate directly. Adding the event just because is an unnecessary overhead.

However, there is a use case for domain events.

Let's say that you have some aggregate which has 4 methods to allow modifications. When you run three out of the four methods to modify the inner state of the aggregate, all you need to do is to update the aggregate in the data layer as well. But when you run the fourth method, after persisting the aggregate you also want to start some process as a reaction to the operation.

This specific case is very well and neatly modeled using domain events. You subscribe to your event bus to react only on the event generated by the fourth method and ignore the other three. The design is cohesive and sleek.

Obviously, using domain events like this will force you to update the data layer from the data contained within the events themselves, as you have demonstrated in the picture.

I would not recommend using events just because they sound cool. Use them at appropriate places and when you really need them. If you don't, using simple mutators to update properties of an aggregate directly is completely fine.

Andy
  • 10,238
  • 4
  • 25
  • 50
0

I think the design is wrong for a general use case. From the comments I understand that the state would be build by the Repository. This is wrong because the logic to update the state should stay in the same place that query the state, so it should also be contained in the Aggregate. Put it other way, the Repository implementation would contain business/domain logic and this is not OK.

If you don't want to use an Event store then you can use CQRS with a flat persistence.

Constantin Galbenu
  • 3,242
  • 12
  • 16