91

イベントを強調するアーキテクチャのコマンドとイベントの違いは何ですか?私が見ることができる唯一の違いは、コマンドは通常、システム外のアクターによってソース/呼び出されるのに対し、イベントはシステム内のハンドラーやその他のコードによってソースされるように見えることです。しかし、私が見た多くのサンプルアプリケーションでは、それらは異なる(しかし機能的に類似した)インターフェースを持っています。

4

9 に答える 9

177

コマンドは拒否できます。

イベントが発生しました。

これがおそらく最も重要な理由です。イベント駆動型アーキテクチャでは、発生したイベントが何かが起こったことを表していることに疑問の余地はありません。

さて、コマンドは私たちがやりたいことであり、イベントは起こったことなので、これらに名前を付けるときは別の動詞を使用する必要があります。これにより、個別の表現が促進されます。

コマンドは通常、システム外のアクターによってソース/呼び出されますが、イベントはシステム内のハンドラーやその他のコードによってソースされているようです。

これは、それらが別々に表されるもう1つの理由です。概念の明確さ。

コマンドとイベントはどちらもメッセージです。ただし、これらは実際には別個の概念であり、概念は明示的にモデル化する必要があります。

于 2011-02-11T00:07:46.657 に答える
13

イベントは過去からの事実です。

コマンドは単なる要求であるため、拒否される場合があります。

コマンドの重要な特徴は、単一のレシーバーによって1回だけ処理される必要があることです。これは、コマンドがアプリケーションで実行する単一のアクションまたはトランザクションであるためです。たとえば、同じ注文作成コマンドを複数回処理しないでください。これは、コマンドとイベントの重要な違いです。多くのシステムまたはマイクロサービスがイベントに関心を持っている可能性があるため、イベントは複数回処理される可能性があります。'msdn'

于 2019-03-24T14:28:11.147 に答える
9

また、ここで公開されているすべての回答に加えて、イベントハンドラーは、イベントが発生したという通知を受信した後、コマンドをトリガーできる場合があります。

たとえば、Customerを作成した後、いくつかのアカウント値なども初期化するとします。CustomerARがEventDispatcherにイベントを追加し、これがCustomerCreatedEventHandlerオブジェクトによって受信された後、このハンドラーはコマンドのディスパッチをトリガーできます。必要なものは何でも実行します。

また、DomainEventsとApplicationEventsがあります。違いは単に概念的なものです。最初にすべてのドメインイベントをディスパッチする必要があります(一部のイベントはアプリケーションイベントを生成する場合があります)。これはどういう意味ですか?

CustomerCreatedEventが発生した後にアカウントを初期化することは、DOMAINイベントです。お客様に電子メール通知を送信することは、アプリケーションイベントです。

それらを混ぜてはいけない理由は明らかです。SMTPサーバーが一時的にダウンしている場合でも、ドメイン操作がその影響を受ける必要があるという意味ではありません。それでも、アグリゲートの破損していない状態を維持する必要があります。

私は通常、アグリゲートルートレベルでディスパッチャにイベントを追加します。このイベントは、DomainEventsまたはApplicationEventsのいずれかです。両方である可能性があり、それらの多くである可能性があります。コマンドハンドラーが完了し、コマンドハンドラーを実行するコードにスタックに戻ったら、ディスパッチャーをチェックして、他のDomainEventをディスパッチします。これがすべて成功したら、トランザクションを閉じます。

アプリケーションイベントがある場合は、それをディスパッチするときです。電子メールを送信するために、データベースへの接続を開いたり、トランザクションスコープを開いたりする必要はありません。

元の質問から少し外れましたが、イベントが概念的にどのように異なる方法で処理されるかを理解することも重要です。

それからあなたはSagasを持っています....しかしそれはこの質問の範囲から外れています:)

それは意味がありますか?

于 2016-12-28T18:57:59.720 に答える
8

