使用DDD和CQRS处理领域逻辑的重复性[英] Handling duplication of domain logic using DDD and CQRS

本文是小编为大家收集整理的关于使用DDD和CQRS处理领域逻辑的重复性的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我正在尝试DDD + CQR,我无法理解如何处理此域逻辑重复问题:

首先,关于跨域重复:

方案1: 假设我有一些可以处理办公室员工的应用程序.我有3个有界环境:程序员部门,质量检查部和审计部.每个卑诗省都有自己的AR:"程序员"," Tester"," Worker".它们的99%不同,每个逻辑都不同,但是,每个逻辑都具有"名称","姓氏"和一个简单的方法" getfullname",它使这两个融合了.

问题1:我如何(我应该?

最简单的答案可能是使一些共享的"人类"类,并使这三个AR从中衍生出来,但这违背了DDD的想法,因为" QA部门"永远不需要" getfullname"方法,但需要一些方法其他"共享"方法.因此,该解决方案将使域用未使用的方法垃圾邮件.

现在关于CQRS代码重复:

方案2:数据库包含发票.每个发票都有"总和"和"税"字段.在" Show Invoice"页面中,我需要以税款显示发票总和.因此,在我的阅读模型中,我需要进行" Total = SUM +税"才能将其显示给最终用户.但是,用户可以按"批准"按钮,可以说,应该在其他数据库(会计或其他内容)中注册发票总和.因此,在我的写入模型中,我将再次需要做"总计= sum +税".

问题2:我如何(我应该?)删除这种重复?

当然,这是一个简单的情况,但是在分析了我的一些现实生活应用程序之后,我看到使用CQR需要在不同的地方进行大量重复,因为在许多地方可以根据数据计算最终结果存储在数据库中,这是在查询和命令操作上完成的.

有什么想法吗?我想念什么吗?

推荐答案

方案1

  1. 将代码复制并粘贴到三个有界环境中的每个上下文中.
  2. 为共享库中包含的名称创建值对象,该名称封装了获取全名的逻辑.
  3. 创建负责管理员工详细信息的员工有限上下文.然后,任何其他有限的上下文都可以将其用于查找员工的详细信息.将发布事件以确保有限上下文之间的一致性(例如EmployeeJoinedCompanyEvent包含其全名).

方案2

任何计算都应是您域模型的一部分.包含在实体,价值对象或域服务中.

然后将任何计算的结果 - 在本示例中总计 - 随后包含在从域发布的事件中.读取和写入数据存储都可以从已发布事件中包含的值中更新.他们不应该自己进行任何计算.

作为一个例子,如果域发布InvoiceApprovedEvent,它将包含读取模型所需的所有数据.包括总税和总金额.

事件也是有限上下文之间集成的主要手段.因此,如果您需要更新会计有限的上下文或外部系统,则将订阅从发票有限上下文中的相关事件并处理收到的事件.

参考

我强烈建议实施DDD和CQR的一些资源(假设您已经熟悉Eric Evan的DDD书).

其他推荐答案

方案1

经常类似主数据管理之类的东西将是其本身的有限上下文.这是员工的姓名,出生日期等的地方.其他有限的上下文以及各种读取模型可以从那里(直接或间接)检索其数据.

方案2

如果您只是创建简单的总和,我不介意在上下文中进行一些重复.一旦有了更复杂的计算方法,它们应该与各自的有限上下文相关联.在您的示例中,可能有一个发票有限的上下文,是与发票相关算法,计算和服务所属的自然场所.然后将从那里传播发票的创建和批准以填充受影响的读取模型.

本文地址:https://www.itbaoku.cn/post/627411.html

问题描述

I'm experimenting with DDD + CQRS and I can not understand how to handle this domain logic duplication problems:

First, about duplication across domains:

Scenario 1: Let's say I have some application which handles office employees. I have 3 bounded contexts: Programmer department, QA department and Audit Department. Each BC has it's own AR: "Programmer", "Tester", "Worker". They are 99% different, with different logic in each, however, each of those have "Name", "Surname" and a simple method "getFullName" which concatinates those two.

Question 1: How do I (and should I?) make that the common method is not duplicated in each AR?

Easiest answer is probably to make some shared "Human" class, and make those 3 ARs derive from it, but that is against the idea of DDD, as "QA Department" could never need the "getFullName" method but need some other "shared" method. Therefore this solution will make the domain spammed with unused methods.

Now about CQRS code duplication:

Scenario 2: Database contains invoices. Each invoice has fields "sum" and "tax". In "show invoice" page I need to show invoice sum with tax. Therefore in my read model I will need to do "total = sum + tax" to show it to the end user. However, user can press "approve" button, which should, let's say, register the invoice sum in some other database (accounting or something). So, in my write model I will once again need to do "total = sum + tax".

Question 2: How do I (and should I?) remove this kind of duplication?

Sure, this is a simple scenario, but after analyzing some of my real life applications I see that using CQRS would require lots of heavy duplication in different places, as there are lots of places where the end result is calculated from the data stored in database, and that is done both on query and command operations.

Any ideas? Am I missing something?

推荐答案

Scenario 1

  1. Copy & paste the code into each of the three bounded contexts.
  2. Create a Value Object for names contained within a shared library that encapsulates the logic of getting a full name.
  3. Create an Employee bounded context responsible for managing employee details. Any additional bounded context can then use this for looking up an employee's details. Events would be published to ensure consistency between bounded contexts (e.g. EmployeeJoinedCompanyEvent containing their full name).

Scenario 2

Any calculations should be part of your domain model. Contained within the Entities, Value Objects or Domain Services.

The result of any calculations - total in this example - are then included in the Events that are published from the domain. Both read and write data stores can be updated from the values contained within the published events. They should not be doing any calculation themselves.

As an example, if the domain publishes an InvoiceApprovedEvent it would contain all data necessary for the read model. Including the sum tax and total amounts.

Events are also the primary means of integration between bounded contexts. So if you need to update an Accounting bounded context or external system, you would subscribe to the relevant events from the Invoicing bounded context and handle the events as they are received.

References

A couple of resources that I can highly recommend for implementing DDD and CQRS (assuming you're already familiar with Eric Evan's DDD book).

其他推荐答案

Scenario 1

Quite often something like Master Data Management would be a bounded context of its own. This is where an employee's name, date of birth, etc. would belong. Other bounded contexts as well as the various read models could retrieve their data (directly or indirectly) from there.

Scenario 2

If you're merely creating simple sums I'd not mind having some duplication across contexts. Once you have more complex means of calculation they should be clearly associated with their respective bounded context. In your example there could be an Invoicing bounded context, being the natural place where invoicing-related algorithms, calculations and services belong. The creation and approval of invoices would then be propagated from there to populate the affected read models.