c# - 如何对存在于所有限界上下文中并且是应用程序核心部分的实体进行建模?

标签 c# design-patterns domain-driven-design cqrs bounded-contexts

我正在使用 DDD 原则制作应用程序。在尽可能多地考虑所有事情之后,我决定开始制作我的限界上下文。我还没有设置最终结构,但截至目前,我的应用程序将包含以下限界上下文:

  1. 员工管理
  2. 采购
  3. 归档
  4. 报告

我希望它尽可能地可插拔,这样我就可以分别开发和维护它们。他们可能会公开 WCF 或 Web API 以与它们交互。

我将使用 Udi Dahans implementation of a simple CQRS pattern .我不想一直使用事件源、消息总线等,因为这不是一个高度协作的应用程序(少于 1000 个用户,他们不太可能编辑相同的小数据集),这会增加了很多不必要的复杂性。

所以问题:

The employee and department entities are common for all BC, how to model that?

部门是组织结构的一部分,因此在员工管理 BC 中,员工在一个部门工作,他们可以管理一个部门,并且他们有他们工作过的部门的历史。

在采购 BC 中, cargo 从一个部门采购,然后交付给一个部门。供应商与不同部门有不同的契约(Contract)。

在存档中,一些信息将被存档并绑定(bind)到一个部门,等等。

这同样适用于员工。

How to persist the data from the bounded contexts?

它们可以映射到同一个数据库或者每个都有自己的数据库。

到目前为止我的一些想法

如何建模
我是否应该再创建一个 BC,称为“公司”或“组织”,并在那里管理部门?

根据上面引用的 Udi Dahans 文章,我应该为每个 BC 创建一个部门实体和一个员工实体,其中只包含该 BC 所需的字段和行为。这听起来很合理,但后来我在考虑如何实际使用它,但我想不通。我需要访问在其他地方管理的部门,但我该怎么做才能做到这一点而不混淆我的 BC?

如何使用?
假设我通过查询从某处获得我的部门列表。在用户界面中,我得到了我也想购买的部门列表。这是这个部门的第一次采购,所以采购 BC 还不知道这个部门......所以采购 BC 中的部门对象将填充从另一个 BC 维护的数据 - 那么我如何坚持这个?我是否需要添加一些信息,例如送货地址和发票地址(如果不存在)?

在“注册部门 UI”中,我是否应该在所有 BC 上调用“RegisterDepartment”服务,然后确保这些服务与通过 UI(MVC Controller )所做的所有更改同步?

员工也是如此。我想知道哪个员工进行了购买或将某些东西放入了文件。所以不知何故,我也需要这些 BC 中的员工对象,但从不同的 BC 管理它们。

坚持
上面的一些挑战可以通过将不同的员工对象映射到数据库中的同一个表来解决。 Purchasing BC 和 Archive BC 不能注册新员工,而是将信息附加到那里的员工,并将他们绑定(bind)到同一数据库中的其他对象。然后数据库将确保所有 BC 仍然生活在同一个世界中......

我需要建议,这样我才不会最终做出一些以后很难维护的东西。

最佳答案

看来你的大部分疑惑都围绕着:“单个现实生活中的对象如何被不同的限界上下文共享?”

问题是,尽管实体相同,但每个 BC 对它们的处理方式不同。在 Employee Management BC 中,整个权重都集中在 Employee 和 Department 实体上——您应该能够添加、修改、相互分配、保留历史记录并处理与管理有关的所有业务逻辑。您可以实现一些保留员工个人数据、维护适当的官方结构或维护某些责任的政策。

另一方面,Purchase 上下文中的部门实体仅表示发票地址,也可能是负责部门的人员,而关注中心将是构建订单。所有与购买过程没有直接关系的数据都应该放在不同的上下文中。例如,如果域要求每个订单都必须连接到部门并且缺少发票详细信息,则采购上下文不应尝试自行填充它们。相反,可以通知员工管理层以填补缺失的部分。

请注意,它很可能发生在同一个应用程序甚至同一个窗口中。但是您必须确保它会通过员工管理上下文发生,即通过调用上下文公共(public) API。

附带说明一下,我不知道你的领域,但你可能想重新考虑你的上下文边界,例如将交付与购买分开。

继续使用并按照您的示例进行操作,如果您想购买,我会考虑以下路径:

  • 读取必要的部门数据(让我们稍后再说“如何”),您可能想检查此时是否存在所有数据
  • 阅读可以购买的商品,根据您的领域,可能值得介绍另一个 BC,例如供应商。以上这些都是CQRS的“查询”部分
  • 构建订单或任何其他必要的购买上下文实体,执行验证或任何其他逻辑
  • 提交更改,保留购买上下文实体(“命令”部分)
  • 创建和发布一些领域事件(例如通知 Archive 或 Reports)

最后但同样重要的是,您不应该关心领域层中的全局持久性。每个 BC 都应该连接到一些数据访问或基础设施层,以提供必要的对象并处理诸如从何处获取它们等细节。

特别是,实体不一定需要镜像数据库布局,存储在一个数据库还是多个数据库应该只是一个性能问题。例如,一些实体将引用相同的对象(例如员工姓名),但可以从完全不同的表或数据库中获取其他详细信息(即购买历史或发送到存档的元素)。你可以使用类似 NHibernate 的东西使其易于管理。

关于c# - 如何对存在于所有限界上下文中并且是应用程序核心部分的实体进行建模?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13530557/

相关文章:

c# - 使用C#Nest查询ElasticSearch

java - 如何在 Java 中实现复合模式?

java - 具有泛型的构建器

c++ - 通过前向声明隐藏实现

domain-driven-design - DDD,值对象和ORM

c# - 如何使用聚合根内部数据库中的数据填充子实体?

sql - 更新语句与 ASP.NET MVC4 中的 FOREIGN KEY 约束冲突

c# - 如何通过代码获取TFS工作项验证错误信息?

c# - 基于接口(interface)的编程的独立示例和详细说明

c# - 返回字节数组作为具有 Image/png 内容类型的 Http 响应