14

特にイベントが他のイベントの発生をトリガーする可能性がある場合に、EventStore からイベントを再生してモデルを再構築するときに何が起こるべきかについて頭を悩ませています。

たとえば、10 回購入したユーザーを優先顧客に昇格させ、特定のプロモーションを提供する電子メールを受け取る必要があります。

そのユーザーのモデルを再構築するたびに電子メールが送信されるのは明らかに望ましくありませんが、10 番目の を再生するときに、これが発生しないようにするにはどうすればよいPurchaseMadeEventでしょうか?

4

3 に答える 3

11

イベント チェーンは非常に扱いにくく、簡単に制御不能になる可能性があるため、できるだけ避けたいと思います。たとえば、あなたが説明しているシナリオでは、UserPromotedEvent(おそらくを使用してPromoteUserCommand)を発生させますが、実際の/物理的な電子メールの送信をドメインの一部とは見なしません。代わりに、追加のハンドラー/デノーマライザーを作成しUserPromotedEventて、おそらくいくつかの追加のチェックで電子メールを送信する必要性を登録します。その後、別のプロセスがまだ処理されていない電子メールの情報を収集して送信します。このアプローチにより、完全にアクセス可能/スケーラブルでない電子メール ゲートウェイで発生する可能性がある問題が軽減されます。

より一般的には、イベント チェーンの必要性は、多くの場合、プロセスにSagaを実装することを検討する必要があることを示しています。

于 2011-09-06T07:12:00.597 に答える
8

イベント ハンドラーからイベントを発生させるべきではありません。代わりにサガを使用する必要があります。

あなたの場合、サガはサブスクライブしてCOMMANDPurchaseMadeEventを発行します。PromoteCustomerこれにより、CustomerPromotedイベントが発生します。CustomerPromotedここでも、イベントをサブスクライブしてコマンドを送信する別のサガがありますSendEmailToPromotedCustomer。イベントを再生しているときは、イベントのサガをサブスクライブしないでくださいCustomerPromoted

これはすべて、コマンドとイベントの違いに関するものです。それを理解することが重要です。イベントはすでに起こったことを伝え、コマンドはこれから何が起こるかを伝えます。

于 2011-09-06T12:38:03.223 に答える
3

イベントを再生するとき、それらのイベントの生成に伴うすべてのドメイン ロジックを再生しているわけではありません。通常、ドメイン メソッドでイベントを発生させます。そのイベントの発生により、そのドメイン オブジェクトの全体的な状態が更新されます。

例えば:

public class Purchase {
  private int _id;
  private string _name;
  private string _address;
  private double _amount;

  public Purchase(int id, string name, string address) {
    //do some business rule checking to determine if event is raised

    //perhaps send an email or do some logging
    //etc.
    if (should_i_raise_event) {
      ApplyEvent(new PurchaseMadeEvent() {
        ID = id,
        Name = name,
        Address = address
      });
    } 
  }

  public UpdatePurchase(int id, double amount) {
    //more checking to see if event is to be raised
    if (should_i_raise_event) {
      ApplyEvent(new PurchaseUpdatedEvent() {
        ID = id,
        Amount = amount
      });
    }
  }

  protected void OnPurchaseMade(PurchaseMadeEvent e){
    _id = e.ID;
    _name = e.Name;
    _address = e.Address;
  }

  protected void OnPurchaseUpdated(PurchaseUpdatedEvent e){
    _id = e.ID;
    _amount = e.Amount;
  }
}

この例では、イベントが再生さOnPurchaseMadeれると、ドメイン オブジェクト コンストラクターではなく、イベント ハンドラーが実行されます。と同じPurchaseUpdatedEvent- イベントを発生させたドメインメソッドではなく、イベントハンドラーが実行されます。

このイベントには、ドメイン モデルを更新する (そして更新を読み取りモデルに適用する) ために必要なすべてが含まれています。実行されるドメイン メソッドによって、イベントを発生させることができるようになります。

これが役立つことを願っています。さらに情報を提供する必要がある場合はお知らせください。

幸運を!!

于 2011-09-05T22:46:09.053 に答える