Dmi*_*ich 28 domain-driven-design cqrs event-sourcing
假设Stack Overflow域问题和以下事件定义:
UserRegistered(UserId, Name, Email)
UserNameChanged(UserId, Name)
QuestionAsked(UserId, QuestionId, Title, Question)
Run Code Online (Sandbox Code Playgroud)
假设事件存储的状态如下(按出现顺序):
1) UserRegistered(1, "John", "john@gmail.com")
2) UserNameChanged(1, "SuperJohn")
3) UserNameChanged(1, "John007")
4) QuestionAsked(1, 1, "Help!", "Please!")
Run Code Online (Sandbox Code Playgroud)
假设以下非规范化读取模型列出问题列表(对于SO的第一页):
QuestionItem(UserId, QuestionId, QuestionTitle, Question, UserName)
Run Code Online (Sandbox Code Playgroud)
以下事件处理程序(构建非规范化读取模型):
public class QuestionEventsHandler
{
public void Handle(QuestionAsked question)
{
var item = new QuestionItem(
question.UserId,
question.QuestionId,
question.Title,
question.Question,
??? /* how should i get name of the user? */);
...
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是如何找到提出问题的用户的姓名?或者更常见的是:如果我的非规范化读取模型需要在特定事件中不存在的附加数据,我应该如何处理事件?
我已经研究CQRS包括现有的样本SimpleSQRS格雷格年轻的Fohjin马克Nijhof的样品.但在我看来,他们只使用事件中包含的数据.
Chr*_*ray 24
我个人认为从事件处理程序中查找用户名是没有错的.但是如果你处于无法从User的读取模型中查询名称的位置,那么我将向QuestionEventsHandler引入一个额外的事件处理程序来处理UserRegistered事件.
这样,QuestionEventsHandler可以维护自己的用户名存储库(您不需要存储用户的电子邮件).然后,QuestionAsked处理程序可以直接从它自己的存储库中查询用户的名字(正如Rinat Abdullin所说,存储很便宜!).
此外,由于您的QuestionItem读取模型包含用户的名称,因此您还需要处理QuestionEventsHandler中的UserNameChanged事件,以确保QuestionItem中的名称字段是最新的.
对我而言,这似乎比"丰富事件"更省力,并且有利于不依赖于系统的其他部分及其读取模型.
只需使用所有必要的信息来丰富活动即可。
我记得格雷格的方法是——在以这种方式创建和存储/发布活动的同时丰富活动。