1

それでは、通常の Order の例を見てみましょう。リッチ ドメイン モデルを仮定すると、Order.place() 呼び出しがあります。最近、このアクションに関連する追加のタスクを実行する方法は、ドメイン イベントを指しているようです。では、この呼び出しが「OrderPlaced」イベントを発生させたとしましょう。イベントが配置された後に発生する通常のことは、確認メールを送信して、このイベントのイベント リスナーを作成し、メールを送信することです。

簡単に: Order.place() > OrderPlaced イベントが発生 > EmailForOrderPlaced リスナーが起動 > メールが送信される

同様の方法で機能する登録もあります (User.register() > UserRegistered イベントが発生 > 登録リスナーが起動 > メールが送信されます)

でも:

問題 (作成されたタスク - 意味をなす必要はありません - しかし、実際のビジネス要件の多くはとにかく意味がありません):

ここで、登録と注文の機能を 1 つにまとめて提供したいと考えています。通常の登録ごとに 1 つのメールと注文用の 1 つのメールではなく、両方を含む 1 つのメールのみを送信したいと考えています。これは誇張された懸念であるため、通常はこれを行うドメイン サービスを作成しますが、User.register(); を呼び出すと、注文. 場所 (); これで、通常どおり 2 つのイベントが発生し、顧客に電子メールがスパム送信されます (そうではありませんが、これは一例です)。

では、どうすればこれを回避できるでしょうか。サービスでイベントを発生させることができるため、結合された電子メールを送信することは明らかに問題ではありませんが、それでも元の 2 つの電子メールが残ります。2 つの呼び出しを実行する前にサービス内の 2 つのリスナーをデタッチすると、実際にはそれらの機能について知る必要があり、新しいリスナーが追加されるたびに、サービスのデタッチにも戻る必要があることを意味します。など、これをシームレスに行うより良い方法はありますか?

4

1 に答える 1

1

いくつかのオプションがあります。

まず、ユースケースを明示的にします。たとえば、UserRegisteredユーザーが注文の作成の一部として登録されたことを示す bool をイベントに追加できます。これにより、電子メール ハンドラが適切な電子メールを送信できるようになります。

もう 1 つのオプションは、両方のイベントの電子メールを送信するハンドラーを作成することです。いずれにせよ、電子メールはすぐに送信されるべきではないため、ハンドラーはコミット時に、特定の作業単位中にどのイベントが到着したかを判別し、この方法で送信する電子メールのタイプを判別します。両方のイベントが到着した場合は、1 つの電子メールを送信します。それ以外の場合は、受信したイベントに対応する電子メールを送信します。これを機能させるには、ハンドラーに作業単位ごとの有効期間があることを確認する必要があります。

最後に、さらに掘り下げて、プレイ中に集約する必要があることに注意してUserくださいOrder。理想的には、特に分散シナリオでは、単一のトランザクション内で集計を変更しないでください。集約への変更が必要なユース ケースを実装するには、プロセス マネージャーとも呼ばれるサガを作成します。サガでは、各集計が独自のトランザクションで変更され、トランザクションの一部として、メッセージが送信されて次のステップに進みます (この場合は 2 つのステップがあります)。サガは、 のような開始メッセージを受け取りますRegisterUserAndCreateOrder。次に、ユーザー、次に注文を登録し、両方が完了すると、適切な電子メールを送信します。ユーザーと注文を同時に作成することもできます。こちらをご覧くださいこのイベント駆動型アプローチの詳細については。

于 2013-05-20T15:43:10.203 に答える