14

CQRS 設計アプローチ (パターンとアーキテクチャ) を学習して新しいプロジェクトに適用しようとしていますが、重要な部分が欠けているようです。

私のクライアント アプリケーションはクエリを実行し、読み取りモデルから軽量の読み取り専用 DTO のリストを取得します。ユーザーはアイテムを選択し、ボタンをクリックしてアクションを開始します。アクションは、対応するコマンド オブジェクトを作成して書き込みモデルに送信することによって実行されます (コマンド ハンドラーがアクションを実行し、データ ストアを更新するなど)。しかし、ある時点で、変更を反映するために UI を更新する必要があります。アクションの結果としてのアプリケーションの状態。

UI は、元のリストを更新する時期をどのように認識しますか?

追加情報

CQRS について説明しているほとんどの記事やブログでは、例として MVC クライアント アプリが使用されていることに気付きました。私は現在、Silverlight クライアントに取り組んでおり、その場合、パターンが単に機能しないのではないかと考え始めています。

フォローアップの質問

Bartlomiej の応答とその後の議論についてさらに考えた結果、CQRS でのエラー処理について疑問に思いました。コマンドが基本的に起動して忘れる非同期操作であることを考えると、エラー状態を UI に報告するにはどうすればよいでしょうか?

「UI の更新」が次の 2 つの形式のいずれかであることがわかります。

  1. 操作が成功し、データが変更されたため、これらの変更を反映するように UI を更新する必要があります
  2. 操作は失敗し、データは変更されていませんが、ユーザーには失敗と潜在的な修正アクションが通知される必要があります。

MVC で Post-Redirect-Get パターンを使用しても、操作の結果がわかるまで実際にリダイレクトすることはできません。私がこれまで見てきた例のどれも、これらの現実世界の問題に対処していません。

4

4 に答える 4

4

私は、WPF クライアントの同様の問題に苦労してきました。データの再クエリ トリガーは、更新するデータに依存します。コマンドは次のカテゴリに分類される傾向があります。

  1. このコマンドは真のファイア アンド フォーゲット メソッドであり、バックエンドに状態の変更を通知しますが、この変更を UI に反映する必要がないか、変更が UI にとって重要ではないだけです。

  2. このコマンドは、単一のクエリの結果を変更します

  3. このコマンドは、通常 (少なくとも私のドメインでは) 複数のクエリの結果をカスケード方式で変更します。つまり、単一の「高レベル」データの状態を変更すると、多くの「低レベル」キャッシュに影響を与える可能性があります。

私の最初のトリガーはページの読み込みです。ほとんどのページは、最後にアクセスしてからデータが更新されたと想定する必要があるため、これから除外されるアイテムはほとんどありません。一部のシステムは、この方法で財務データやその他の重要なデータを更新するだけで回避できる場合があります.

短いコマンドの場合、コマンドから「成功」が返されたときにもデータを更新します。私見としては、これはほとんど怠惰ですが、すべての CQRS コマンドは非同期で起動する必要があります。それなしでは生きていけないオプションですが、実装でコマンドとクエリの間の待ち時間が長いことが予想される場合は、必要になるかもしれません。

私が利用し始めている 1 つのパターンはメディエーターです (ほとんどの MVVM フレームワークにはメディエーターが付属しています)。コマンドを起動すると、起動されたコマンドを指定するメッセージもメディエーターに送信されます。各キャッシュ (ビュー モデル プロパティRetriever<T>) は、それに影響するコマンドをリッスンし、適切に更新します。1 つのメッセージから不必要に更新されるキャッシュの数を最小限に抑えながら、メッセージの数を最小限に抑えようとします。そのため、(うまくいけば) 最終的には更新理由の短いリストになり、それぞれの「理由」がキャッシュのリストを更新します。

もう 1 つのアプローチは単純な正直さです。システムの更新自体がどのように行われるかをグラフィカルに公開することで、ユーザーはより忍耐強くなることがわかりました。コマンドを実行すると、成功した応答を待っていることを示すいくつかの UI が表示されます。エラーが発生した場合は、再試行を提案するかエラーを表示できます。成功した場合は、関連するフィールドの更新を開始します。このコマンドは別の端末 (あなたが知らない) から起動された可能性があるため、他のマシンによって呼び出された状態の変更が失われないように、データは最終的にタイムアウトする必要があることに注意してください。

皮肉なことに、クライアントでキャッシュと値を更新する唯一の効率的な方法は、ハードコーディングまたはハッシュマップのようなものを使用して、コマンドとクエリを再び分離することです。

于 2012-08-28T11:47:25.370 に答える
2

私の2セント。

MVVM は実際には CQRS に非常によく適合すると思います。ViewModel は単に監視可能な ReadModel になります。

1 - ReadModel のクエリを介して ViewModel の状態を初期化します。

2 - ViewModel の変更は、それにバインドされているすべてのビューに自動的に反映されます。

3 - ViewModel の特定の変更により、コマンドがメッセージ キューに伝達されます。これらのコマンドをサーバーに送信するオブジェクトは、それらのメッセージをキューから取り出し、WriteModel に送信します。

4 - クライアントは整形式である必要があります。つまり、ViewModel はコマンドをトリガーする前に適切な検証を実行する必要があります。コマンドがトリガーされると、クライアントのイベント バスにイベント通知を発行して、変更に関心のあるシステム内の他の ViewModel またはコンポーネントに変更を伝えることができます。これらのイベントは、必要な関連情報を運ぶ必要があります。通常、これは、他のビュー モデルが、取得する必要がある他のデータに依存していない限り、通常、変更の結果として読み取りモデルを再クエリする必要がないことを意味します。

5 - このクライアントが知りたい変更を他のクライアントが行ったときにリアルタイムのプッシュ通知のためにサーバー上のメッセージ バスに接続し、必要に応じてロング ポーリングにフォールバックするオブジェクトがあります。それらを、クライアント上のコンポーネントを結び付ける内部メッセージ バスに伝達します。

6 - 処理する最後の部分は、クライアントがときどき接続される可能性があるという事実です。これは、コマンドが失敗する唯一の理由 (現時点ではインターネット アクセスがない) であり、クライアントに問題を通知する必要があります。

于 2013-11-13T02:06:50.330 に答える
1

ASP.NET MVC 3 では、ユース ケースに応じて 2 つの手法を使用します。

  • CQRS にうまく適合する、既によく知られている Post-Redirect-Get パターン。コマンドをトリガーする MVC アクションは、クエリを実行するアクションへのリダイレクトを返します。
  • 場合によっては、他のクライアントのリアルタイム更新など、ドメイン イベント/メッセージに依存しています。私は、singlarR を使用して、接続されている関心のあるすべてのクライアントに変更をプッシュするイベント ハンドラーを作成します。
于 2012-07-05T07:44:19.377 に答える
0

私が知る限り、あなたが取ることができる2つの主要な方法があります:

1) UI を設計して、ユーザーが変更をすぐに認識しないようにします。たとえば、彼の行動が成功したことを伝え、仕事を続けるためのさまざまな選択肢を提供するメッセージなどです。これにより、readmodel を更新するのに十分な時間が得られるはずです。

2)より複雑ですが、サーバーに送信した情報を保持し、インターフェースに表示する場合があります。

私が推測する最も重要なことは、データがここにない理由を理解できるように、可能であればユーザーを教育することです...まだ!

私は今それについて考えているだけですが、これらは非同期ではなく同期コマンド処理のためのものです。

于 2012-07-09T12:39:53.570 に答える