Domain driven design 解决外部引用聚合内实体(DDD)的明显需要

Domain driven design 解决外部引用聚合内实体(DDD)的明显需要,domain-driven-design,Domain Driven Design,我试图遵循DDD原则来创建一个模型,用于确定身份是否可以访问属于资源的操作 资源(例如Web服务)是包含许多操作(例如方法)的东西,这些操作可以访问也可以不访问。标识是指希望访问资源上的一个或多个操作的标识。例如,有人在调用webservice方法时使用api键,必须确定是否允许访问 正如我目前看到的,标识和资源是聚合根,而操作是属于资源的实体。一个行动单独存在似乎没有意义;它将始终属于一种资源。标识需要知道它可以访问哪些资源操作。这似乎表明了以下模式 然而,据我所知,这违反了聚合之外的东西不

我试图遵循DDD原则来创建一个模型,用于确定身份是否可以访问属于资源的操作

资源(例如Web服务)是包含许多操作(例如方法)的东西,这些操作可以访问也可以不访问。标识是指希望访问资源上的一个或多个操作的标识。例如,有人在调用webservice方法时使用api键,必须确定是否允许访问

正如我目前看到的,标识和资源是聚合根,而操作是属于资源的实体。一个行动单独存在似乎没有意义;它将始终属于一种资源。标识需要知道它可以访问哪些资源操作。这似乎表明了以下模式

然而,据我所知,这违反了聚合之外的东西不能引用聚合中的实体的原则。它必须经过根。然后我在想,如果行动是聚合的根,资源是实体呢?但我觉得这不太符合逻辑。我也一直在考虑将资源和操作合并到一个实体中,这将是一个聚合根,但这在我看来也是错误的

因此,它让我陷入了如何使用DDD原理正确建模的困境。有人对如何建模有好的想法吗

更新:我试图创建的模型是标识模型,用于定义允许标识访问哪些资源操作。它不是实际执行资源和行动的模型

更新2-不变量: 所有对象的Id都是在出生时给定的,是唯一的,并且不会更改。标识的ApiKey在所有标识中都必须是唯一的。
聚合中的操作名称必须是唯一的,但两个不同的资源可以具有相同名称的操作,例如,资源“R1”可以具有操作“A1”,资源“R2”也可以具有操作“A1”,但两个“A1”不相同。

基于您提到的不变量,标识可以包含一个资源字典/映射,其中resourceId是键,值是一组唯一的操作名称/ID。这为您提供了每个资源每个标识的操作名称的唯一性:

Map

或者,您可以拥有一组/列表的资源,并且这些资源上有一组操作。唯一性可以通过您正在编码的语言中可用的集合类型来实现:

Set<Resource> Resources

class Resource {
    Set<Action> Actions
}
设置资源
类资源{
采取行动
}
更简单的是,只需通过组合两个ID创建一个资源操作键,并将其存储在一个集合或其他东西中,以提供唯一性:

Resource1-Action1

Resource1-Action2

Resource2-Action1

…等等

然后,您可以在Identity上使用一个方法来添加新的资源操作组合

我在你的描述中看不到任何东西可以证明行动是实体,因为它们似乎没有自己的身份

这是非常简单的,所以我想你已经大大简化了这个领域

例如,有人在调用webservice方法时使用api键,必须确定是否允许访问

这是一个疑问。从根本上说,通过连接属于不同聚合的实体的两个只读副本来回答查询没有什么错

您确实需要注意,因为聚合可以彼此独立地更改,并且因为它们可以独立于您的查询而更改,所以在进行连接时得到的答案可能会过时,并且不完全一致

例如,您可能正在将100毫秒前编写的身份副本加入200毫秒前编写的操作副本。运行查询时,其中一个聚合可能正在更改。

query或Write操作? 在DDD中,聚合和实体方面的域模型的目的是简化不变量的表达和实施,因为写入操作应用于模型

正如@VoiceOfUnreason的回答中提到的,“此用户是否可以对资源R执行操作”是一个不一定需要流经域模型的问题-可以通过对预投影只读模型的查询或对构成写模型持久性的表的标准SQL查询来回答(取决于你的需要)

拆分上下文以简化不变量 然而,您的问题主要是关于如何识别是否允许一个身份执行一个操作,但实际上是在寻找一个更简单的模型来更新资源、操作和权限。因此,为了探索这个想法……隐式地有两种类型的写操作:

  • 定义可用资源和行动
  • 定义允许特定标识执行哪些资源操作组合
  • 如果将这两种类型的操作划分为不同的有界上下文,则可能会简化这两种类型操作的模型

    在第一种情况下,您可以像以前一样建模一个聚合,其中Resource作为聚合根,Action作为包含的实体。这允许强制执行不变的操作,即Action名称在资源中必须是唯一的

    在此上下文中进行更改时,您将发布事件,例如
    ActionAddedToResource
    ActionRemovedFromResource

    在第二个上下文中,您将有三个聚合:

    • 身份
    • 资源行动
      • 属性:Id、ResourceId、ResourceName、ActionId、ActionName
    • 许可
    ResourceAction实例将根据从第一个上下文发布的事件进行更新-在ActionAddedToResource上创建,在ActionRemovedFromResource上删除。如果存在没有act的资源
    [RequiredPermission("my-system:\\order\create")]