30

私は最近、CQRS à la Greg Youngの記事を読みましたが、まだ CQRS について理解を深めようとしています。

入力の検証をどこで行うべきか、また、2 つの別々の場所で行わなければならない可能性があるかどうかについてはわかりません (そのため、Don't Repeat Yourself ルールに違反し、懸念の分離にも違反している可能性があります)。

次のアプリケーション アーキテクチャがあるとします。

#      +--------------------+           ||
#      |    event store     |           ||
#      +--------------------+           ||
#           ^          |                ||
#           |  events  |                ||
#           |          v                  
#      +--------------------+         events         +--------------------+
#      |      domain/       | ---------------------> |   (denormalized)   |
#      |  business objects  |                        |  query repository  |
#      +--------------------+           ||           +--------------------+
#         ^   ^   ^   ^   ^             ||                      |
#         |   |   |   |   |             ||                      |
#      +--------------------+           ||                      |
#      |    command bus     |           ||                      |
#      +--------------------+           ||                      |
#                ^                                              |
#                |             +------------------+             |
#                +------------ |  user interface  | <-----------+
#                  commands    +------------------+        UI form data  
  • ドメインは、コマンド バスの背後にある UI から隠されています。つまり、UI はコマンドをドメインに送信できるだけで、ドメイン オブジェクトに直接到達することはありません。

  • 集約ルートがイベントに反応しているときに検証を行うのではなく、それ以前に検証を行う必要があります。

  • コマンドはドメイン内で (集約ルートによって) イベントに変換されます。これは、検証が行われる可能性のある場所の 1 つです。コマンドを実行できない場合、コマンドは対応するイベントに変換されません。代わりに、(たとえば) 例外がスローされ、コマンド バスを経由して UI に戻り、キャッチされます。

問題:

コマンドを実行できない場合は、UI で対応するボタンまたはメニュー項目を無効にしたいと考えています。しかし、途中でコマンドを送信する前に、コマンドが実行できるかどうかをどのように知ることができますか? クエリ側にはビジネス ロジックがまったく含まれていないため、ここでは役に立ちません。コマンド側でできることは、コマンドを送信することだけです。

可能な解決策:

  • 任意のコマンドDoXに対して、対応するダミー コマンドCanDoXを導入します。これは実際には何も実行しませんが、コマンドXがエラーなしで実行できるかどうかをドメインにフィードバックさせます。

  • UI で (実際にはドメインに属している) いくつかの検証ロジックを複製します。

明らかに、2 番目の解決策は好ましくありません (関心の分離が不足しているため)。しかし、最初のものは本当に良いですか?

4

2 に答える 2

9

私の質問は、Udi Dahanによる別の記事Clarified CQRSによって解決されたと思います。「コマンドと検証」セクションは次のように始まります。

コマンドと検証

コマンドが失敗する原因を考えてみると、1 つのトピックとして検証が考えられます。検証は、コマンドに関するコンテキストに依存しない事実を示すという点で、ビジネス ルールとは異なります。コマンドが有効か無効かのどちらかです。一方、ビジネス ルールはコンテキストに依存します。

[…] コマンドが有効であっても、それを拒否する理由が存在する場合があります。

そのため、クライアントで検証を実行して、そのコマンドに必要なすべてのフィールドがそこにあること、数値と日付の範囲に問題がないことなどを確認できます。サーバーは、クライアントが検証を行うことを信頼せずに、到着するすべてのコマンドを検証します。

これは、CQRS が適切に機能するためによく提案される (ドメイン動詞としてのコマンド) ように、私がタスクベースの UI を持っていることを考えると、コマンドが機能しない場合にのみ、ボタンまたはメニュー項目をグレーアウト (無効化) することを意味すると私は考えています。コマンドに必要な一部のデータがまだ欠落しているか無効であるため、送信されません。すなわち。UI は、ドメイン オブジェクトに対するコマンドの将来の影響ではなく、コマンドの有効性自体に反応します。

したがって、CanDoXコマンドは必要なく、ドメイン検証ロジックを UI に漏らす必要もありません。ただし、UI にはコマンド検証用のロジックが含まれます。

于 2011-03-06T21:04:04.393 に答える
2

クライアント側はサーバー上のデータモデルの状態を知ることができないため、クライアント側の検証は基本的にフォーマットの検証に限定されます。今有効なものは、今から 1/2 秒後には無効になる可能性があります。

したがって、クライアント側は、すべての必須フィールドが入力されているかどうか、およびそれらが正しい形式であるかどうかのみを確認する必要があります (電子メール アドレス フィールドには、(.+)@(.+) などの形式の有効な電子メール アドレスが含まれている必要があります)。 (.+) など)。

これらすべての検証は、ビジネス ルールの検証と共に、コマンド サービスのドメイン モデルで実行されます。したがって、クライアントで検証されたデータが、サーバーでは無効なコマンドになる可能性があります。その場合、何らかのフィードバックをクライアント アプリケーションに戻すことができるはずですが、それはまた別の話です。

于 2011-03-10T12:42:26.750 に答える