3

我正在为一家电信公司的大型系统工作。我是DDD的新手,很难将不同的部分连接在一起。我们目前的系统是使用NHibernate构建的。它目前有超过600个表格,所有的数据访问都是使用NHibernate完成的,但是对于新系统我们将使用EF。以下是几个功能区域和每个功能区域中数据库表格的示例。如何聚合存储库?

顾客
-----> CustomerDemographics
-----> CustomerPayments
-----> CustomerTransactions

RoutingEngine
-----> InboundRoutes
- ---> OutboundRoutes

ProvisioningEngine
-----> InboundSwithces
-----> OUTB oundSwitches
-----> RouterConfigs
-----> GatewayConfigs

BillingEngine
-----> InboundTraffic
-----> OutboundTraffic

由于该系统具有为单元测试,我开始用存储库模式抽象实际实体。一种方法是为每个数据库表创建一个存储库对象。当然,所有这些存储库类都可以从通用存储库接口派生。但是,这会在代码库维护方面增加相当多的开销。在DDD中,我读到了关于Aggregates的这个概念,但我不确定应该如何将它专门应用于EF的上下文中。聚合对象应该是这些存储库的容器,还是更多的是相关上下文的容器(意味着沿着Bounded DbContexts的行)?

回答

6

一种方法是为每个数据库 表创建一个存储库对象。

在DDD中,伴随着持久性无知的概念,数据库表通常不与存储库进行一对一映射。相反,存储库应该与集合一一对应。

当然,所有这些存储库类都可以从通用的 存储库接口派生。

存储库模式可能是一个光滑的斜坡。虽然封装很好,但很容易被不必要的抽象带走。看看here为另一种视角。

应该总结的对象是这些存储库的容器或 是这些更相关的上下文(意思是沿界DbContexts线的东西 )的容器?

在DDD中,您称为“功能区”的字段被称为bounded contexts(BC)。 (在EF中不是DbContext)。另外,聚合不是存储库的容器,它们包含来自域模型的一组相关实体。定型的例子是销售订单模型,其中您有一个订单集合,它由订单集合根和各种实体以及订单行项目等价值对象组成。如上所述,聚合是存储库应该提供访问的域对象。因此,你应该围绕总量构建你的仓库,但是当然首先你必须确定你的总量和BC。看看Effective Aggregate Design by Vaughn Vernon

此外,在一个BC中有600个表格看起来太多了,这是一个潜在的迹象,表明您有多个BCs参与其中。 BCs实现的是functional cohesion,这反过来又是对您的资源库进行分组(将DDD术语“聚合”为冲突)的最合适的方式。

+0

谢谢。关于“你应该围绕总量构建你的仓库”,你可以在你的答案中添加任何它的例子。我只是想听听我应该如何组织这些聚合体。 – imak

+0

单个存储库应该负责域模型中的单个聚合。所以如果客户是一个聚合,你会有一个CustomerRepository等等。关于如何识别和设计总量的问题,请看看有效总量设计的链接。 – eulerfx

2

DDD中的聚合是一致性边界 - 事务一致性的孤岛。如果在域模型中有一组对象应该保持事务一致并且可以被视为一个有意义的概念整体,那么您可能有一个聚合。在整个聚合中,你可以有最终的一致性。

如果您正在进行新的开发,我会建议最初在对象中建模您的域,然后计算出数据库模式应该作为以后的传递。

我会建议将您的一个巨大模型分解为许多更专业化的领域模型,或许沿着广泛的功能领域,仔细地注意每个模型要处理的关键业务场景(例如,您试图与每个模型解决)。每个模型需要围绕它有一个良好的边界(即它应该在明确定义的有界上下文内),明确属于一个模型的属性和属于另一个模型的属性。这通常通过将模型边界与某种子系统边界对齐来实现(从结构上讲)。