2

もちろんクラスを表す巨大な入力フォームがあると仮定します。この入力をクラスのインスタンスにロードする必要があります。この入力には明らかに(いくつかの非常に複雑な検証)チェックが含まれており、明らかにロジックレイヤーにはすでにそれらの入力検証が含まれています。問題は、私がGUIで何をしているのかということです。

非常に醜い方法で、GUIでこれらすべての検証を書き直す必要がありますか?

または、ロジックレイヤーでいくつかの静的メソッドを記述し、GUIとロジックレイヤーでそれらのメソッドを使用する必要がありますが、それでも自分自身を検証する複製を作成します(最初にGUIがそれ自体を検証し、次にロジックが送信されたものを検証します)。

または、GUIが正常であると想定し、ロジックレイヤーを使用する関連コードをtryブロックで囲み、例外がスローされた場合は、何かが正しくないことをユーザーに通知します(ユーザーに何を知る機会を与えずに)それは)

または、例外を公開する必要があります。その方法で、パラメータ、クラス、名前空間の名前を公開しますが、おそらく彼は理解できません。

または、すべてのエラーに対して特別な例外クラスを作成する必要があります。この方法で、問題が何であるかをユーザーに正確に通知しますが、おそらく数百の可能な例外を作成します。

または、一般的な例外に分離する必要があります。列挙型にはエラーの正確な内容が記述されており、それらの例外をキャッチします。列挙型をチェックすることで、問題の正確な内容をユーザーに通知しますが、不必要な例外をすべてキャッチすることでアプリを重くします。時間。

または、ロジックレイヤーの入力を検証し、GUIでのみチェックする(誰かが私にこれを提供した、これは私の考えではない、私に叫ばないでください:D)必要があります(私は絶対に恐ろしいようです)解決策:D)

そしてもっと重要な質問-私はそのようなことをどこで学ぶべきですか?通常、私の本能はかなり良いですが、私は不必要に車輪を発明したくありません..(あなたが毎日爆撃したそのような基本的なもののための慣習がすでにあると確信しています)。

どうもありがとうございます!

4

3 に答える 3

3

確かに、ユーザー入力を検証する必要があります。入力と検証ロジックがあなたが言うほど複雑である場合、期待値が何であるか、そしてエラーがあるかどうかをユーザーに明らかにする方法で、GUIで入力を検証することがさらに重要です、 彼らが何でありますか。それらのエラーを修正する方法を提案できる場合はボーナスポイント!

ユーザーが例外や例外の詳細を表示するのに実際には役立ちません。したがって、それを避けるようにしてください。

また、GUIで入力検証を処理しているため、入力の誤りは予期されたものであり、実際には異常ではないため、例外を使用することは必ずしも良い考えではありません。IsValid()何かが有効かどうかを確認する簡単な方法が望ましいです。私は常に「例外は例外的な状況のためのものである」という規則に従います。

したがって、GUIでの検証が良いことであると認めた場合、次の質問は次のとおりです。

すでに多くの検証が行われているとのことですが、検証ロジックが個別に利用できるようには思えません。私が常に役立つと思った方法は、検証コードを他のビジネスロジックから分離しておくことです。これにより、必要に応じて検証ロジックを再利用できます。この場合、ビジネスオブジェクトとGUIの間で同じ検証ロジックを共有できます。明らかに、これを行うための多くの設計アプローチとフレームワークがありますが、基本的な原則は「関心の分離」です。検証ロジックを分離して、使用できるようにします。「ロジックレイヤーでいくつかの静的メソッドを記述し、GUIとロジックレイヤーでそれらのメソッドを使用する」と言うとき、あなたは同じ方針に沿って考えているようです。

わかりやすくするために、GUI自体に検証ロジックを配置することはお勧めしません。むしろ、GUIで使用できるように検証ロジックを使用可能にします。GUIに含める必要がある検証の唯一の部分は、ユーザーからの入力を受け取る部分(検証に送信するため)と、検証の結果を表示する部分(ユーザーに)です。

編集:

私は特定の設計哲学のサクラのように聞こえたくありませんが、最近、ドメイン駆動設計の原則を使用してより多くの作業を行っています。私はそれが非常にうまく機能することを発見しました、そしてそれはあなたが尋ねている多くの質問に対処します。SOには、それが何であるか、およびいくつかのリソースがどこにあるかについての詳細を提供するいくつかの質問があります。

https://stackoverflow.com/questions/1353742/domain-driven-design-ddd-readings
ドメイン駆動設計とは何ですか?

