CQRSを試しています。CustomerService(ドメインサービス)が顧客が存在するかどうかを知る必要がある検証状況があります。顧客はメールアドレスによって一意です。カスタマーリポジトリ(汎用リポジトリ)には、Get(id)とAdd(customer)のみがあります。CustomerServiceは、顧客が存在するかどうかをどのように確認する必要がありますか?
4 に答える
このブログ投稿を見てください:CQRSアーキテクチャでのセットベースの検証。
それはまさにこの問題に対処します。CQRSで対処するのは複雑な問題です。CustomerEmailAddressIsNotUniqueCompensatingCommand
Bjarteが提案しているのは、既存の顧客の電子メールアドレスについてレポートデータベースにクエリを実行し、電子メールアドレスが見つかった場合は、ドメインモデルに補正コマンド(など)を発行することです。次に、を含む適切なイベントを発生させることができますUndoCustomerCreationEvent
。
別のアイデアについては、上記のブログ投稿のコメントを読んでください。
Adam D.はコメントで、検証はドメインの懸念事項であると示唆しています。その結果、ReservedEmailAddressesを、顧客の作成を容易にし、イベントストア内のイベントによって調整されるサービスに格納できます。
完全にきれいに感じるこの問題の簡単な解決策があるかどうかはわかりません。あなたが思いついたものを教えてください!
幸運を!
この問題はそれほど複雑である必要はありません。
- UpdateCustomerコマンドを送信する前に、レポートストアで顧客の一意性を確認してください。
- 電子メールアドレスの一意性のためにDBに制約を追加します。コマンドを実行するときは、例外を処理し、応答チャネルを使用してユーザーに通知を送信します。(レポートストアに対してCustomerUpdatedイベントを発生させることはありません。
データベースを使用して、ORMの制限にとらわれないようにしてください。
Udi Dahanによるこの投稿http://www.udidahan.com/2009/12/09/clarified-cqrs/には、次の段落が含まれています。
「また、コマンドを処理するためにクエリストアにアクセスする必要はありません。必要な状態は、自律コンポーネントによって管理される必要があります。これは、自律の意味の一部です。」
Udiは、データベースに一意の制約を追加することを提案したと思います。
しかし、それをやりたくない場合は、上記のステートメントに基づいて、「ByEmail」メソッドをリポジトリに追加してそれを実行することをお勧めしますが、それでもUdiの方が良い提案があります。
手遅れではないことを願っています...しかし、プロジェクトで同様の状況に直面しました。実際にコマンドエグゼキュータをインターセプトし、そのコマンド用に作成された一連のルールを添付して、クエリを使用してデータをフェッチします。
したがって、この場合、コマンド「RegisterCustomerCommand」がRegisterCustomerCommandExecutorによって実行されようとしているときに、RuleEngineによってフェッチされるCustomerEmailMustBeUniqueRuleという名前のクラスを持つことができます。このルールクラスは、データベースにクエリを実行して電子メールIDが存在するかどうかを確認し、無効なフラグを立てて実行を停止する責任があります。