イベントソーシングとモデル生成の読み取り
-
27-09-2019 - |
質問
スタックオーバーフロードメインの問題とイベントの次の定義を想定してください。
UserRegistered(UserId, Name, Email)
UserNameChanged(UserId, Name)
QuestionAsked(UserId, QuestionId, Title, Question)
次のイベントストアの状態(外観の順に)を仮定する:
1) UserRegistered(1, "John", "john@gmail.com")
2) UserNameChanged(1, "SuperJohn")
3) UserNameChanged(1, "John007")
4) QuestionAsked(1, 1, "Help!", "Please!")
質問リストの次の非正規化された読み取りモデルを仮定します(SOの最初のページの場合):
QuestionItem(UserId, QuestionId, QuestionTitle, Question, UserName)
次のイベントハンドラー(非正規化された読み取りモデルを構築します):
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? */);
...
}
}
私の質問はです ユーザーの名前を見つけるにはどうすればよいですか 誰が質問しましたか?またはより一般的:非正規化された読み取りモデルには、特定のイベントに存在しない追加のデータが必要な場合、イベントを処理する方法は?
CQRの既存のサンプルを含む既存のサンプルを調べました simplesqrs グレッグ・ヤングの fohjin Mark Nijhofのサンプル。しかし、それらはイベントに含まれるデータでのみ動作しているように思えます。
解決
必要なすべての情報でイベントを充実させるだけです。
グレッグのアプローチは、私が思い出すように、このように作成および保存/公開中にイベントを充実させます。
他のヒント
個人的には、イベントハンドラー内からユーザーの名前を調べることに何の問題もないと思います。ただし、ユーザーの読み取りモデルから名前を照会できない場合は、ユーザーが登録されたイベントを処理するために、QuestionSeventsHandlerに追加のイベントハンドラーを紹介します。
そうすれば、質問Eventshandlerはユーザー名の独自のリポジトリを維持できます(ユーザーのメールを保存する必要はありません)。質問録音されたハンドラーは、ユーザーの名前を独自のリポジトリから直接照会できます(Rinat Abdullinがストレージは安いと言ったように!)。
QuestionSITEM Read Modelがユーザーの名前を保持しているため、質問EventsHandler内のusernameChangedイベントを処理する必要があります。質問項目内の名前フィールドが最新のものであることを確認する必要があります。
私にとって、これは「イベントを豊かにする」よりも努力が少ないようで、 いいえ システムの他の部分とその読み取りモデルへの依存関係を構築します。
イベントストアからイベントを引き出します。
覚えておいてください - 読み取りモデルは、すでにイベントストアへの読み取り専用アクセスを必要としている必要があります。読み取りモデルは使い捨てです。それらは単にキャッシュされたビューです。読み取りモデルをいつでも削除 /期限切れにすることができるはずです - そして、イベントストアからReadModelを自動的に再構築することができます。したがって、あなたのreadmodelbuildersはすでに過去のイベントを照会できる必要があります。
public class QuestionEventsHandler
{
public void Handle(QuestionAsked question)
{
// Get Name of User
var nameChangedEvent = eventRepository.GetLastEventByAggregateId<UserNameChanged>(question.UserId);
var item = new QuestionItem(
question.UserId,
question.QuestionId,
question.Title,
question.Question,
nameChangedEvent.Name
}
}
また、Eventstoreリポジトリは真のイベントストアである必要はありませんが、確かにそうである可能性があります。分散システムの利点は、必要に応じて、必要に応じて再モデルに近いイベントストアを簡単に複製できることです。
私はこのまったく同じシナリオに遭遇しました... 1つのイベントで利用できるよりも多くのデータが必要だった場合。これは、初期状態の新しいReadModelを入力する必要があるCreate-Typeイベントに特に当てはまります。
読み取りモデルから:他の読み取りモデルから引っ張ることができます。しかし、私はこれを本当にお勧めしません。あなたはビューがビューに依存する依存の泥の大きなボールを導入するからです。
イベントの追加データ:ビューに必要なすべての追加データでイベントを膨らませたくありません。ドメインが変更され、イベントを移行する必要がある場合、本当にあなたを傷つけます。ドメインイベントには特定の目的があります - それらは状態の変化を表します。データを表示しないでください。
お役に立てれば -
ライアン