33

スタック オーバーフロー ドメインの問題と、次のイベントの定義を想定します。

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? */);
        ...
    }
}

私の質問は、質問をしたユーザーの名前を見つけるにはどうすればよいですか? または、より一般的な: 非正規化された読み取りモデルが特定のイベントに存在しない追加データを必要とする場合、イベントをどのように処理すればよいですか?

Greg Young の SimpleSQRS やMark Nijhof のFohjinサンプルなど、 CQRSの既存のサンプルを調べました。しかし、それらはイベントに含まれるデータのみで動作しているように思えます。

4

3 に答える 3

26

個人的には、イベント ハンドラー内からユーザー名を検索しても問題はないと思います。しかし、ユーザーの読み取りモデルから名前を照会できない場合は、UserRegistered イベントを処理するために、QuestionEventsHandler に追加のイベント ハンドラーを導入します。

そうすれば、QuestionEventsHandler はユーザー名の独自のリポジトリを維持できます (ユーザーの電子メールを保存する必要はありません)。次に、QuestionAsked ハンドラーは、独自のリポジトリーから直接ユーザーの名前を照会できます (Rinat Abdullin がストレージは安価であると言ったように!)。

さらに、QuestionItem 読み取りモデルはユーザーの名前を保持するため、QuestionItem 内の名前フィールドが最新であることを確認するために、QuestionEventsHandler 内で UserNameChanged イベントも処理する必要があります。

私には、これは「イベントを充実させる」よりも労力が少なく、システムの他の部分とその読み取りモデルへの依存関係を構築しないという利点があります。

于 2012-02-06T14:29:09.043 に答える
4

必要なすべての情報でイベントを充実させるだけです。

私が思い出したように、グレッグのアプローチは、この方法でイベントを作成および保存/公開しながら、イベントを充実させることです。

于 2010-11-03T08:29:55.847 に答える
1

EventStore からイベントをプルします。

注意 - 読み取りモデルには、EventStore への読み取り専用アクセスが既に必要です。読み取りモデルは使い捨てです。それらは単にキャッシュされたビューです。読み取りモデルはいつでも削除/期限切れにすることができ、ReadModel を EventStore から自動的に再構築できます。そのため、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 リポジトリが真の EventStore である必要はありませんが、そうなる可能性もあります。分散システムの利点は、必要に応じて、ReadModel の近くで EventStore を簡単に複製できることです。

これとまったく同じシナリオに遭遇しました...単一のイベントで利用できるよりも多くのデータが必要でした. これは、新しい ReadModel に初期状態を設定する必要がある Create タイプのイベントに特に当てはまります。

読み取りモデルから: 他の読み取りモデルからプルできます。ただし、ビューがビューに依存する依存関係の泥の大きなボールがビューに依存するため、これはお勧めしません。

イベントの追加データ: ビューに必要なすべての追加データでイベントを肥大化させたくはありません。ドメインが変更され、イベントを移行する必要があると、本当に困ります。ドメイン イベントには特定の目的があり、状態の変化を表します。データを表示しません。

お役に立てれば -

ライアン

于 2012-01-11T20:12:48.987 に答える