【问题标题】:How granular should a domain event be?域事件应该有多精细?
【发布时间】:2014-07-13 00:57:35
【问题描述】:

我想知道域事件的粒度应该是多少?

例如,我有一些简单的事情,比如在个人资料页面上更改名字、第二个名字和电子邮件地址。我应该有 3 个不同的域事件还是只有一个?

当我添加一个新特性时,通过粗粒度的域事件,我必须创建一个新版本的事件,所以我必须添加一个新的事件类型,或者将事件版本存储在事件存储中。通过细粒度的领域事件,我没有这些问题,但是我有太多的小类。您认为,在这种情况下,最佳做法是什么?

【问题讨论】:

    标签: domain-driven-design cqrs event-sourcing


    【解决方案1】:

    我可以同意 MikeSW 的回答,但是在建模过程中应用 SRP,最终可以得到小班,这完全不是问题。

    根据Greg Young,领域事件应该始终表达用户从业务角度所做的事情。例如,如果用户有 2 个理由更改她的电话号码 PhoneNumberChanged,并且从业务角度来看,此信息可能很重要,那么我们应该创建 2 个事件类型 PhoneNumberMigratedPhoneNumberCorrected 以在技术上存储相同的数据。这显然违反了 DRY,但这不是问题,因为 SRP 在这些情况下可以覆盖 DRY,就像它通过在多个有界上下文之间共享聚合及其属性(最常见的是聚合 id)一样。

    在我的例子中:

    我有一些简单的事情,比如更改名字, 个人资料页面上的 secondName 和电子邮件地址。

    我们应该问以下问题:用户为什么要这样,从我们业务的角度来看有什么重要性?

    • 她的帐户被盗(安全问题,不是业务问题)
    • 她转移到另一个电子邮件地址
    • 她结婚了
    • 她讨厌她以前的名字
    • 她故意将帐号交给其他人
    • 等等……

    好吧,如果我们有约会代理服务,那么记录离婚可能具有商业重要性。所以如果这个信息真的很重要,那么我们应该把它放到领域模型中,并创建一个UserProbablyDivorced 事件。如果它们都不重要,那么我们可以简单地说,她只是想更改她的个人资料页面,我们不在乎为什么,所以我认为在这种情况下UserProfileChangedUserSecondNameChanged 事件都可以接受。

    领域事件可以与命令成 1:1 和 1:n 关系。他们以 1:1 的关系命名通常与命令相同,但使用过去时。例如ChangeUserProfile -> UserProfileChanged。通过 1:n 关系,我们通常将命令所代表的行为分解为一​​系列较小的域事件。

    因此,总而言之,领域事件的粒度应该由领域开发人员决定,但它应该受到业务角度的明显影响,而不仅仅是从数据模式建模的角度。但我认为这很明显,因为我们正在为业务建模,而不仅仅是数据结构。

    【讨论】:

    • 你把事情弄得有点乱。 CQRS 与事件溯源 (ES) 无关,但它们一起使用。您不会为 ES 设计域事件,因为您并不总是使用 ES,而且我不同意事件应该始终表达用户意图。事件捕获 更改,无论是什么触发了它们。 PhoneNumberMigrated 和 PhoneNumberCorrected 是从域的角度来看的,而不是用户的。领域专家不是编码员,(s)他不知道命令/事件是什么。开发人员将根据与领域专家的讨论决定事件的结构
    • 在编写一行代码之前决定所有事情肯定是瀑布式的,而且这是一种过于死板的 IMO 方法。你知道,开发人员不是那种只会大量编写代码的业务无知的猴子。开发人员必须在编码之前了解领域,但开发人员进行建模而不是领域专家(除非他们是同一个人)。所以我必须说开发者与它息息相关。
    • 反对“在 DDD 和 CQRS 中,这些法律可能并不总是有效的地方”。这是不正确的。 DDD、ES 和 CQRS 也是不同的东西。 “使用 CQRS 设计应用程序”作为一个声明并没有真正的意义。
    • @Roysvork 随意添加您的答案。
    • @MikeSW 我不是指瀑布。你仍然可以提前发布,经常发布,只是总是先设计你的新特性应该有什么命令、查询和领域事件,然后在你有一个完整的模型之后再实施。
    【解决方案2】:

    很多类有什么问题?真的,为什么这么多开发者害怕有太多的类?您可以根据需要定义尽可能多的类。

    域事件表明域以某种方式发生了变化。它应该包含所有相关信息,并且应该考虑到事件也是 DTO 的事实。您想要明确的事件,但由开发人员决定事件的粒度或通用性。

    大小不是问题,但是如果您的事件“权重”为 1 MB,则可能有问题。而且类的数量不是领域事件设计的标准。

    【讨论】:

    • 谢谢,我要找的词是粒状的。
    • "很多类有什么问题?" - 为每个属性更改定义一个类对我来说有点奇怪......我不知道,这是一种直觉......:D Btw。拥有 3-4 个属性的小班是可以的,但是对我来说,拥有一个具有单个属性的 DTO 就不行了。
    • 你能再具体一点吗?通过我给出的个人资料更改示例,您会怎么做?
    • 您没有为每个属性更改定义一个类,您为每个域更改定义一个类,可以是一个或多个属性
    • 我同意你的看法@MikeSW。我现在正面临这种情况,对我来说,细粒度的事件似乎更合乎逻辑。 IMO 要考虑的事情是事件类应该包含所发生事件的所有细节,不多也不少。如果我们考虑“人员”,那么我们可以定义一个包含 n 个字段的 PersonChangedEvent 或一个 PersonNameChangedEvent。如果我们定义了一个包含许多字段的 PersonChangedEvent,那么实际上知道哪些确切的字段已经/已经被更改可能会有问题。到目前为止,我更赞成 PersonNameChanged。但实际上这一切都“取决于”:)
    猜你喜欢
    • 1970-01-01
    • 2010-11-27
    • 2016-07-13
    • 1970-01-01
    • 2019-04-04
    • 1970-01-01
    • 2010-09-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多