【问题标题】:Domain Driven Design Precise Aggregate Definition领域驱动设计精确聚合定义
【发布时间】:2017-12-17 22:05:47
【问题描述】:

聚合

聚合是一组关联对象,在数据更改方面被视为一个单元。聚合由边界划分 它将内部的对象与外部的对象分开。每个 聚合有一个根。根是一个实体,它是唯一的 可从外部访问的对象。

在阅读 DDD Quickly 一书时,这是聚合的建议定义。但是,当我在 youtube 上解析一些视频时,特别是:

DDD 和 REST - 网络领域驱动 API - Oliver Gierke

他对聚合的定义如下:

实体 + 存储库 = 聚合

他还建议我们为每个属性子类化字符串,我认为这与 DDD 解决复杂性的目标相反。如果我们有 100 个属性怎么办?

因此,我认为我的问题是双重的。 Repository 是聚合的一部分,还是仅仅是基础设施层的聚合持久化的载体?第二,为了实现可读性而增加软件的复杂性和可维护性是谨慎的做法,还是整体上这种做法有利于 DDD 的目标?

【问题讨论】:

    标签: domain-driven-design ddd-repositories


    【解决方案1】:

    聚合是关于领域的:它代表给定专业领域的特定主题。

    相比之下,存储库是一个关心持久性的技术事物。因此,存储库确实属于域,它是一个能够使用聚合的实用程序。

    所以,不,存储库不属于聚合。您可能还对this question 感兴趣,了解详情。

    关于您的第二个问题:这在很大程度上取决于您的应用程序以及您使用的编程语言……如果您使用动态类型语言(例如 JavaScript),您仍然可以进行 DDD,但您将无法对事物进行子类化(将 ES2015 class 关键字放在一边,因为它不会为 ES 带来真正的面向对象编程)。

    除此之外,DDD 是一种对领域进行建模的方法,并允许跨学科团队就该领域进行更好的沟通。它不是关于技术的(当然,除非你的领域实际上技术;-))。

    由于子类化是一个技术问题,它与 DDD 无关。如果有的话,它与如何实现使用 DDD 创建的模型有关,但这与 DDD 本身无关。

    您可能对Modeling with your team from the wolkenkit documentation 感兴趣,它描述了如何执行 DDD 的方法以及注意事项。

    请注意,我是wolkenkit, a CQRS and event-sourcing framework for Node.js and JavaScript 的作者之一。所以请对最后一段持保留态度。

    【讨论】:

    • 非常感谢。这几乎就是我从阅读中提取的内容。我认为关于 DDD 是什么、它应该如何正确实施,特别是它的真正目标是什么,存在很多困惑。我肯定会回顾你推荐的阅读材料。再次感谢。
    • PS:既然您显然发现答案很有帮助,请您点赞并标记为已接受?
    • 我已经这样做了,但是由于我是该平台的新手,因此并没有改变答案。它说我需要至少 15 声望。唉,我只是一个帕达恩。大声笑。
    【解决方案2】:

    是聚合的存储库部分

    不,完全分开

    属于基础设施层的聚合被持久化的载体?

    也不完全是这样。

    存储库的主要作用是充当应用程序和数据之间的边界。 blue book 中关于存储库的原始讨论引入了具有集合语义的存储库;如果数据只是存储在内存集合中,则存储库的接口与您将使用的接口相同。

    其次,是谨慎增加软件的复杂性和可维护性以实现可读性,还是这种反击有利于整体 DDD 的目标?

    不是“可读性”,而是“交流”;见blue book第2章

    在没有通用语言的项目中,开发人员必须为领域专家翻译...... .

    在这种情况下,复杂性是从领域中提取的复杂性——我们可能不应该想象我们可以使用一两个领域不可知的抽象来用一千个细微不同的概念对领域进行建模。

    你是不是说你相信子类化字符串仅仅是为了可读性,尽管它可能会导致数百个额外的类将是一种谨慎的方法,因为它可以作为共同语言的催化剂

    当然不是子类化,不。但我主张为每个独特的概念(在域中)使用一个唯一的名称(在代码中),即使这些概念共享共同的表示。

    举一个简单的例子,Time 不是Money,即使在两者的底层表示都是long 的情况下。

    Scott Wlaschin 的Domain Modeling Made Functional 包含一个扩展示例。有一次,他将已验证的电子邮件地址未验证的电子邮件地址建模为彼此明显不同;尽管它们都具有底层字符串表示,但他仍然采取步骤为它们中的每一个创建单个案例联合类型,以在代码中捕捉这两个概念不能相互替代的事实。

    这种“复杂性”实际上只是将代码工件与领域专家无处不在的语言保持一致。

    现在,根据您在哪个Blub 中进行编码,您的代码工件可能会增加创建这些不同名称的复杂性;正如 Scott 演示的那样,它在 F# 中非常直接,但在您通常的工作语言中可能并不那么直接。我的感觉是,如果您选择的语言在建模中引入了复杂性,那么也许您应该首先查看是否有另一种语言更适合该任务。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-01
      • 2013-09-16
      • 1970-01-01
      • 2019-06-27
      • 2011-04-26
      相关资源
      最近更新 更多