我可以将更改从一个聚合根级联到另一个聚合根吗?

时间:2016-04-14 14:48:10

标签: c# domain-driven-design

我在DDD中建立关系时遇到了麻烦。我有四个实体:

  • 声明 - 定义对服务的访问权。
  • 服务 - 一项网络服务。服务有很多声明,可以属于任意数量的团队。
  • 角色 - 包含来自任意数量服务的声明集合。角色永远属于团队。
  • 团队 - 包含角色和服务的集合。

当我从服务中删除声明时,也应该从已分配给它们的声明的所有角色中删除它。同样,当我更改服务名称时,该名称应该反映在所有团队中。

我目前有一个服务聚合根(允许独立于任何一个团队添加和更改服务),以及一个团队聚合根(以允许管理特定于团队的角色)。这会产生两个问题:

  • 服务聚合中的更改未反映在团队聚合
  • 当从服务中删除声明时,无法将其级联到团队的角色中。

我的模型出现了明显可怕的错误,并且想知道是否有人可以说明我出错的地方。

2 个答案:

答案 0 :(得分:2)

  

我的模型显然有一些严重的错误,并且想知道是否有人可以照亮我出错的地方。

在我看来,好像你已经将名词优先于规则,并让自己迷失在沼泽中。

示例:

  

同样,当我更改服务名称时,该名称应反映在所有团队中。

Riddle:您需要在需要了解服务聚合的名称的Team聚合中满足哪些不变量?是否存在一些业务规则,例如“如果服务名称是骆驼案例,则团队仅限于10个角色”?

就此而言,您需要在需要知道名称的服务聚合中满足哪些不变量?您的域模型中的服务是否会根据其名称的拼写方式而有所不同?

我认为你需要做的是用两种不同的观点来看你的需求收集。您可以查看报告,支持的查询等,以了解您需要在解决方案中包含哪些数据;你需要什么状态。

但对于聚合,有趣的问题是关于状态如何变化,以及哪些状态限制了可能发生的变化。

换句话说,聚合的工作不是封装一堆相关的状态,而是拒绝那些会以违反不变量的方式改变该状态的命令。

  

我可以将更改从一个聚合根级联到另一个

对于“cascade”的数据库事务含义,编号

聚合的基本概念,它是状态和规则的集合,不需要向外看。只需查看团队的状态即可验证对团队聚合的任何更改;团队聚合之外的任何更改都可以忽略团队中的任何状态。

因此,如果您的想法是“当对服务进行此更改时,那么应该对团队进行更改...如果团队无法更改,则必须回滚对服务的更改”,这是相当于发现你的界限在错误的地方。

BUT

对聚合的更改通常会对其他聚合产生影响。也许这样的场景就像“我们退役了这项服务,因此团队已经放弃了支持它的责任,因此有能力接受新的职责。”

受挫的例子;抱歉。

如果Service和Team是单独的聚合,那么我们将查看两个不同的命令:Service.decommission()和Team.freeCapacity()。

要调用Team.freeCapacity(),常见的解决方案是发布“域事件”ServiceDecommissioned。订阅该事件的事件处理程序(通常称为“进程管理器”)标识相应的团队,并调度freeCapacity命令。

注意:团队仍然对自己的不变量负责;它可能会拒绝freeCapacity命令,如果这样做会引入内部不一致。

流程管理员在使用的解决方案中尤为常见。

答案 1 :(得分:0)

Imho这应该是可行的和有效的。你的问题可能来自于你有一个循环引用,一个循环,有点。

我画了一张图片,不能在这里输入,但考虑一个有4个主要方向的圆圈:

  N  
W   E  
  S

或者,对于您的不同组件:

     Team  
Service   Role
     Claim  

圆形,明智的。团队接触服务和角色,服务接触团队和索赔等。每个组件总是触及其他2个组件。

Imo你应该使用" slot"解决组件中的每个元素(我称之为4层"组件",因此你有4个组件)。

你实现了一个"插槽思维",因为你当然也有每个插槽的多次出现 - 需要一种方法来管理它们,添加新的,删除多余的插槽,以及首先更新"指针" (让我们这样称呼它)从一个组件的任何部分到另一个组件的任何部分。哦,好像,这样:

Service components housekeeping (the [ ] is a "slot", a "list in a list")
(upper row indexes into Team slots, lower row indexes into Claim slots:

    [ ][1 3 4][ ][1 2 5][ ][ ]
    [ ][99 112 18 23 66 21][ ][1][ ][ ]

显然,您的服务位置1,3,5和6是空的。如果出现新服务,您可能需要使用最低的空闲插槽(1)。如果所有广告位都被占用,您可以在列表末尾附加一个新内容并抓住它。

显然,您的服务位置2分位于队列位置1,3和4 显然,您的服务时段2点在索赔槽99,112,18,23,66和21处 显然,服务插槽2和插槽4都指向Team插槽1.因此,Team slot 1将指向服务插槽[2 4]。

查看系统?更新组件时,

  1. 将组件本身更新为其他2个组件的插槽索引。
  2. 顺时针访问组件并更新它的逆时针插槽。
  3. 逆时针访问组件并更新它的顺时针插槽。
  4. Setps 2和3:由于多个插槽可能指向多个其他插槽(即服务,正如我们现在所说)组件的插槽,您必须遍历整个插槽列表,ofc。,以便没有指针是遗忘。

    然后你可以随时解决你需要的任何东西,并且圆圈保持不变。您可以随时跳入圆圈,然后浏览它,即。遵循依赖的路径。