alaboudi
alaboudi

Reputation: 3413

Is my event raised in the correct aggregate

I'm pretty new to implementing a DDD + CQRS + event sourcing system. The following is the business context I'm modelling:

A User can create an Organization. An Organization can have multiple Members. Members can either be Regular members or Admin members. The user that creates the organization is by default the first Admin.

In particular, im trying to represent the act of creating an organization in an implementation that is domain rich. The following is what I have so far.

class User extends Aggregate {
  constructor(
    public readonly id: UserId,
    public readonly name: Name,
    public readonly email: Email
  ) {
    super(id);
  }

  createOrganization(orgId: OrgId, name: Name) {
    const creator = new Member(orgId, MemberRoles.Admin, this.id);
    return new Organization(orgId, name, [creator]);
  }
}

class Organization extends Aggregate {
  public readonly members: Member[];
  public readonly name: Name;

  constructor(
    id: OrgId,
    name: Name,
    members: Member[],
  ) {
    super(id);
    this.name = name;
    this.members = members
  }

  addMember(member) { /**/}
  removeMember(memberId) { /**/}
}

I like the fact that I have a .createOrganization() method on the User class since it illustrates the fact that a user has the ability to do so. But where should I raise UserCreatedOrganizationEvent? Should I do it in the User class? Is it not wrong to create events in one aggregate (User) which would then be used to directly hydrated another aggregate (Organization)? I keep hearing that each aggregate should hydrate themselves from their own events to ensure invariants are always ensured. Then does it make more sense to have a static create method on the organization? But I can't raise an event associated to my aggregate from a static method. Any thoughts on this would be appreciate.

Upvotes: 0

Views: 50

Answers (1)

Subhash
Subhash

Reputation: 3260

Creating the Organization aggregate as part of your User aggregate is wrong because the User aggregate ends up understanding the intricacies of the Organization aggregate. They end up being tightly coupled.

The Admin user is just one of the many details that go into creating the organization. I would think of it as an Authentication/Authorization concern that would validate if the user performing the action should be allowed to go through it.

And yes, typically, you would create a factory method (a class method) within the Organization aggregate that would instantiate the Aggregate and raise an event on the instantiated aggregate object. The factory method would be invoked by a Command Handler, handling the command to create an organization.

Think of the contra argument to clearly understand why the user creating the organization via the user aggregate is not sustainable. Technically, every single action in your application would be performed by a user. That does not mean that the user aggregate is responsible for all other Aggregates in the system.

Upvotes: 1

Related Questions