2016-05-20 11 views
0

ユーザーが2つのaspxページでフォームを使用して顧客オブジェクトの値を入力する例を考えてみましょう。最初のアプローチでは、両方のaspxページは、IDが0より大きく、FirstNameがコンストラクタを呼び出す前に空でないことを検証する必要があります。 2番目のオプションでは、両方のページが検証機能を呼び出し、エラーメッセージをユーザーに表示できます。例外をスローするのは良い方法ですか?

上記の例に基づいて、私は第2の選択肢を好む。しかし、私がWeb上で研究しているときには、例外をすぐにスローし、オブジェクトに無効なデータを受けさせないようにすることが、よりオブジェクト指向であることが分かり続けます。以前の例外と同様に、このコンストラクタを呼び出すすべてのページは、入力が有効であることを検証する必要があります。私は論理を繰り返すのが好きではないので、私は第二の選択肢を好む。

ドメインドリブンデザインではどのような選択肢がありますか? 1

public class Customer{ 

    public int ID { get; set; } 
    public string FirstName { get; set; } 

    public Customer(int ID, string FirstName){ 
     if (ID < 0) 
      throw new Exception("ID cannot be less than 0"); 
     if (string.IsNullOrEmpty(FirstName)) 
      throw new Exception("First Name cannot be empty"); 

     this.ID = ID; 
     this.FirstName = FirstName; 
    } 
} 

オプション2

public class Customer{ 

    public int ID { get; set; } 
    public string FirstName { get; set; } 

    public Customer(int ID, string FirstName){ 

     this.ID = ID; 
     this.FirstName = FirstName; 

    } 

    public List<string> Validate(){ 
     List<string> ErrorMessages = new List<string>(); 

     if (ID < 0) 
      ErrorMessages.Add("ID cannot be less than 0"); 
     if (string.IsNullOrEmpty(FirstName)) 
      ErrorMessages.Add("First Name cannot be empty"); 

     return ErrorMessages; 
    } 

} 
+0

DDDは例外処理とは関係ありません。前者は_言語ニュートラルなデザインに関係していますが、後者は実装上の問題です – MickyD

答えて

2

私はこの質問が他の場所で回答されたと確信しています。しかし、ここで読書のためのいくつかの他のリンクです:書籍「実践的なプログラマー」から

、例外の使用に関する大きな問題は何が例外である」であります? "そのセクションで

、私は引用:

...例外はほとんどのプログラムの通常の流れの一部として使用することはできません。予期しないイベントに対して例外を予約する必要があります。

それはあなたのケースで例外を使用するかどうか議論の余地があるが、私は何を言わないだろう - おそらく一つのリクエストですべての可能な入力エラーをキャプチャし、修正するために、ユーザーのためのフォームに戻って反映させる必要があるため、それらの値。

ここで思い出したように、はいここでは例外を使用する必要があります。これはあなたのコードをで防衛する方法です。すでに有効な引数がCustomerクラスに渡されることを期待している場合、コードはクラスの無効な使用(たとえば、別のプログラマなど)からの保護のために例外をスローする必要があります。その場合、Customerクラスに達する前に、アプリケーションへのユーザーの入力を検証するための別の入力バリデーターを用意する必要があります。

+0

リンクをありがとう。私はあなたの答えに同意しますが、私が見ていたドメイン駆動の設計例のほとんどは例外をスローします。 DDDの一般的なプラクティスですか? – user3587180

+1

実際にあなたがそれを言及したので、あなたはここで例外を保つべきです。リクエストとこのクラスの間に別の入力バリデータが存在するはずです。 - 私の答えを更新しました – mauris

1

オプション短い答えはNOです。

アプリケーションが不良データで実行を続行できない場合は、例外がスローされます。あなたの例では、ロジックはフロントエンドにエラーメッセージを表示し、オプション2はこの要件を達成するためのよりクリーンな方法です。

例外がスローされても(例外がキャッチされたとしても)、コストのかかる操作です。スレッドが続行される前に、例外が呼び出しスタック全体を走査しなければなりません。これにより、規模の問題が発生します。

+0

例外のパフォーマンスコストは無視できるものです。例外的なケースでのみ発生する必要があるためです。必要に応じて例外を使用することを恐れないでください。 – mauris

+0

例外的な場合に使用することに同意します。だからIMHO、オプション2は良い方法です。 –

-1

適切な例外処理がある場合は、例外をスローすることをお勧めします。アプリケーションがクラッシュするまで、盲目的に例外をスローしないでください。

オプション1の例では、ArgumentExceptionがより適切です。

public Customer(int ID, string FirstName){ 
     if (ID < 0) 
      throw new ArgumentException("ID cannot be less than 0"); 
     if (string.IsNullOrEmpty(FirstName)) 
      throw new ArgumentException("First Name cannot be empty"); 

     this.ID = ID; 
     this.FirstName = FirstName; 
    } 

例:

try 
{ 
    Customer cust = new Customer(-1, string.Empty); 
} 
catch(ArgumentException aex) 
{ 
    DoSomething(aex); // Log to database, file, or alike 
    // Maybe display a message on the user 
} 
catch(Exception ex) 
{ 
    DoSomething(ex); // Log to database, file, or alike 
    // Do generic error process here 
} 

あなたのオプション2は、データの検証のためのより適切です。その動作は、DataAnnotationsを適用するときと同様に観察できます。例外はスローされませんが、エラーメッセージが返されます。

+0

私は複数のページにキャッチしようとした場合、それはロジックを複製することはありませんか?さらに、try catchを使用すると、最初のエラーのみがキャッチされます。モデルがエラーメッセージを返すことができ、プレゼンテーションレイヤーがエラーメッセージの表示を処理できるようにすると、例外をスローするのはなぜですか? – user3587180

+0

エラーの処理方法によって異なります。 tryキャッチが第1ページにあり、例外が第2ページで発生した場合、処理は第1ページで行われます。しかし、まだ2ページ目に残しておきたいシナリオがある場合は、それをそのまま使用してください。すべてのビジネスロジックがエラーの文字列コレクションを返したいとは限りません。スタックトレース、例外の詳細などが必要な場合は、オプション1が必要です。 –

+0

スタックトレースの良い点! – user3587180

関連する問題