【问题标题】:Domain Driven Design implement aggregates领域驱动设计实现聚合
【发布时间】:2019-06-27 21:18:24
【问题描述】:

我已阅读有关聚合的创建和职责的信息,但我对如何正确实施它们感到怀疑。假设我们有 2 个实体的上下文。一个是公司,第二个是用户。业务规则在公司实体中,这意味着这应该成为聚合根。对于公司,我们只能分配 3 个用户,当 Comapny 的状态为“被阻止”时,我们不能分配用户。用户也可以使用电子邮件和密码登录。考虑到这一点,用户实体上的每个操作都应该通过聚合根调用,用户不应该有自己的存储库。当没有公司根用户无法直接登录时,如何对用户进行登录操作?我们不能从聚合中调用 User。如何使用提供的电子邮件和密码查找用户?获取所有聚合并迭代其用户效率低下,我认为这不是一个好主意。 谢谢你的帮助。

【问题讨论】:

  • 感觉这里有 2 BC。一个是管理凭据的 IdentityContext,另一个是 CompanyManagementContext。关于授权。它是否可以成为 IdentityContext 的一部分是一个棘手的部分。您应该分析如何将授权规则耦合到 CompanyManagementContext。也许它应该存在于 CompanyManagementContext 中。

标签: domain-driven-design aggregate


【解决方案1】:

我认为该用户应该属于另一个 BC(管理身份验证和授权)。在您的公司 BC 中,您必须从认证和授权 BC 中获取用户。您必须将两个 BC 与上下文映射模式集成,其中身份验证和授权 BC 位于上游,而公司 BC 位于下游。

【讨论】:

  • 我已将 Company 和 User 置于共同的 BC(身份),因为这两个 Entities 都是强连接的。在注册过程中,我使用用户(所有者)创建公司,因此最好的解决方案是在公司聚合中创建工厂方法以避免不一致。如果 Company 和 User 将是单独的 BC,那么我应该抛出业务事件并在 User BC 中处理它吗?
  • 我的回答类似于@Tseng。在公司 BC (C-BC) 中,您应该有所有者和雇员。在身份验证和授权 BC (AA-BC) 中,您拥有用户和角色。上下文映射取决于您。您可以使用异步方法(事件)或同步(AA-BC 中的休息 api)来实现它。正如Tseng所说,从C-BC的角度来看,认证和授权管理是基础设施。它是应用服务中的一个接口,在基础架构中实现,并在此实现中与 AA-BC 对话。
  • 感谢您的帮助。欣赏
  • 我已经按照你的建议模拟了 2 BC,但我仍然想知道如何模拟 BC 之间的通信。例如,注册是一个涉及两个上下文的过程。有一个 REST 请求 - api/registration/company,涵盖 2 个业务操作。一种是在 C-BC 上下文中在 CompanyAggregate 上创建方法。之后,我可以触发将在 AA-BC 中处理的事件,以创建提供电子邮件和密码的用户。如果第一次触发事件后应用程序崩溃怎么办?会有不一致的地方。也许注册应该是简单的 crud 操作,因为这里没有业务逻辑
  • 通讯是另一种方式,AA-BC是上游,C-BC是下游。如果将两者都与事件集成,则上游发布事件,下游监听事件。 AA-BC 管理用户、角色、密码、身份验证等。这就是 Vaughn Vernon 所说的“身份和访问上下文”。看看他的书“实现领域驱动设计”。代码在github.com/VaughnVernon/IDDD_Samples
【解决方案2】:

身份验证通常不是域的一部分(在所有用例的 99% 中),只是基础架构的一部分。

因此Users 不应该出现在有界上下文中。在真实的商业世界中,也没有用户,只有 People、Persons、Employees、Managers 或 Contacts 等。

因此,对于日志记录问题,您可以让我们的用户使用用户名 + 密码作为身份验证。这些用户有一个 id(数字、字符串或 guid)。

您的EmployeePersons 实体/聚合(或您命名它的名称取决于您的域,确切的术语取决于公司 - 无处不在的语言)然后只包含属于该人的数据(但不是识别相关信息)。

然后,您可以将员工连接到用户(通过将员工 ID 设置为用于登录的用户的 ID、额外字段或通过 1:1 或 1:n 查找表)。

通过这种方式,您可以轻松删除用户(登录名)而不删除 Employee 实体,因为在现实世界的场景中,您不能轻易删除业务数据(即想象删除用户会删除每张发票上的收件人或CRM 数据,没有人会知道这个人过去曾在那里工作过)。

【讨论】:

  • 谢谢,我同意在域中“用户”一词没有空格:) 有 CompanyOwner 和 Employee。那么当我创建公司并添加 CompanyOwner 时,应该将登录机制建模为基础设施服务吗?如何将匹配结果与域实体(员工、公司所有者)联系起来?
  • 最简单的方法是它们都使用相同的随机生成的 id。 Guids 是一个很好的匹配,因为它们是全球唯一的。身份验证发生在您的应用程序层(接受调用的 api),在用户通过身份验证后,您继续调用将 id 传递给域服务/聚合的域服务。或者,将Emplyoee 的 id 保存在身份验证用户模型中以关联(这样域就不会受到身份验证和基础设施问题的影响)
猜你喜欢
  • 1970-01-01
  • 2010-11-01
  • 2013-09-16
  • 1970-01-01
  • 2013-06-07
  • 2011-04-26
  • 1970-01-01
相关资源
最近更新 更多