【发布时间】:2013-10-01 16:13:32
【问题描述】:
构建复杂的制造管理系统。我有几十个实体,其中一些似乎有意义,因为子聚合其他显然没有。
请允许我按重要性顺序列出各种实体:
- 工单
- 报价
- 发票
- 保修
- 认证
- 不合格
- 运费
- 串行日志
- CeriLog
- 序列
- 返工
- 消耗品
- RepairLineItem
这些只是与我的问题最相关的一些。
所有这些(发票除外)仅与工作订单 (TrackingID) 相关。
一个工作订单可以存在而没有任何不合格、保修等,唯一的例外是序列 - 一个工作订单必须至少有一个序列。
返工将聚合它自己的序列集合,这些序列是在事实之后创建的,必须属于返工。
工作订单可能没有报价单,但报价单至少需要访问 Consumable 和 RepairLineItem(用于统计工作范围的总和)
最初,我将所有这些实体建模为 Workorder/AR 的聚合,但这种设计糟糕透顶,因此我开始使用自己的存储库为每个实体创建自己的聚合根。但是,通过这样做,我现在失去了强制执行约束的能力。
例如,当创建工作订单时,它具有固定数量的序列,由批准的手册规定。检查员可以打开或关闭这些序列。然后打印该工作订单旅行者并锁定该工作订单以防更改。有时需要添加新序列,以纠正错误或因为原始手册缺少关键步骤 - 这是在创建返工并将新序列添加到工作订单时。
添加这些序列后,需要通知工作订单聚合根,以便分析更改,并可能重新安排预计完成时间。
同样,工单有一套维修项目或消耗品清单(后者可在检查后随时添加)。如果其中任何一个实体的数量发生变化,则必须渗透回必须通知报价汇总的工作订单,以便可以更新总成本并通知相关方通过电子邮件通知。
显然,拥有一个单一的 AR 是没有意义的(尤其是从性能的角度来看——这是作为基于 AJAX Web 的应用程序实现的)。工作订单的存储库将使用以下方法进行复杂化:
selectAllConsumablesForWorkOrder()
selectAllRepairItemsForWorkOrder()
selectAllCertificationsForWorkOrder()
...
我的问题是,鉴于上述场景和要求,我如何在执行这些不变规则的同时使用更小的聚合根?如果一切都被 WorkOrder/AR 封装,我可以看到如何轻松执行上述要求。
我对 DDD 的理解远非完美,所以请温柔:)
我可能对 AR 的全部内容有错误的印象,但我读过的大多数文章似乎都在暗示这一点,使用产品和多行项目示例。这实际上是这个工作订单的内容,但每个行项目可能由其他聚合共享......
任何经验或意见表示赞赏
问候, 亚历克斯
【问题讨论】:
标签: domain-driven-design aggregateroot