2

ビジネスコードの検証を行いたいです。これを行うには2つの方法を考えています。

1 つ目は、次の方法でクラス プロパティ セッターの検証を行うことです。

class Student{
    public string Name{
        get { return _name; }
        set {
            if (value.IsNullOrEmpty) throw exception ...
        }
    } 
} 

さて、このアプローチの問題は、名前が割り当てられるたびに検証コードが実行されることです。これは、DB からのデータを入力する場合など、必要ない場合があります。

私が好む2つは、これらのエンティティクラスに静的メソッドを配置します。

class Student {
    public **static** void ValidateName(**string name**) {
        if (string.IsNullorEmpty(name)) 
        {
            throw ...
        }
        ...
    } 

次のように、インスタンス メソッドではなく静的メソッドを使用していることに注意してください。

class Student{
    public void Validate() {
        // validation logic on instance properties
        if (string.IsNullorEmpty(Name)) 
        {
            throw ...
        }

        ...
    } 

常に Student obj が渡されるとは限らないためです。メソッドに渡される文字列名のようなプリミティブ型を取得することがよくあります。

public static FindStudentByName(string name)
{
   // here I want to first do validation
   Student.ValidateName(name);

   // query DB
   ...
}

学生オブジェクトに渡された場合は、もちろんできます

public static AddStudent(Student s)
{
    // call the instance method
    s.Validate();
}

さて、私は物事を非常にシンプルにしたいので、次のアプローチのいずれにも行きたくありません

  1. [StringLength(25)] などのプロパティで属性を使用します。

    1 つ目は、これにはリフレクションが必要であり、パフォーマンスに影響を与えるため、パフォーマンスを低く抑えるためのトリックがありますが、ここでも、よりシンプルに保ちたいと考えています。

    2 つ目は、自分のサイトを Medium Trust で実行できるようにしたいということです。私が理解しているように、完全な信頼が必要です。

  2. MS など、そこにある検証ブロックのいずれかを使用します。CodePlex にある Enterprise Library など。

では、この件についてご意見をお聞きしたいのですが、

私が行っているアプローチの潜在的な問題は何ですか?
このアプローチは、他のアプローチよりも優れたパフォーマンスを発揮し、読みやすく、維持しやすいでしょうか?

中間層での検証はどのように行っていますか?

たくさんありがとう!

レイ。

4

3 に答える 3

4

ここに書かれているものと非常によく似たルール エンジンを使用して、中間層でドメイン検証を実行します。友人のプロジェクトは、後者の例で提案しているものと同様のアプローチを使用しており、最終結果は維持できません (脆弱で、一般的な検証 UI を実装するのが難しい)。ルール エンジンのアプローチは、すべての検証および永続化ルールを 1 つの適切に整理された場所にローカライズし、各ルールを本格的なクラスとして保持するため、保守が容易ですが、提案したものと同様のドメイン クラスで検証を公開します。動的コンパイルを好む人もいます。そのため、高度な展開後の構成のためにデータベースに格納します。私の場合、コンパイル時にチェックされるのが好きなので、静的クラスで公開されたラムダを使用したルール定義があります。

これがあなたのやりたいことと一致していないことはわかっていますが、私ならどうするかを尋ねて、他のアプローチが十分に単純ではないと言うのは、「信頼できるコードをどのように書くことができるか、私はそれを単純に保ちたいので、単体テストは問題外です。」私にとっては、各ルールを独自のクラスとして扱うのは良いことです。なぜなら、実装はより複雑ですが、保守と文書化が容易だからです。

于 2008-10-30T18:33:38.437 に答える
1

オプション 2 は、少なくとも検証を手動で呼び出さない限り、実際には検証を強制しないものです。したがって、オブジェクトの消費者がルールに違反する可能性があります。

すべてのデータが有効であることを保証するため、個人的には最初の例に似たものを使用します。これは DB 側の追加チェックですが、私が気づいたことから、通常は大したことではありません。

于 2008-10-30T18:20:18.667 に答える
1

あなたが提案するアプローチは、一連の検証を常に適用すべきではないことを示しているようです。どちらでも構いません。「ほとんどの場合」必要なルールと検証をたくさん見てきましたが、実際には常にではありません。では、質問は「これらの検証をいつ適用するか」になります。

たとえば、常に適用したい検証と、ストレージ (データベース) に保存しようとしているときにのみ検証したい検証があるとします。その場合、常に適用されるチェックはプロパティにある必要があり (詳細は以下を参照)、ストレージに保存しようとしているときにのみ適用されるチェックはメソッドにある必要があります (おそらく ' の行に沿って名前が付けられます)。 VerifyRulesForStorage') は、適切なときに呼び出されます (たとえば、'SaveToStorage' メソッドの途中)。

考慮すべきことの 1 つは、複数のエンティティ間で同じ検証を行った場合に発生するリスクがある重複です。プロパティであろうと、「VerifyRulesForStorage」メソッドであろうと、多くのクラスにわたって多くの場所で同じチェック (例: String.IsNullOrEmpty、または CheckItsANumber、または CheckItsOneOfTheAcceptedValues など) を行う可能性があります。もちろん、これは継承 (たとえば、すべてのエンティティが、各タイプのチェックを実装するメソッドを持つ基本エンティティ クラスから継承する)、または構成 (おそらく、エンティティのクラス ツリーが他のエンティティによって駆動されるようにするためのより良いアプローチ) によって解決できます。より適切な考慮事項、たとえば、すべてのエンティティには、これらすべてのチェックを実装する Validator オブジェクトがあります)。いずれにせよ、静的メソッドから離れたいと思うかもしれません。

私たちのシステムには、実際に検証ルールを説明するメタデータがあります。クラスのプロパティ名を使用して適切なメタデータを取得し、適用するルールをシステムに伝えます。次に、ファクトリを介して実際に検証を実行するために適切なタイプのオブジェクトをインスタンス化するバリデーター オブジェクトがあります (たとえば、IsRequiredString ルールを実装する 1 つのクラス、IsNumber ルールを実装するクラスなどがあります)。非常に複雑に思えますが、私たちのような大規模システムでは、それだけの価値がありました。

最後に、既製のライブラリが良い代替手段になる可能性があります。私たちの場合、それらは私たちが持っていた特定の要件によるものではありませんでしたが、一般的には.. 他の誰かが開発した (そしてサポートする) ホイールを使用することには、独自のものを構築するよりも利点があります (信じてください。できます..それぞれのアプローチが他のアプローチよりも優れている場合があると言っているだけです)。

于 2008-10-30T18:37:54.827 に答える