【问题标题】:Domain Driven Design and aggregates领域驱动设计和聚合
【发布时间】:2013-09-16 08:44:03
【问题描述】:

在我们的系统中,我们有一个数据库,其中许多表具有很多列,在某些情况下超过 300 列。让我们举个例子——一辆车。我们有一个包含 300 列的汽车表。除了汽车的 id 之外,其余列包含与汽车效果相关的数据。右侧座椅的尺寸。

问题是我们如何在不加载所有列的情况下将此表映射到 DDD 聚合?

DDD 表示存储库会加载整个聚合,但在大多数情况下,客户只想查看聚合的一小部分。 car aggregate 也会有很多计算各种事物的方法,有些情况下需要从其他表中加载数据。

我们如何以 DDD 方式实现这一点?域服务?

我们是不是找错树了?我们应该改用 CQRS 吗?

请忽略事实;数据库是一团糟。

【问题讨论】:

    标签: c# domain-driven-design ddd-repositories


    【解决方案1】:

    您的问题似乎是您将聚合和用户希望看到的视图 1:1 映射。仅仅因为我们谈论聚合,它不是 1:1 的视图。 (您自己说过“但在大多数情况下,客户只希望看到汇总的一小部分”)。

    使用 CQRS(或“仅”CQS)的一个好处是您可以专注于域,这意味着您可以从用户/客户的角度为您的命令和视图(eq 查询)建模,而无需考虑您当前的数据库设计。

    看看effective aggregate Design by Vaughn Vernon,可能会有帮助。

    【讨论】:

    • 如果我们看一下写入端,例如,您如何处理 ChangeNumberOfBoltsCommand?该命令采用汽车 ID 和螺栓数。但是存储库是否必须加载整个聚合来更新螺栓的数量?延迟加载似乎违反了 DDD 的“规则”。
    • 这取决于但我认为必须加载整个聚合。我没有使用延迟加载,因为它在针对域进行开发时会导致问题。
    【解决方案2】:

    在简单的 oop 中,如果您发现某些行为只需要字段的子集,您可以将它们提取到另一个 Class 并将实现委托给它。

    在您的汽车案例中,您可以进行相同的重构。然后你可以使用延迟加载:首先加载汽车,并在需要时加载汽车的其他本地实体。我认为这更像是一个基础架构问题,而不是领域驱动设计。

    当然,如果您发现持久性基础架构妨碍您进行建模。您可以使用单独的持久性对象。但这在开始时需要更多资源。

    另一方面,如果您有一个遗留数据库,我认为采用 CQRS 会更难。这可能会给您的团队带来太多负担。

    【讨论】:

      【解决方案3】:

      CQRS 和 DDD 不是互斥的。该领域应专注于行动/计算/“实际”工作。您可能希望使用读取/查询层来获取用户希望查看的数据子集。

      尽量不要查询您的域。如果您发现自己提出了您现在提出的问题,这通常意味着您正在或正在考虑查询该域。这只会导致痛苦。

      所以 DDD 和 CQRS 可以很好地协同工作。 CQRS 也有不同级别,因此您需要正确平衡:)

      【讨论】:

      • 你说的很对,CQRS 和 DDD 并不排斥。我的错。
      • 我喜欢读和写的想法。读取只会使用 OData 或类似方法公开一系列 DTO。写入端(域)可能会使用 DDD。在那种情况下,我必须弄清楚如何处理具有很多属性的聚合(汽车)上的 CRUD 操作。
      最近更新 更多