numberjak
numberjak

Reputation: 1255

Am I right in separating integration events from domain events?

I use event sourcing to store my object.

Changes are captured via domain events, holding only the minimal information required, e.g.

GroupRenamedDomainEvent 
{
   string Name;
}

GroupMemberAddedDomainEvent
{
   int MemberId;
   string Name;
}

However elsewhere in my application I want to be notified if a Group is updated in general. I don’t want to have to accumulate or respond to a bunch of more granular and less helpful domain events.

My ideal event to subscribe to is:

GroupUpdatedIntegrationEvent
{
   int Id;
   string Name;
   List<Member> Members;
}

So what I have done is the following:

  1. Update group aggregate.
  2. Save down generated domain events.
  3. Use these generated domain events to to see whether to trigger my integration event.

For the example above, this might look like:

var groupAggregate = _groupAggregateRepo.Load(id);

groupAggregate.Rename(“Test”);
groupAggregate.AddMember(1, “John”);

_groupAggregateRepo.Save(groupAggregate);

var domainEvents = groupAggregate.GetEvents();

if (domainEvents.Any())
{
   _integrationEventPublisher.Publish(
       new GroupUpdatedIntegrationEvent
       {
          Id = groupAggregateId,
          Name = groupAggregate.Name,
          Members = groupAggregate.Members
       });
}

This means my integration events used throughout the application are not coupled to what data is used in my event sourcing domain events.

Is this a sensible idea? Has anyone got a better alternative? Am I misunderstanding these terms?

Upvotes: 0

Views: 600

Answers (1)

Benjamin M
Benjamin M

Reputation: 24527

Of course you're free to create and publish as many events as you want, but I don't see (m)any benefits there.

  1. You still have coupling: You just shifted the coupling from one Event to another. Here it really depends how many Event Consumers you've got. And if everything is running in-memory or stored in a DB. And if your Consumers need some kind of Replay mechanism.

  2. Your integration Events can grow over time and use much bandwidth: If your Group contains 1000 Members and you add 5 new Members, you'll trigger 5 integration events that always contain all members, instead of just the small delta. It'll use much more network bandwidth and hard drive space (if persisted).

  3. You're coupling your Integration Event to your Domain Model. I think this is not good at all. You won't be able to simply change the Member class in the future, because all Event Consumers depend on it. A solution could be to instead use a separate MemberDTO class for the Integration Event and write a MemberToMemberDTO converter.

  4. Your Event Consumers can't decide which changes they want to handle, because they always just receive the full blown current state. The information what actually changed is lost.

The only real benefit I see is that you don't have to again write code to apply your Domain Events.

In general it looks a bit like Read Model in CQRS. Maybe that's what you're looking for?

But of course it depends. If your solution fits your application's needs, then it'll be fine to do it that way. Rules are made to show you the right direction, but they're also meant to be broken when they get in your way (and you know what you're doing).

Upvotes: 1

Related Questions