Domain driven design DDD、BoundedContext、域事件和事务

Domain driven design DDD、BoundedContext、域事件和事务,domain-driven-design,ddd-repositories,Domain Driven Design,Ddd Repositories,我目前正在根据DDD原则为产品/政党管理系统创建概念验证。其中一项要求是,第三方数据(客户、经销商)将存储在web上的CRM中,特定于产品的数据将存储在本地SQL数据库中(见下文) CRM系统(基于Web) 客户(包括姓名、地址、电子邮件、联系人偏好等) 经销商(包含名称、地址、活动状态) 产品系统(内部部署) 基本产品(定义香草产品) 转销商产品(定义转销商将销售的基础产品的定制) CustomerProduct(定义客户注册的产品) 我一直在对如何实现解决方案的不同方法进行大量研究,但我很难

我目前正在根据DDD原则为产品/政党管理系统创建概念验证。其中一项要求是,第三方数据(客户、经销商)将存储在web上的CRM中,特定于产品的数据将存储在本地SQL数据库中(见下文)

CRM系统(基于Web)
客户(包括姓名、地址、电子邮件、联系人偏好等)
经销商(包含名称、地址、活动状态)

产品系统(内部部署)
基本产品(定义香草产品)
转销商产品(定义转销商将销售的基础产品的定制) CustomerProduct(定义客户注册的产品)

我一直在对如何实现解决方案的不同方法进行大量研究,但我很难理解所有概念以及它们如何应用于我的问题

我首先将这些区域划分为两个不同的有界上下文:Party和Product。我为这些上下文中的每一个定义了域模型,其中实体引用了另一个模型中的概念,我将这些作为简单的Guid ID(即产品域中的CustomerProduct将具有相关Guid的CustomerRef值)

然后,我实现了一个使用API调用web CRM的Party基础设施实现和一个使用NHibernate的产品基础设施实现。对于其中的每一个,我都实现了一个UnitOfWork,这样我就可以在每个上下文中控制事务流程。应用层将在运行时注入这两个上下文并使用它们

例如:

  • ApplicationService.RegisterNewProduct(customerId, ProductId)
  • 启动每一个交易单元的交易 工作(PartyUnitOfWork.Begin(), ProductUnitOfWork.Begin())
  • 为每个上下文使用存储库 查找相关的域对象 (一方客户查找(Id), 产品.经销商产品.查找(Id))
  • 执行逻辑以确定 客户合格,产品合格 有效等
  • 创建新的CustomerProduct并保存 产品体系
  • 提交每个工作单元
然后,我开始进一步探索有界上下文,并考虑重构应用程序,使每个上下文对来自另一个上下文的概念有一个有限的表示,但只针对该上下文。i、 e.在产品上下文中,我将拥有一个客户实体,该实体具有Id、名称和活动状态,但可能没有联系人首选项等。然后,我将使用DomainEvents来协调不同系统之间的活动,以使其数据保持最新(即,如果在CRM系统中创建了新客户,则产品系统将引发并处理一个事件,以更新其对客户的表示)。因此,上述示例将发生更改,因此仅使用产品上下文

为了进一步混淆问题,假设“RegisterNewProduct”呼叫也创建了一个新客户,我是否会在产品系统中创建该客户并引发一个“NewCustomer”事件,该事件将由Party系统处理


我有兴趣收集人们对这些想法的评论?

除了我的评论/问题之外,您所描述的UnitOfWork方法还有一个根本问题。您将遇到一系列问题,其中一个单元已提交,另一个单元已失败。您将最终得到一个跨两个上下文的分布式事务

如果您确实需要多个有界上下文,则更好的(主观)方法是在它们之间进行异步、基于消息的通信。您在一个上下文中对聚合执行命令,并在将更改持久化到数据库的同一事务中发布(例如,通过NServiceBus或MassTransit)发生了某事的消息(事件)。另一个上下文接收消息/事件并作出反应

如果你是一个纯粹主义者,你可以将这种方法用于所有聚合间的通信。通过这样做,你可以完全消除拥有一个工作单元的要求


这有什么意义吗?

除了我的评论/问题之外,您所描述的UnitOfWork方法还有一个根本问题。您将遇到一系列问题,其中一个单元已提交,另一个单元已失败。您将得到一个跨两个上下文的分布式事务

如果您确实需要多个有界上下文,则更好的(主观)方法是在它们之间进行异步、基于消息的通信。您在一个上下文中对聚合执行命令,并在将更改持久化到数据库的同一事务中发布(例如,通过NServiceBus或MassTransit)发生了某事的消息(事件)。另一个上下文接收消息/事件并作出反应

如果你是一个纯粹主义者,你可以将这种方法用于所有聚合间的通信。通过这样做,你可以完全消除拥有一个工作单元的要求


这有意义吗?

为什么需要两个概念?在这些上下文中是否有不同含义的术语?如果没有歧义,我会从一个简单的上下文开始,然后将其拆分,如果其大小无法管理。理想情况下,我只需要一个上下文,即一个客户拥有一组CustomerProducts。但是,因为e在这种情况下,客户和客户产品将在不同的系统中,我认为他们需要分开。因此,我将有一个持久层与CRM实体交互,另一个与数据库实体交互。我不确定我将如何构建它,否则,我将有一个持久层可以d通过NHibernate处理对CRM和数据库的访问?我认为如何存储和检索数据是一个技术细节,您应该将此逻辑深入到存储库实现中。为什么d