4

これまでの検証への取り組みについて、ご意見をお聞かせください。私たちはまだ開発プロセスの初期段階にあるので、まだ変更できます。検証は、このアプリケーションとクライアントにとって非常に重要であるため、最適な方法を見つける必要があります。これまでに行ったことを説明しましょう...

さまざまなクライアントによって消費されるこのアプリケーションを構築しています。すべてのクライアントを管理しているわけではないため、すべてのレイヤーで検証するための厳格な要件があります。一部のクライアント アプリケーションは管理していますが、そのうちの 1 つは最大 100 人のユーザーが使用する WPF アプリケーションです。このアプリケーションから、ワークフローは次のようになります。

|                     Client                   |                                 Backend Service                             |
ViewModel -> ClientRepository -> ServiceClient -> Service (WCF) -> ApplicationService -> DomainModel -> Repository -> Database

検証を実行するための候補として、以下を参照してください。

  • クライアント: 必須フィールド、長さなどで UI をサポートするための ViewModel 検証。
  • バックエンド: クライアントが常に 100% 有効な値を提供することに依存できないため、サービス リクエストの DTO 検証。
  • バックエンド: ドメイン モデル エンティティの検証。エンティティが無効な状態になることは望ましくないため、各エンティティには、操作が実行されるときに異なるチェックが含まれます。
  • バックエンド: 制約の失敗などのデータベース検証 (FK、一意性、長さなど)

クライアントの ViewModel 検証は非常に明白であり、私たち自身のクライアントにとっては、サービスに到達する前にできるだけ多くのエラーを修正する必要があります。ただし、私たちのサービスを消費する他のアプリケーションについて話すことはできません。最悪の場合を想定する必要があります。

サービス リクエストの DTO は、主にサード パーティのアプリケーションの場合と、弊社のクライアントでのミスについて検証する必要があります。リクエストが正しいことを確認することで、後でリクエストの処理中にエラーが発生するのを防ぐことができ、より効果的なサービスを確保できます。ViewModel の検証と同様に、これはさまざまなプロパティの必須フィールド、長さ、および形式 (電子メールなど) に帰着します。

Customerドメイン モデルのエンティティ自体は、常に完全に有効な属性/プロパティを持つことを保証する必要があります。エンティティを例として、このように実現しています。

public class Customer : Entity
{
    private Customer() : base() { }

    public Customer(Guid id, string givenName, string surname)
        : this(id, givenName, null, surname) { }

    public Customer(Guid id, string givenName, string middleName, string surname)
        : base(id)
    {
        if (string.IsNullOrWhiteSpace(givenName))
            throw new ArgumentException(GenericErrors.StringNullOrEmpty, "givenName");
        if (string.IsNullOrWhiteSpace(surname))
            throw new ArgumentException(GenericErrors.StringNullOrEmpty, "surname");

        GivenName = givenName.Trim();
        Surname = surname.Trim();

        if (!string.IsNullOrWhiteSpace(middleName))
            MiddleName = middleName.Trim();
    }
}

これにより、属性が有効であることが保証されますが、CustomerValidatorクラスは Customer クラス全体を検証し、それが有効な状態にあり、有効な属性を持っているだけではないことを確認します。FluentValidationCustomerValidatorフレームワークを使用して実装されます。これは、顧客オブジェクトをデータベースにコミットする前に、アプリケーション サービスで呼び出されます。

これまでの私たちのアプローチについてどう思いますか?

私が少し心配しているのは、いたるところにスローされる例外の使用です。たとえばArgumentException、上記の例だけInvalidOperationExceptionでなく、オブジェクトの現在の状態では許可されていないメソッドへの呼び出しの場合も同様です。

サービス リクエストの DTO が検証されているため、これらの例外がスローされることはめったにないことを願っています。たとえば、サービス リクエストの DTO が検証される場合、検証のどこかにエラーがない限り、引数の例外が発生することはありません。したがって、ドメイン モデルでのこれらの引数チェックは、追加のセキュリティ レイヤーとして機能すると言えます。InvalidOperationException一方、クライアントが、現在の状態では利用できない Customer オブジェクトのメソッドを呼び出すサービス メソッドを呼び出した場合に発生する可能性があります (したがって、失敗するはずです)。

