有界上下文和聚合根

6
我们正在尝试使用DDD原则建模基于RBAC的用户维护系统。我们已经确定了以下实体:
Authorization is an Aggregate Root with the following:
    User   (an entity object)
    List<Authority>    (list of value objects)

Authority contains the following value objects:
    AuthorityType (base class of classes Role and Permission)
    effectiveDate

Role contains a List<Permission>
Permission has code and description attributes

在典型情况下,授权是聚合根,因为用户维护中的所有内容都围绕它展开(例如,我可以授予用户一个或多个角色或权限)。
我的问题是:角色和权限呢?它们在它们自己的上下文中也是聚合根吗?(即我有三个上下文,授权、角色、权限)。虽然可以将所有内容合并到一个上下文中,但角色会不会太重了,因为它将作为授权“对象图”的一部分加载?
1个回答

38

首先,我不禁感觉您误解了有界上下文的概念。您所描述的有界上下文我会称之为实体。在我的理解中,有界上下文用于为通用语言中定义的实体在给定上下文中赋予不同的目的。

例如,在医院领域,门诊部门治疗的患者可能有一份转诊单清单以及预约(BookAppointment())等方法。然而,作为住院病人的患者将拥有一个病房属性和转移到手术室(TransferToTheatre())等方法。因此,存在两个有界上下文,即门诊和住院。在保险领域,销售团队制定了一个保单,与风险程度和费用相关。但如果到达理赔部门,这些信息对他们来说毫无意义。他们只需要验证保单是否适用于索赔。因此,在此处存在两个上下文:销售和理赔。

其次,您是否只是在使用RBAC作为示例,同时尝试实现DDD?我问的原因是,DDD旨在帮助解决复杂的业务问题,即需要进行计算的问题(例如保单风险)。在我看来,RBAC是一个相当简单的基础设施服务,它不涉及实际的领域逻辑,因此不需要严格的DDD实现。DDD的投资成本很高,您不应该仅仅为了采用而采用;这就是有界上下文的重要性——只有在有理由时才使用DDD进行建模。

无论如何,冒着这个答案听起来太“学术”的风险,我将尝试回答您的问题,假设您仍然想将其建模为DDD:

对我而言,所有内容都适合一个上下文(称为“Security”或类似名称)。

作为一个通用的经验法则,使所有需要独立事务的内容成为聚合,因此:

  1. 假设该系统允许在 Authorization 对象中添加权限(Authorities)信息,将Authorization设置为聚合根。(虽然可能有人认为应该放弃Authorization,并在User中列出权限(Authorities)信息作为聚合根)
  2. 权限(Authorities)仅在添加时才有意义,并且只用于Authorization聚合根内部,因此仍然保留为实体。
  3. 假设该系统允许向角色(Role)添加权限(Permissions),则Role成为聚合根。
  4. 假设权限(Permissions)无法创建/删除 - 即系统定义了它们,因此这些是简单的值对象。

谈到聚合设计问题,我非常推荐这些文章


1
再次感谢你,David。你的陈述“有界上下文用于为通用语言中定义的实体在给定上下文中赋予不同的目的”让我明白了。我想最初让我感到困惑的是必须通过AR才能访问其中一个EO/VO的要求。这很令人困惑,因为正如你所提到的,Role也是在Authorization AR内引用的AR。我们将进行RBAC练习,以掌握使用DDD的方法。我们正在处理的其他上下文我认为也适合应用DDD。 - jett
3
没问题。我给你一个建议:让聚合根通过引用其ID而不是聚合根本身来引用其他聚合根。如果你读了我建议的那些文章,就会明白其中的原因。 - David Masters
我喜欢这个例子,让我更清楚地理解上下文。 - 王奕然

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接