DDD-聚集大量子节点的根


10

首先,我会说我对DDD相对陌生,所以在这里我可能会犯一些基本错误!

我从事的项目涉及会计和交易(从财务角度而言)的概念。一个帐户可以针对它输入许多交易。

在我看来,“帐户”和“交易”都是实体,并且“帐户”是包含交易的汇总根,因为没有该帐户就无法存在“交易”。

但是,当我将其应用到代码中时,我立即遇到了问题。在许多情况下,始终拥有帐户中每个交易的列表对我来说并不是特别有用。我对能够执行诸如计算帐户余额和强制执行不变性(例如信用额度)之类的操作感兴趣,但是我也希望能够轻松处理一部分交易(例如,显示日期范围内的交易)。

在后一种情况下,如果我使用,则TransactionRepository可以有效地访问所需的那些对象,而无需加载整个列表(可能非常大)。但是,这将允许除帐户以外的其他事物与事务一起使用,这意味着我已经破坏了帐户作为聚合根的概念。

人们如何处理这种情况?您是否只接受为聚合根加载潜在大量子代所带来的内存和性能影响?

Answers:


9

我建议您谨慎对待“不能没有它”的规则。这涉及到UML / OO设计中的组合概念,并且可能是原始DDD蓝皮书(不确定这一点)中设计聚合的规定方法之一,但此后已进行了很大的修订。从事务一致性边界的角度来看您的聚合可能是一个更好的主意。

这样做的想法既不会使聚合过大,也不会导致性能问题(如您指出的问题),也不会太小,因为某些不变量将不可避免地跨越多个聚合,从而导致聚合锁定和并发问题。

正确的合计大小将理想地匹配您在给定的业务交易中所做的修改的轮廓,不要多也不少。在您的示例中,如果跨多个金融交易的域不变式不多,那么Transaction单独使用“聚合根”可能是最好的解决方案。


谢谢,我将继续阅读一致性界限。我认为您建议将“交易”作为其自身的总根可能是一个好主意;正如您所说,我在跨多个事务中没有很多不变性。
krixon 2015年

7

tl; dr-如果需要,请打破规则。DDD不能解决所有问题。实际上,它给出的目标思想是很好的建议和良好的开端,但是对于某些业务问题而言确实是错误的选择。考虑一下如何做事的提示。


对于将所有子项(事务)与父项(帐户)一起加载的问题-好像您遇到了许多ORM已解决的n + 1问题(对Google而言)。

您可以通过延迟加载子级(事务)来解决它-仅在需要时才可以。

但是听起来您已经知道,通过提及可以使用TransactionRepository解决问题。

要“隐藏”该数据以使只有Account可以使用它,您甚至不需要将其存储在其他人无法反序列化的位置,例如公共关系表。您可以将其与帐户的“文档”一起存储在文档数据库中。无论哪种方式,如果有人足够努力,他们仍然可以看到数据。并与之“合作”。当您不看时,他们会的!

因此,您可以设置权限,但是随后,您必须将“帐户”作为一个单独的过程运行。

您在这里真正意识到的是,DDD和纯粹使用对象模型有时会使您陷入困境。坦白说,当然,您不必使用“组合” /聚合根即可受益于DDD的设计原理。当您遇到适合其约束的情况时,这只是一件事。

有人可能会说“不要及早优化”。不过,在这种情况下,您知道答案了-将有足够的交易来冻结一种方法,该方法将使这些交易永远保留在帐户中。

真正的答案是开始站起来SOA。在我的工作场所,我们观看了Udi Dahan的“分布式计算”视频,并购买了nServiceBus(这只是我们的选择)。为帐户提供服务-具有其自己的流程,消息队列,仅能看到的对关系数据库的访问权,以及...中提琴,您可以在程序中对SQL语句进行硬编码,甚至抛出几个Cobol交易脚本(当然),但是比起最聪明的OO / Java snob梦dream以求的,严重地存在更多的关注点分离。

无论如何,我建议您对其进行建模。通过将服务视为微型绑定的计数扩展,您可以在这里获得聚集根的好处而不会出现问题。

当然,这有一个缺点。您不仅可以在服务之间和服务之间以及它们之间进行RPC(Web服务,SOAP或REST)RPC,或者由于时间耦合而获得称为“结”的SOA反模式。您必须使用通信模式的反转,也称为“ Pub-Sub”,它就像事件处理程序和事件引发程序一样,但要使用(1)进程之间(如果它们在一个机器上过载,则可以放在单独的机器上)。

真正的问题是,您不希望某个服务需要从另一个服务获取数据来“阻止”或等待-您必须启动并忘记该消息,并让程序中其他地方的处理程序将其拾取以完成处理。这意味着您必须改变逻辑。nServicebus可以自动执行“ saga”模式来帮助解决其中的某些问题,但最后,您必须开发出不同的编码样式。您仍然可以做所有事情,只是必须做不同的事情!

Arnon Rotem-Gal-Oz的《 SOA模式》一书回答了许多与此有关的问题。包括使用“活动服务模式”在需要时定期将外部服务中的数据复制到您自己的数据中(本来需要许多RPC,或者在发布/预订生态系统中链接不可靠/不可靠)。

只是为了预览,UI 确实必须RPC到服务中。报告是由服务数据库提供的报告数据库生成的。有人说不需要报告,应该以另一种方式解决问题。对此讲话表示怀疑。

最后,并非所有事物都能正确地归类为一项服务。世界不是依靠馄饨代码运行的!因此,您将不得不违反规则。即使您永远不必这样做,项目的新开发人员也可以在离开时完成它。但是不用担心,如果您能做得到,遵循规则的85%会使程序变得更易于维护。

哇好长


感谢您的详细答复,我一定会对SOA进行一些阅读。
krixon 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.