3

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

客户
-----> CustomerDemographics
-----> CustomerPayments
-----> CustomerTransactions

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

ProvisioningEngine
-----> InboundSwithces
-----> OutboundSwitches
-----> RouterConfigs
-----> GatewayConfigs

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

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

4

2 回答 2

6

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

在 DDD 中,由于忽略了持久性的概念,数据库表通常不会与存储库进行一对一的映射。相反,存储库应该与聚合是一对一的。

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

存储库模式可能是一个滑坡。虽然它非常适合封装,但很容易被不必要的抽象带走。在这里查看另一种观点。

Aggregate 对象应该是这些存储库的容器,还是这些更多的是相关上下文的容器(意味着类似于 Bounded DbContexts 的内容)?

在 DDD中,您所说的“功能区域”似乎被称为有界上下文(BC)。(不是 EF 中的 DbContext)。此外,聚合不是存储库的容器,它们包含一组来自您的域模型的相关实体。典型示例是销售订单模型,其中您有一个订单聚合,该订单聚合由订单聚合根和各种实体和值对象(例如订单行项目)组成。如上所述,聚合是存储库应提供访问的域对象。因此,您应该围绕聚合构建存储库,但当然首先您必须确定聚合和 BC。看看Vaughn Vernon 的《有效聚合设计》

此外,在单个 BC 中拥有 600 张桌子似乎太多了,这可能表明您有多个 BC 在玩。BC 实现的是功能凝聚力,这反过来又是最适合对存储库进行分组(“聚合”与 DDD 术语冲突)的方式。

于 2012-10-16T17:22:49.867 回答
2

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

如果您正在进行新的开发,我建议您首先在对象中对您的域进行建模,然后再确定数据库模式应该是什么。

我建议您将一个巨大的模型分解为许多更专业的领域模型,也许沿着功能领域的广泛线,仔细注意每个模型打算处理的关键业务场景(即您试图用每个模型解决哪些困难的业务问题)。每个模型都需要有一个良好的边界(即它应该在明确定义的有界上下文中),其中清楚什么属于一个模型,什么属于另一个模型。这通常是通过将模型边界与某种子系统边界(从架构上讲)对齐来实现的。

于 2012-10-17T04:49:30.507 回答