我正在尝试DDD + CQRS,我无法理解如何处理这个域逻辑重复问题:
首先,关于跨域的重复:
场景1: 假设我有一些处理办公室员工的应用程序。我有三个有限的背景:程序员部门,QA部门和审计部门。每个BC都有自己的AR:“程序员”,“测试者”,“工人”。它们有99%的不同,每个都有不同的逻辑,但是,每个都有“Name”,“Surname”和一个简单的方法“getFullName”,它们将这两个结合起来。
问题1:我如何(以及我应该?)使每个AR中的常用方法不重复?
最简单的答案可能是制作一些共享的“人类”类,并使这3个AR派生自它,但这违背了DDD的想法,因为“QA部门”永远不需要“getFullName”方法但需要一些其他“共享”方法。因此,此解决方案将使用未使用的方法使域发送垃圾邮件。
现在关于CQRS代码重复:
场景2:数据库包含发票。每张发票都有“sum”和“tax”字段。在“显示发票”页面中,我需要显示含税的发票金额。因此,在我阅读的模型中,我需要做“total = sum + tax”来向最终用户展示它。但是,用户可以按“批准”按钮,这应该说,在一些其他数据库(会计或其他)中注册发票金额。所以,在我的写作模型中,我将再次需要做“总计=总和+税”。
问题2:我如何(我应该?)删除此类重复内容?
当然,这是一个简单的场景,但在分析了我的一些现实应用程序后,我发现使用CQRS需要在不同的地方进行大量重复,因为有很多地方可以根据数据计算最终结果存储在数据库中,这是在查询和命令操作上完成的。
有什么想法吗?我错过了什么吗?
答案 0 :(得分:5)
EmployeeJoinedCompanyEvent
包含其全名)。任何计算都应该是您的域模型的一部分。包含在实体,值对象或域服务中。
任何计算的结果 - 在此示例中为总计 - 然后包含在从域发布的事件中。读取和写入数据存储都可以从已发布事件中包含的值进行更新。他们不应该自己做任何计算。
例如,如果域发布InvoiceApprovedEvent
,它将包含读取模型所需的所有数据。包括总和税和总金额。
事件也是有界上下文之间集成的主要手段。因此,如果您需要更新会计有界上下文或外部系统,您可以从发票有界上下文订阅相关事件,并在收到事件时处理这些事件。
我强烈建议实施DDD和CQRS的一些资源(假设您已熟悉Eric Evan的DDD书籍)。
答案 1 :(得分:3)
情景1
像主数据管理这样的事情往往是它自己的有限背景。这是员工的姓名,出生日期等所属的地方。其他有界上下文以及各种读取模型可以从那里直接或间接地检索它们的数据。
场景2
如果您只是创建简单的总和,我不介意在上下文中有一些重复。一旦你有更复杂的计算方法,它们应该与它们各自的有界背景明确相关联。在您的示例中,可能存在 Invoicing 有界上下文,是与发票相关的算法,计算和服务所属的自然场所。然后,将从那里传播发票的创建和批准,以填充受影响的读取模型。