DDD聚合建模

发布于 2025-01-22 04:56:32 字数 2075 浏览 0 评论 0原文

我相对需要DDD战术模式,并且需要帮助建模示例应用程序的帮助。我正在创建一个应该帮助人们管理商店/组织中的转变的应用程序。

我目前正在从事我的第一个微服务:会员服务(域)。该服务负责创建新的组织&邀请用户成为创建组织的成员。以下是我试图建模的服务规则。

  • 任何用户都可以创建一个组织,
  • 用户可以创建一个以上的组织来
  • 创建该组织的组织是组织的初始管理,
  • 一个组织至少只有1个
  • 管理员只能邀请人们加入组织。他们可以通过通过电子邮件发送邀请来邀请不是当前用户的人,
  • 只有在接受邀请(可能是通过电子邮件单击链接)

的情况下,我只有2个汇总根类:组织和AMP ;用户

组织

class Organization extends Aggregate {
  private _id!: OrgId;
  private _members!: Member[];
  private _name!: Name;

  get members() {
    return this._members;
  }

  get id() {
    return this._id;
  }

  constructor(args: InstantiateConstructorArgs | CreateConstructorArgs) {
    super();
    if (args.type === ConstructorTypes.Instantiate) {
      this.loadFromHistory(args.events);
    } else {
      const organizationCreatedEvent = OrganizationCreatedEvent.create(
        args.id,
        args.creatorId,
        args.name
      );
      this.applyChange(organizationCreatedEvent);
    }
  }

  private applyOrganizationCreatedEvent(e: OrganizationCreatedEvent) {
    const initialMember = new Member(
      e.orgId,
      MemberRoles.Admin,
      e.creatorUserId
    );
    this._id = e.orgId;
    this._name = e.orgName;
    this._members = [initialMember];
  }
}

如您所见,组织Rogent Root负责维护其成员的集合。这也是事件来源。成员类是在这样的

export enum OrganizationMemberRoles {
  Admin,
  Regular,
}

class OrganizationMember {
  constructor(
    public readonly organizationId: OrgId,
    public readonly role: OrganizationMemberRoles,
    public readonly userId: UserId
  ) {}
}

用户

class User extends Aggregate {
  constructor(public readonly id: UserId) {
    super();
  }

  createOrganization(orgId: OrgId, name: Name) {
    return OrganizationFactory.CreateOrganization(orgId, this.id, name);
  }
}

的上下文中定义的,我

  1. 不确定什么是建模邀请过程的最佳方法。由于只有管理员才能向组织扩展邀请,您是否建议创建管理类并将扩展名称方法放在上面?如果是这样,请求流将如何?
  2. 我应该对组织汇总的邀请进行建模?还是应该吞噬整体?如果外部,我应该使用最终的一致性模型将成员添加到组织中吗?

I am relatively need to DDD tactical patterns and need help modelling an example app im putting together. I am creating an app that is supposed to help people manage shifts in their stores/organizations.

I am currently working on my first microservice: Membership service (domain). This service is responsible for creating new organizations & inviting users to be become members of the created organizations. The following are rules of the service I am trying to model.

  • Any user can create an organization
  • A user can create more than one organization
  • The user that creates the organization is the initial admin of the organization
  • An organization should at least have 1 admin
  • Only admins can invite people to join the organization. They can invite people who are not current users by sending an invitation via email
  • A user is added to the organization only if they accept the invitation (probably click on a link via email)

So far, I only have 2 aggregate root classes: Organization & User

Organization

class Organization extends Aggregate {
  private _id!: OrgId;
  private _members!: Member[];
  private _name!: Name;

  get members() {
    return this._members;
  }

  get id() {
    return this._id;
  }

  constructor(args: InstantiateConstructorArgs | CreateConstructorArgs) {
    super();
    if (args.type === ConstructorTypes.Instantiate) {
      this.loadFromHistory(args.events);
    } else {
      const organizationCreatedEvent = OrganizationCreatedEvent.create(
        args.id,
        args.creatorId,
        args.name
      );
      this.applyChange(organizationCreatedEvent);
    }
  }

  private applyOrganizationCreatedEvent(e: OrganizationCreatedEvent) {
    const initialMember = new Member(
      e.orgId,
      MemberRoles.Admin,
      e.creatorUserId
    );
    this._id = e.orgId;
    this._name = e.orgName;
    this._members = [initialMember];
  }
}

As you can see, the Organization aggregate root is responsible for maintaining a collection of its members. It is event sourced as well. The Member class is defined within the context of the as such

export enum OrganizationMemberRoles {
  Admin,
  Regular,
}

class OrganizationMember {
  constructor(
    public readonly organizationId: OrgId,
    public readonly role: OrganizationMemberRoles,
    public readonly userId: UserId
  ) {}
}

User

class User extends Aggregate {
  constructor(public readonly id: UserId) {
    super();
  }

  createOrganization(orgId: OrgId, name: Name) {
    return OrganizationFactory.CreateOrganization(orgId, this.id, name);
  }
}

My Modelling Struggle

  1. I am not sure what is the best way to model the invitation process. Since only Admins can extend an invitation to the organization, would you recommend creating an Admin class and putting the extendInvitation method on that? If so, how would the request flow look like?
  2. Should I model the invitation outside of the Organization aggregate? Or should it be engulfed in the aggregate? If outside, then should I use an eventual consistency model to add the member to the organization?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

笙痞 2025-01-29 04:56:32

只有管​​理员才能创建它的事实是“授权”问题,也许明天您想将其扩展到不是该组织的“特殊”用户的子集,或者您希望整个平台的管理员能够邀请特定组织中的用户。

只有在接受邀请时将用户添加到组织中(可能通过电子邮件单击链接)

在我看来,邀请是一个实体本身,我看到在组织上具有“邀请”命令的可能性只能通过管理组织本身执行,并将创建一个新的邀请(发送的电子邮件是创建邀请实体的副作用)。

(我看到一种很好的方法,邀请函数insite the org应该已经拥有所需的所有信息来检查不变性,它知道所有已经加入的用户的所有用户)

The fact that only admin can create it is a "authorization" concern, maybe tomorrow you want to extend it to a subset of "special" users that are not admin of that org, or you want the admin of the entire platform to be able to invite a user in a specific org.

A user is added to the organization only if they accept the invitation (probably click on a link via email)

It seems to me that the invitation is an entity itself, and I see the possibility to have an "Invite" command on the Organization that can be execute only by admin of the org itself, and will create a new Invite (the email being sent is a side effect of the Invite entity being created).

(I see a good approach having the Invite insite the org as it should already have all the info needed in order to check the invariants, it knows all the users that already joined it)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文