Events 事件来源。在哪里生成事件粒度?

Events 事件来源。在哪里生成事件粒度?,events,event-sourcing,Events,Event Sourcing,我开始从DDD的角度学习EventSourcing。关于EventSourcing的一个声明是,它允许通过重播事件重播应用程序的状态,甚至将应用程序置于以前的状态(过去的状态) 我意识到它增加了复杂性,并且与其他解决方案相比具有优势。我真正关心的是事件发生在哪里。前端还是后端 我将用一个例子来解释它 假设我的应用程序由前端和后端组成,它是关于用户的。用户表示可以如下所示(我将使用JSON表示,尽管问题不是格式或语言特定的): 第一个问题: 假设我从前端创建了一个用户。我的服务器接收以下信息: {

我开始从DDD的角度学习EventSourcing。关于EventSourcing的一个声明是,它允许通过重播事件重播应用程序的状态,甚至将应用程序置于以前的状态(过去的状态)

我意识到它增加了复杂性,并且与其他解决方案相比具有优势。我真正关心的是事件发生在哪里。前端还是后端

我将用一个例子来解释它

假设我的应用程序由前端和后端组成,它是关于用户的。用户表示可以如下所示(我将使用JSON表示,尽管问题不是格式或语言特定的):

第一个问题:

假设我从前端创建了一个用户。我的服务器接收以下信息:

{
    id: 1,
    name: "aName",
    age: 20,
    description: "aDescription"
}
是否应发出以下事件?CreatedEvent、NameChangedEvent、AgeChangedEvent、DescriptionChangedEvent

在这种情况下,前端生成的事件(只有一个)与后端生成的事件(四个)不同

或者应该发出具有所有属性的CreatedEvent?在这种情况下,后端中的事件类似于前端事件(仅一个)


执行更新时也会发生类似的问题。如果我从前端一次更改多个属性,我应该在后端创建一个包含所有这些更改的事件,还是应该将这些更改拆分为多个事件?如果我必须在多个事件中拆分这些更改,我必须检查实体(用户)的当前状态,以检查属性是否已更改。

您仍在思考
CRUD
。在
CQRS
中,您不设置属性,而是执行
命令。那些
命令
对您的域模型有意义;它们被发送到
聚合
,如果不变量成立,则验证并执行它们;如果没有,它们将被拒绝

我意识到它增加了复杂性,并且与其他解决方案相比具有优势。我真正关心的是事件发生在哪里。前端还是后端

事件由聚合生成,聚合可能在后端执行。前端可能只创建发送到后端的命令

是否应发出以下事件?CreatedEvent、NameChangedEvent、AgeChangedEvent、DescriptionChangedEvent

应该发出什么事件取决于不变量。在您的特定情况下,业务规则允许
用户
出生时没有
姓名
年龄
说明
?如果没有,则必须在
CreateUserCommand
中输入所有必需字段,可能还有可选字段,并发出完整的
UserWasCreated(id、username、age、description)
。但并不禁止以类似事务的方式发出多个事件,只要它们被持久化(不要求使用事务,要求持久化是原子的:所有事件都被持久化或无)。你应该发出一个或四个大事件?这取决于这些事件的监听者感觉如何,因为它与聚合无关:聚合将接收它发出的内容,并且足以重建其内部状态

事件生成的粒度可能取决于您是否允许像
ChangeUserName
这样的粒度命令;如果您允许这样的命令,那么此命令将发出
UserNameChanged
事件

我真正关心的是事件发生在哪里。前端还是后端

答案取决于记录簿在哪里。如果事实是由服务本身决定的,那么记录簿就是服务的持久存储——在这些情况下,事件通常在后端生成

如果真相是在服务边界之外(在另一个服务中,或在真实世界中)确定的,那么事件通常是在更接近真相来源的地方生成的

如果我们在做数据输入,我们可能是在描述现实世界中的某些东西,而不是模型控制的东西。对我来说,这听起来像是一个前端用例

假设我从前端创建了一个用户

CRUD动词是一种代码气味——它们通常表示对域的理解肤浅,或者编码人员试图用泛型语言替换特定于域的语言

有时,它们暗示您实际上是在构建一个数据库,而不是一个服务,这暗示您的服务不是记录簿,而是一个持久存储。同样,这种拼写表明前端正在捕获事件,并将它们传递给后端

<>你可能想在你的名字拼写中小心,因为你经常在他们的生命周期中间的实体的快照中工作(EX:“用户”已经存在了20年,但是我们只是在捕捉他们当前的状态,而不是他们的整个历史)。 是否应发出以下事件?CreatedEvent、NameChangedEvent、AgeChangedEvent、DescriptionChangedEvent

不是一般的,不是。变化通常以原子方式表示

执行更新时也会发生类似的问题。如果我从前端一次更改多个属性,我应该在后端创建一个包含所有这些更改的事件,还是应该将这些更改拆分为多个事件

看。编辑通常不是无中生有,但通常有一个可能引起业务兴趣的原因(我们是否更正了错误的输入?现实世界是否发生了变化,使我们以前的数据无效?)。有多个事件包含对同一组字段的更改是完全合理的

{
    id: 1,
    name: "aName",
    age: 20,
    description: "aDescription"
}