私は現在、特定のシステムを構築するときに CQRS を適用できるかどうかを調査しており、簡単に答えを見つけることができないいくつかの質問があります。
コマンドの可用性/検証
ユーザーが特定のエンティティに対して実行できることは、通常、ユーザーの役割だけでなく、この特定のユーザーとこのエンティティ (作成者など) との関係、およびこのエンティティの状態 (公開、アーカイブなど) にも関連付けられます。
私には、CQRS のユーザー アクションは、それらを処理するコマンドにマップされているように見えますが、どのアクションとコマンドが使用可能かを判断する方法が明確ではありません。
すべての読み取りモデルで使用可能なコマンドのリストを返すことは、一貫性が必要なため、ユーザーの役割にのみ関連付けられているコマンド (メニュー項目など) をチェックする必要があるため、不適切に思えます。
もちろん、別のユーザーが状態を変更してコマンドが無効になった場合に備えて、コマンドはトランザクション中に再度検証を行う必要があります)。
要件変更への抵抗
私の経験では、冗長なロジックと特定のビジネス オブジェクトに関連付けられたクラス/テーブルが多すぎるシステムを維持することは悪夢です。
CQRS では、1 つの特定のビジネス エンティティに対して複数の読み取りモデルが存在する場合があります。そのエンティティを変更する必要がある場合は、関連するすべての読み取りモデルも変更する必要があります。
保守性のために、リファクタリング中に簡単に明らかにできる方法でそれらを関連付ける必要があります。
関連する注意点として、過度に具体的なコマンドが多数あると、保守性の問題も発生します-1つのユースケースごとに1つのコマンドが最適に機能するはずであると想定するのは正しいですか?
ドメイン モデルを変更しない読み取りモデルとコマンド
CQRS コマンドでは、読み取りモデルを更新することになっており、ユーザーはその間に古いバージョンにアクセスできます。
私の頭の中で問題を引き起こす2つの特別なケースがあります。
まず、ドメイン モデル自体を変更するのではなく (おそらく状態のみ)、サード パーティのシステム/フレームワーク/電子メールなどを含む何らかの操作を実行するコマンドがあり、場合によっては、これらのコマンドの実行にかなりの時間がかかることがあります。
ここで見たように、ドメイン モデルとコマンド実行状態を組み合わせた読み取りモデルが必要です。この読み取りモデルは、現在処理中のアイテムの履歴またはリストとして使用できます。
次に、いくつかのコマンドが結果を生成します。この結果は、コマンドが正常に完了したときにユーザーに表示する必要があり、場合によっては、しばらくしてから破棄し、ファイルにする必要があります。したがって、これらのコマンドの結果をデータベースに保存し、コマンドの特定のインスタンスに関連付ける方法が必要です。つまり、一時的な読み取りモデルを用意します。
読み取りモデル テーブルとインメモリ キャッシュ
また、第 2 レベルの ORM キャッシュ (クエリ結果用) では、読み取りモデル用のデータベース テーブルを用意する必要はありませんが、ORM はクエリが初めて実行されたときにそれらを生成し、結果をキャッシュして無効にすることができます。モデル エンティティが変更されると、それらは自動的に変更されます。このアプローチは、CQRS インターフェイス/パターンを強制する良い出発点のようですが、変更することができ、おまけとして動的プロジェクションをサポートできます (ユーザーが表示する列などを選択した場合)。