どう思いますか?すべて問題ないように思える場合、何かが失敗したときに WCF を介してユーザーに適切に通知するにはどうすればよいでしょうか? 、ArgumentExceptionInvalidOperationExceptionまたはエラーのリストを含む例外 (CustomerValidator クラスを使用して顧客オブジェクトを検証した後、ApplicationService によってスローされます)。どうにかしてこれらすべての例外をキャッチし、それらを WCF によってスローされる一般的なエラー例外に変換して、クライアントがそれに反応し、何が起こったかをユーザーに通知できるようにする必要がありますか?

私たちのアプローチについてあなたの考えを聞きたいです。私たちはこのかなり大きなアプリケーションを構築し始めたばかりで、検証を実行する良い方法を見つけたいと思っています。私たちのアプリケーションには、データの正確性が非常に重要な非常に重要な部分がいくつかあるため、検証が重要です!

4

2 に答える 2

2

私自身の意見では、ドメインの一貫性はドメインによって処理されるべきです。したがってCustomerValidator、種類は必要ありません。

例外ArgumentNullExceptionについては、ユビキタス言語の用語であることを考慮する必要があります (詳細な説明については、http://epic.tesio.it/2013/03/04/exceptions-are-terms-ot-theを参照してください)。 -ユビキタス-language.html )。

ところで、すべての DTO が以前に検証されていたとしても、ドメインから適切な検証を決して削除しないでください。ビジネス不変条件はそれ自身の責任です。

パフォーマンスに関しては、例外には計算コストがかかりますが、これまでに見たほとんどの DDD シナリオでは、例外は問題になりません。特に、人間からのコマンドの場合は問題ありません。

編集
の検証は、常にドメインの責任です。ISIN値オブジェクトを取得します。適切な例外をスローすることにより、独自の不変条件を保証するのはコンストラクター次第です適切にコーディングされたドメインでは、無効なオブジェクトのインスタンスを保持できません。したがって、エラーを累積するためのバリデーターは必要ありません。

同様に、ファクトリは、インスタンスを取得する唯一の方法である場合にのみ、ビジネスの不変条件を保証できます。データベース列の長さなどの技術的な不変条件はドメイン外にある必要があるため、工場はそれらにとって適切な場所になる可能性があります。これには、例外の連鎖を有効にするという利点もあります。SqlExceptions は、クライアントにとってあまり表現力がありません。

表現力豊かな例外を使用すると、クライアントは処理できる例外を試行/キャッチするだけで済みます (ユーザーに例外を提示することは、それを処理する方法であることを忘れないでください)。

于 2013-03-23T21:56:17.890 に答える
0

システムにデータが入るポイントがあります。これは、アクション引数 (ビュー モデル) またはサービス レイヤーのパラメーターの形式である場合があります。この時点で常にハイパー検証を行い (すべてを null 可能にしてから null を許可しない、整数の負の数をチェックするなど)、これらのエントリ ポイントですべてが 100% 正しいことを保証する必要があります。そうすれば、検証が特定のエッジ ケースに対するものでない限り、システムの残りの部分はそれについて心配する必要はありません。クライアント検証は便利ですが、完全に信頼してはいけません。検証で切断が発生する場合があります。また、あなたのアクションを呼び出しているクライアントが、あなたが思っているとおりのクライアントであるという保証はありません (たとえば、URL のクエリ パラメータをすべて変更して、何が起こるかを確認しました)。

あなたが投稿したコードに関する私の問題は、その時点で、有効な場合とそうでない場合があるデータがドメインにあるという事実です。常にプロセスの外部境界で検証を実行する場合、心配する必要はありません。また、「その検証をどこに置いたのだろうか?」と疑問に思うこともありません。

于 2013-03-25T13:53:48.193 に答える