また、ここを読んでください: http ://www.lostechies.com/blogs/jimmy_bogard/archive/2009/02/15/validation-in-a-ddd-world.aspx

編集2:

また、有用な(および関連する)読み物:Business Objects、Validation and Exceptions

于 2009-10-17T05:35:03.853 に答える
1

仕事中のプロジェクトで非常によく似た作業を終えたところです。3つのかなり大きなフォームと、必要なデータを表すクラスがたくさんありました。各クラスにはboolIsValid()メソッドがありました。

ユーザーが保存ボタンをクリックすると、フォームの入力項目からすべてのクラスを構築するメソッドが呼び出されます。各プロパティには非常に単純な検証があります(タイプ、設定されていない場合のデフォルト値など)。すべてのクラスが構築されると(ツリーのような構造体-他の多くのクラスを含む1つのトップレベルクラス)、IsValidメソッドが親で呼び出され、次にそのすべての子でIsValidが呼び出されます。

IsValidがFalseを返す場合、親のErrorsプロパティは、IsValid呼び出しに失敗したすべての子のErrorsプロパティで設定されます。次に、エラーをユーザーフレンドリーなビューで表示します。

ただし、保存ボタンをクリックする前に特定の基準を検証する必要がある場合がいくつかありました。これは、関連するクラスのメソッドを提供しました。

GUIクラスに検証を入れるべきではないと思います。各クラスは、独自の検証要件を担当する必要があります。ただし、GUIを使用して、フォームのどの領域が必要かについてユーザーに「ヒント」を提供することは問題ないと思います。たとえば、変更イベントを使用してフォームの一部を有効または無効にします。

一般的に、GUIを必要としないような方法ですべてのロジックとクラスを作成することをお勧めします。Windowsフォームの代わりにコンソールフロントエンドを作成したい場合はどうなりますか?すでに持っているビジネスクラスを変更せずに、一方を他方に交換できるはずです。

于 2009-10-17T05:32:38.640 に答える
0

これは素晴らしい質問です。バリデーションをデータ レイヤーに配置するというアイデアは、古典的な OO の概念ですが、ゴムが道に出くわすと、厄介な場合があります。エンティティの検証ルールを独自のクラスに入れ、再利用できるようにするというアイデアが気に入っています。ただし、考慮すべき点は他にもあります。

私は一般的に、最も洗練された有用なコードを含む最上層 (プレゼンテーション層) を使用して、データの検証に階層化されたアプローチを使用します。中間層とデータ層では、検証はアサーションの検証と、無効なデータが検出された場合の例外のスローに重点を置いています。プレゼンテーション層がデータを完全に検証することを期待しているが、無効なデータが通過した場合は、ビジネス ロジックを保護し、適切な診断を提供する必要があるという考えです。生の例外をユーザーに表示したくないことは間違いありませんが、取得できるように例外情報を保持することをお勧めします。たとえば、例外トレースをログ ファイルに書き込んだり、電子メール メッセージで自分自身に送信したり、ユーザーが処理できると思われる場合は適切なコンテキストでユーザーに表示したりできます。

データ検証の詳細を考えると、それ自体を検証する方法を「知っている」オブジェクトを作成するという古典的な考え方は、最初に思われるほど役に立たなくなります。検証の各レイヤーは、多少異なる懸念事項に対処します。基礎となるビジネス ルールによってすべての層で検証が行われる場合でも、無効なデータへの対応はコードのコンテキストによって異なります。主な違いは、プレゼンテーション層では、ユーザーとの明確なコミュニケーションと、無効なデータに直面した場合の優れたユーザー エクスペリエンスの作成に本当に集中したいということです。このコードを個々の画面とコントロールに組み込む必要があることは理にかなっています。

シンプルでアトミックなビジネス ルールを、検証専用のクラス内のシンプルな関数または定数に抽出することをお勧めします。あなたが提案するように、これらのルールをデータ層クラスの静的関数に入れることもできます。主なことは、検証ルールを一度だけ定義することです。たとえば、アプリケーションが 10 ~ 100 の値を制限している場合、定数 10 と 100 はコード内で 1 回だけ使用する必要があります。ただし、これらの定数、または範囲検証を実行する単純な関数は、さまざまな層の複数の検証関数から使用されます。

関連トピックとして、検証定数と単純な検証関数のみを使用して、クラスでいっぱいの検証アセンブリを定義することもできます。その後、これらの検証アセンブリを SQLCLR に読み込み、データベース レイヤーの検証に使用できます。このようにして、同じ検証定義をシステム全体からデータベース層まで広げることができます。

于 2009-10-17T07:15:40.747 に答える