我目前正在开发一个单片系统,我想将其纳入现代,并采用DDD和CQRS。我收到了重新编写解决方案导入机制的请求,并认为这可能是开始重新构建过程的好机会。
目前的流程是:
其他详细信息是多行可能属于同一个实体(例如,2行可能是订单中的订单项,因此会有相同的订单参考号。)
我正在考虑有一个导入传奇,它会生成一堆导入聚合(例如OrderImportAggregate),然后当提交导入时,这些将被转换为当前系统中使用的类,这有望成为聚合他们自己的权利,当重新架构进一步下线!因此,传奇过程将采取以下方式:
由于这是我第一次实施CQRS /事件采购/ DDD,我想从正确的基础开始,所以想知道这是否是这种功能的理想方法?
答案 0 :(得分:2)
我建议您将域名划分为两个单独的子域名,这些子域名实现为分隔有界上下文,一个有界上下文为Import bounded context
(ImportBC
),另一个为receiving bounded context
(ReceivingBC
,实际名称不为我所知,请相应更换。)
然后,在Import BC
中,您应该使用CRUD
样式实现,为每个导入文件创建一个实体,并使用持久性来记住验证的进度和导入过程(此实体包含尚未导入的项目列表)。在人员验证每个项目之后,可以将命令发送到ReceivindBC
中的聚合,以根据业务规则测试聚合是否有效,但不将更改提交到存储库!这样做是为了让人类用户知道该项目是否确实有效并启用/禁用import button
。这样,您就不会在两个有界上下文中复制验证逻辑。当用户实际按下import button
时,将导入命令发送到ReceivingBC
中的聚合,并实际将更改提交到存储库。另外,您从import file CRUD entity
。
这种发送命令但实际上没有持久存储到存储库的技术对于帮助UI
中的用户体验(不在UI
内部重复逻辑)非常有用如果您遵循DDD
最佳实践并将您的聚合设计为纯粹的,无副作用的对象(与存储库无关,不知道它们的存在,根本不使用它们),则是可行的。)
答案 1 :(得分:1)
首先,您必须问问自己为什么使用CQRS。 CQRS是建筑中的重型18轮车。我知道尖叫CQRS的2个充分理由
1)您需要支持撤消功能
2)将来实施新要求时,您也希望将这些要求应用于过去的数据。
然而,您所描述的部分要求与crud非常相似。 (您导入一组行,列出一组行,编辑这些行,然后标记为已完成的行将从其输入状态中删除并转换为其他类型的实体。
如果您觉得描述特定实体和适用的验证规则有很多复杂性,那么DDD将是一个不错的选择。但仍然我会考虑缩小它并构建一个simle mvc风格的应用程序来实现这个(取决于该项目还需要什么)
即使这是一个更大的域的一部分我会建议一个微服务方法,这将是一个完全独立的导入应用程序(在这种情况下,你仍然可以提出一个ImportCompleted事件,并把它放在一个服务总线与多个其他听取那个事件的应用程序)
注意:CQRS不是事件源,cqrs将命令(更新)堆栈与查询堆栈分开。它经常与事件采购结合使用。但是,在任何地方突然出现的事件都可能是一种痛苦,特别是因为提升事件的事件往往不那么明显,以及事件是否有相互影响(如果订单完成和订单取消事件被提升,订单会发生什么? ,可能有时间问题,首先处理一个)
答案 2 :(得分:0)
我不是 DDD 专家,但这是我对此的看法。我不会使用单独的有界上下文,因为在我看来,域对象的导入理想情况下可以与它们所属的有界上下文处于相同的有界上下文中。很想听听专家的意见,为什么会出错!