4

私は現在、特定のシステムを構築するときに CQRS を適用できるかどうかを調査しており、簡単に答えを見つけることができないいくつかの質問があります。

コマンドの可用性/検証

ユーザーが特定のエンティティに対して実行できることは、通常、ユーザーの役割だけでなく、この特定のユーザーとこのエンティティ (作成者など) との関係、およびこのエンティティの状態 (公開、アーカイブなど) にも関連付けられます。

私には、CQRS のユーザー アクションは、それらを処理するコマンドにマップされているように見えますが、どのアクションとコマンドが使用可能かを判断する方法が明確ではありません。

すべての読み取りモデルで使用可能なコマンドのリストを返すことは、一貫性が必要なため、ユーザーの役割にのみ関連付けられているコマンド (メニュー項目など) をチェックする必要があるため、不適切に思えます。

もちろん、別のユーザーが状態を変更してコマンドが無効になった場合に備えて、コマンドはトランザクション中に再度検証を行う必要があります)。

要件変更への抵抗

私の経験では、冗長なロジックと特定のビジネス オブジェクトに関連付けられたクラス/テーブルが多すぎるシステムを維持することは悪夢です。

CQRS では、1 つの特定のビジネス エンティティに対して複数の読み取りモデルが存在する場合があります。そのエンティティを変更する必要がある場合は、関連するすべての読み取りモデルも変更する必要があります。

保守性のために、リファクタリング中に簡単に明らかにできる方法でそれらを関連付ける必要があります。

関連する注意点として、過度に具体的なコマンドが多数あると、保守性の問題も発生します-1つのユースケースごとに1つのコマンドが最適に機能するはずであると想定するのは正しいですか?

ドメイン モデルを変更しない読み取りモデルとコマンド

CQRS コマンドでは、読み取りモデルを更新することになっており、ユーザーはその間に古いバージョンにアクセスできます。

私の頭の中で問題を引き起こす2つの特別なケースがあります。

まず、ドメイン モデル自体を変更するのではなく (おそらく状態のみ)、サード パーティのシステム/フレームワーク/電子メールなどを含む何らかの操作を実行するコマンドがあり、場合によっては、これらのコマンドの実行にかなりの時間がかかることがあります。

ここで見たように、ドメイン モデルとコマンド実行状態を組み合わせた読み取りモデルが必要です。この読み取りモデルは、現在処理中のアイテムの履歴またはリストとして使用できます。

次に、いくつかのコマンドが結果を生成します。この結果は、コマンドが正常に完了したときにユーザーに表示する必要があり、場合によっては、しばらくしてから破棄し、ファイルにする必要があります。したがって、これらのコマンドの結果をデータベースに保存し、コマンドの特定のインスタンスに関連付ける方法が必要です。つまり、一時的な読み取りモデルを用意します。

読み取りモデル テーブルとインメモリ キャッシュ

また、第 2 レベルの ORM キャッシュ (クエリ結果用) では、読み取りモデル用のデータベース テーブルを用意する必要はありませんが、ORM はクエリが初めて実行されたときにそれらを生成し、結果をキャッシュして無効にすることができます。モデル エンティティが変更されると、それらは自動的に変更されます。このアプローチは、CQRS インターフェイス/パターンを強制する良い出発点のようですが、変更することができ、おまけとして動的プロジェクションをサポートできます (ユーザーが表示する列などを選択した場合)。

4

1 に答える 1

4

全体として、具体的にどのような質問をされているのかよくわからないので、できる限りお答えします。これが役立つことを願っています。質問の要点を見逃していた場合は明確にします - お知らせください。

コマンドの可用性/検証:

この部分に対するあなたの質問が何であるかはわかりませんが、基本的に、ユーザーの行動によって、使用できるコマンドが決まります。その特定のユーザーに対してコマンドが有効かどうかは、コマンドを送信する UI のコントローラー (または任意のメカニズム) によって処理されるか、コマンドを受信するドメインによって処理されます。コマンドには、ドメインがそれを評価し、状態を変更してイベントを発生させるのに十分な情報が含まれている必要があります。

要件変更への耐性:

エンティティが変更された場合、関連するすべての読み取りモデルを変更する必要があるわけではありません。実際には、その読み取りモデルの目的に依存します。読み取りモデルを維持するいくつかの方法は、関連する一連の読み取りモデルごとに異なるスキーマを使用するか、命名基準 (ORDER_xxx など) を使用することです。これはよりクリーンであるため、前者を好みます(少なくとも私の観点からは)。

ドメイン モデルを変更しないモデルとコマンドを読み取ります

コマンドは常に読み取りモデルを更新するとは限りません。ドメイン内のビジネス ルールによって、処理および永続化される適切なイベントが発生した場合は、読み取りモデルを更新できます。コマンドが発行されたからといって、読み取りモデルが更新されるわけではありません。

CQS (および CQRS) に従う場合、コマンドは結果を返さないはずです。コマンドは void を返します。コマンドとは、システムに何かをするように指示することです。あなたが説明しているのは、コマンドを発行してから読み取り要求を発行するという 2 段階のプロセスです。読み取り要求が「古い」データ (つまり、コマンドが読み取りモデルを更新する前) を生成する可能性は非常に高くなります。これを処理するにはいくつかの方法があります。あなたは投票することができます - 非常にエレガントな方法ではありませんが、うまくいきます。コマンドが発行された後、ユーザーを中間ページに移動させ (「ご注文ありがとうございます。何か他のものを注文しますか?」)、ユーザーが戻ると、更新されたリストが表示されます (コマンドが現在処理されています)。繰り返しますが、理想的ではありません。しかし、それが結果整合性の性質です。それに対する本当の答えはありません。

状態を更新したり、サード パーティのシステムとやり取りしたりするだけのコマンドの場合、ユーザーが完了するのを待たずにオフラインで実行することはできませんか? これは、ユーザーがシステムをどのように使用するかをシステムに反映させる別のケースだと思います。

読み取りモデル テーブルとインメモリ キャッシュ:

これが良いアイデアかどうか尋ねているなら、私にはよくわかりません. このメモリ内キャッシュの出発点は何ですか? システムを再起動するとどうなりますか? モデルはどうなりますか? 再構築しますか? どこからどのように状態を復元しますか? これにイベント ソーシングを使用しており、最後のスナップショットからすべてのイベントを再生して、ドメイン モデルを適切に取得しますか?

それらの質問に対する答えを知らなければ、答えを出すことはできません。

于 2012-08-30T20:51:21.577 に答える