具有多个数据库的复合.NET应用程序的DDD / CQRS

时间:2011-05-17 11:35:04

标签: domain-driven-design cqrs

我承认我仍然是DDD的新手,使用CQRS更是如此。我也意识到DDD和/或CQRS可能不是解决每个问题的正确方法。不过,我喜欢校长,但在当前项目的背景下有一些问题。

该解决方案是一个模拟器,可根据当前配置生成性能数据。管理员可以创建和修改模拟规范。测试人员设置了一些环境条件并运行模拟器。结果被捕获,汇总和报告。

该解决方案由3个组件区域组成,每个区域都有自己的用例,域逻辑和支持数据结构。因此,模块化设计似乎是一种分离逻辑和单独关注点的方式。

  1. 第一个区域是管理方面,允许用户创建和修改规范。这将是一个CRUD重型“模块”。
  2. 第二个区域是执行模拟。域模型将类似于第一个区域,但针对执行模拟进行了优化,而不是提供方便的编辑模型。
  3. 第三个领域是报道。
从此我相信我有三个边界上下文,是吗?我有三个明确的应用入口点,三组域逻辑和三个不同的数据模型来支持域逻辑。

我的第一直觉是遵循这些行并创建三个模块(程序集),用于封装每个区域的域层。我还应该有三个独立的数据库吗?也许超过三个支持写与读?

我认为这可能是CQRS的首选,但我不确定如何去做。在我看来,CQRS建议一组移动数据的后端流程。但如果是这种情况,并且数据持久性是跨领域的(如DDD建议的那样),那么我的数据访问代码是否需要了解所有域对象?如果是这样,那么拥有单独的模块是否有好处?

最后,我之前没有提到的一点是规范在发布之前被认为是“草稿”,这使得它可用于模拟。我的PublishingService需要了解第一和第二区域的域模型,这样当它响应SpecificationPublishedEvent时,它可以读取规范,转换模型并将其持久化以便执行。这让我觉得我毕竟没有三个有界的背景。或者我在分析中遗漏了什么?

1 个答案:

答案 0 :(得分:1)

你可能有一个模块化的用户界面,但我没有看到你所描述的三个独立的域名。

首先,在CQRS报告中并不直接关注域模型,它是分离的读取模型的一个方面,它负责呈现为报告而优化的域状态。

其次只是因为你在域中发生了不同的事情并不一定是将它们彼此隔离开的理由。我将阅读蓝色DDD书籍,以便更好地了解BC的样子。

我并不太了解您的域名,但我会尝试提供一些一般性的建议。

从您谈论PublishingService的地方开始。我看到一个规范聚合根,它带有一些看起来像CreateNewSpecification,UpdateSpecification和PublishSpecification的命令。

事件看起来很相似,可能感觉多余:SpecificationCreated,SpecificationUpdated,SpecificationPublished。哪种糟糕但CRUD重型模型没有非常有趣的行为。我还建议找到一种自动的方法来处理这个聚合上的模型/模式更改,如果你不使用代码生成,或者处理不需要你的动态*强调文本*方式的变化将是乏味的每次都要建立新的活动。

另外,您可能只考虑不使用事件源来获得这样的聚合根,因为CRUD很重。

你描述的第二件事似乎是开始一个基于规范运行的模拟,并在模拟过程中产生数据(我假设)。事件驱动的体系结构在这里有意义地将报告数据的更新与生成数据的进程分离。如果要生成大量要处理的数据,这将带来巨大的好处。

然而,这听起来并不像是模拟必然会受益于事件采购的AR。有几个原因:

  1. 模拟实际上只需要一个类似于StartSimulation的命令
  2. 模拟然后在其生命周期内生成事件,表示模拟内部发生的事情
  3. 模拟似乎没有收到任何其他可能依赖于模拟的当前状态的命令
  4. 模拟与多个客户/用户不同时进行交互,正如我们所指出的那样,它根本没有真正与之互动
  5. 通常,域建模对每个项目都非常具体,因此很难为您提供构建域模型所需的所有信息。这是因为花费了大量时间来了解用户的需求以及他们试图用软件解决的问题。当您深入了解其流程时,它可能会进行多项改进。