将DDD应用于Northwind数据库

时间:2010-03-04 17:28:23

标签: architecture domain-driven-design ddd-repositories

我想做一些练习并将DDD应用于我应用于Northwind数据库的域模型。即使Northwind是一个例子,我想也是为了满足一些“虚拟业务”的要求。因此,目标是建立一个尊重DDD的域模型,并将数据存储在Northiwnd数据库中。

考虑这个EF持久性模型:

alt text http://blogs.developpeur.org/blogs/tja/NorthwindModel_thumb_4FC6AF51.png

请注意,我们只有实体和双向关系。我想有一个真正的DM尊重DDD。更多,我的DM模型不需要是我的数据库的镜像

  1. 如何改变des关系,在需要时只有一种关系或两种方式。

  2. 是否存在可以更改为一对一的多对一或一对多关系?

  3. 您如何为agregates建模?

  4. 如果需要,值对象,服务和工厂如何?

  5. 我知道我可能会考虑业务需求,看看模型应该如何改变,但希望对此有所了解。

    如果我的问题不明确,请不要犹豫。

    提前致谢。

1 个答案:

答案 0 :(得分:12)

总的来说,我很想回答Mu(在禅宗意义上),因为从DDD的角度来看这个场景是错误的。在DDD中,我们从业务需求和领域专家开始,然后从我们派生的域模型开始。

尽管这是一个有争议的观点,但数据库几乎只是业务需求的偶然工件(几乎总是声明必须保留实体)。

那就是说,我会努力做到最好。

在大多数情况下,订单是一个非常重要的业务对象,显然我们需要知道订单行,包括每行中的产品,所以看起来我们需要从订单行(Order_Detail)到订单行的关联产品

然而,当给定特定产品时,我们很少需要知道它包含在哪个订单中,因此这表明存在单向关系。我们可以从订单行导航到产品,但不能从产品到订单行。

然而,上述分析可能在更深层次上被证明是错误的。想象一下开发人员和领域专家之间的以下对话:

开发 我们已经从订单到产品创建了此关联,以便我们始终以特定顺序了解产品的所有内容。

Exp: 听起来不错,但供应商怎么样?

Dev: 也包括在内。

Exp: 那么当我们更改产品的供应商时会发生什么?

Dev: 这也将隐含地反映在订单数据中......

Exp: 这不是我们想要的。我们希望数据反映我们发货时的订单。

在这种情况下,事实证明数据库模式实际上存在错误。问题可能是由报告引起的,因为业务分析师可能希望生成有关不同供应商如何影响收益的报告(我知道什么)。

这种情况可能建议完全从订单线到产品的关联。订单应包含历史(快照)产品数据,而不是当前产品数据。

我们甚至可能会引入一个ProductSnapshot 值对象,它在语义上镜像Product 实体,以便在域模型中对此进行建模。

总而言之,将Order建模为自身和订单行(使用ProductSnapShots)的聚合似乎越来越合理,但订单与客户之间的关系如何?

由于我目前了解关联和聚合,关联定义聚合。给定订单,我们想了解客户吗?最有可能的。鉴于客户,您想了解订单吗?可能。

这表明双向关系,使Customer 聚合根。这意味着您将拥有CustomerRepository,但没有OrderRepository。每当您需要订单时,您必须通过Customer

获取订单

在某些情况下,这可能是完全合理的,而在其他情况下这可能非常笨重。这实际上取决于业务要求......

您也可以考虑创建OrderRepository,但这会侵入Customer聚合根。如果你这样做,那么对秩序的责任就变得含糊不清。如果您从订单到客户,会发生什么? Customer有一个订单列表,但如果您从OrderRepository读取订单,它们是否都填充在内存中?

可能不是,但如果您从CustomerRepository读取客户,可能就是这样。这里的要点是对聚合根的分析很重要,一旦定义了聚合,就必须坚持并尊重它。

这使我支持小聚合而不是大聚合,所以在这个例子中,我会将聚合约束为Order及其顺序行,并且{{1}之间没有关联}和Order

CustomerOrder之间没有正式关联并不意味着我们根本无法将它们联系起来,但我们需要明确的服务来为我们提供帮助给定客户的订单。我们不能只从一个导航到另一个。

相关问题