いくつかの例、特にGreg Youngのプレゼンテーション(http://www.youtube.com/watch?v=JHGkaShoyNs)を実行した後、コマンドは冗長であるという結論に達しました。それらは単にユーザーからのイベントであり、そのボタンを押しました。これらはデータであり、将来のビューで使用するかどうかわからないため、他のイベントとまったく同じ方法で保存する必要があります。ユーザーがそのアイテムを追加してから後でバスケットから削除するか、少なくともしようとしました。後でこの情報を使用して、後日ユーザーにこのことを思い出させることができます。

于 2014-12-01T10:04:22.137 に答える
2

それらは非常に異なるものを表すため、別々に表されます。@qstarinが言ったように、コマンドは拒否できるメッセージであり、成功するとイベントが生成されます。コマンドとイベントはDtoであり、メッセージであり、エンティティを作成するときに非常によく似ている傾向がありますが、それ以降は必ずしもそうとは限りません。

再利用が心配な場合は、コマンドとイベントを(メッセージ)ペイロードへのエンベロープとして使用できます。

class CreateSomethingCommand
{
    public int CommandId {get; set;}

    public SomethingEnvelope {get; set;}
 }

しかし、私が知りたいのは、なぜあなたは:Dを尋ねているのですか?つまり、コマンド/イベントが多すぎますか?

于 2011-02-11T14:32:51.893 に答える
2

上記の概念上の違いに加えて、一般的な実装に関連する別の違いがあると思います。

イベントは通常、イベントキューをポーリングする必要があるバックグラウンドループで処理されます。イベントの処理に関心のあるパーティは、通常、イベントキュー処理の結果として呼び出されるコールバックを登録できます。したがって、イベントは1対多の場合があります。

コマンドをそのような方法で処理する必要がない場合があります。コマンドの発信者は通常、コマンドの目的のエグゼキュータにアクセスできます。これは、たとえば、エグゼキュータへのメッセージキューの形式である可能性があります。したがって、コマンドは単一のエンティティを対象としています

于 2016-07-05T11:39:28.433 に答える
2

これらの素晴らしい答えに追加するだけです。カップリングの違いを指摘したいと思います。

コマンドは特定のプロセッサに向けられます。したがって、コマンドイニシエータおよびプロセッサとの依存/結合にはある程度のレベルがあります。

たとえばUserService、新しいユーザーを作成すると、に「SendEmail」コマンドが送信されますEmailService

UserServiceが必要であることを知っているという事実EmailService、それはすでに結合しています。EmailServiceAPIスキーマを変更したり、ダウンしたりすると、関数に直接影響しますUserService


イベントは特定のイベントハンドラーに向けられません。したがって、イベント発行者は緩く結合されます。どのサービスがそのイベントを消費するかは関係ありません。イベントのコンシューマーが0であることも有効です。

たとえばUserService、新しいユーザーを作成すると、「ユーザー作成イベント」が公開されます。潜在的に、EmailServiceはそのイベントを消費し、ユーザーに電子メールを送信する可能性があります。

ここでは、UserServiceは認識していませんEmailService。それらは完全に分離されています。ダウンした場合、またはビジネスルールを変更した場合は、EmailService編集するだけで済みます。EmailService


どちらのアプローチにもメリットがあります。純粋にイベント駆動型のアーキテクチャ設計は、特に大規模なシステムでは結合が緩すぎるため、追跡が困難です。また、コマンドヘビーアーキテクチャには高レベルの結合があります。したがって、バランスが取れていることが理想的です。

それが理にかなっていることを願っています。

于 2020-08-13T21:22:42.023 に答える
1

quentin-santinの答えに追加するものは、次のとおりだと思います。

リクエストをオブジェクトとしてカプセル化することで、さまざまなリクエストでクライアントをパラメータ化し、リクエストをキューまたはログに記録し、元に戻せない操作をサポートできるようにします。

ソース

于 2016-12-28T02:54:28.327 に答える
0

コマンドに基づいて状態を再計算することはできません。一般に、コマンドは処理されるたびに異なる結果を生成する可能性があるためです。

たとえば、GenerateRandomNumberコマンドを想像してみてください。呼び出されるたびに、異なる乱数Xが生成されます。したがって、状態がこの数値に依存している場合、コマンド履歴から状態を再計算するたびに、異なる状態が得られます。

イベントはこの問題を解決します。コマンドを実行すると、コマンド実行の結果を表す一連のイベントが生成されます。たとえば、GenerateRandomNumberコマンドはGeneratedNumber(X)、生成された乱数をログに記録するイベントを生成できます。これで、イベントログから状態を再計算すると、コマンドの特定の実行によって生成されたのと同じ番号を常に使用するため、常に同じ状態になります。

言い換えると、コマンドは副作用のある関数であり、イベントはコマンドの特定の実行の結果を記録します。

注:監査またはデバッグの目的で、コマンドの履歴を引き続き記録できます。重要なのは、状態を再計算するには、コマンドの履歴ではなく、イベントの履歴を使用するということです。

于 2020-03-21T11:29:59.610 に答える