0

例外を定義し、スローし、キャッチする場所についてどう思いますか。また、考慮事項についてコンセンサスがあるかどうかを確認したいと思います。

基礎となる例を述べさせてください。私には解決策があり、その解決策には2つのプロジェクトがあるとしましょう:DomainProjectControllerProject

  1. DomainProjectには、クエリを実行するためのリポジトリがあります。たとえば、RepositoryClass次のメソッドがあります。

    GetObjectById(int id) { ... }
    

    そして、私はこのプロジェクトでのようないくつかの例外を定義していますObjectNotFoundException

  2. リポジトリにクエリを実行しControllerProjectたいので、次のようになります。

    MyObject obj = repo.GetObjectById(11);
    

ここで問題となるのは、IDが実際に存在するかどうかを誰がチェックする必要があるかです。ControllerProjectがIDの存在をチェックすることを選択した場合、次のようなコードになってしまう可能性があります。

MyObject obj = repo.GetObjectById(11);
if (obj == null) {throw new ObjectNotFoundException();}

しかし、その欠点は、使用される場所全体で重複する傾向があることGetObjectByIdです。もちろん、null値を取得してもかまわない状況もあるため、DomainProjectで例外を直接スローしないのはどういうわけか正当なことです。しかし、最初にifテストを複製するのは好きではありません。次に、私の質問に関連して、現在のプロジェクトの外部で例外定義を使用するのは好きではありません。

例外は、それが定義されているプロジェクトでのみスローされるべきであり、他のプロジェクトはそれらをキャッチするだけである必要があると私は感じています。

さて、私の例に戻ると、この状況をどのように解決すればよいでしょうか。簡単なアイデアは、私のドメインプロジェクトで2つのメソッドを定義することです。例外をスローするものとスローしないもの。私が確信していない唯一のことは、私が使用しなければならない命名規則です:GetObjectByIdThrowsIfNotFound()GetObjectById()。または、オプションのパラメータを追加することもできますGetObjectById(int id, bool isExceptionThrow = true)

例外についてどう思いますか?

ありがとう

4

3 に答える 3

2

デザインの意図がきちんと伝わるように配慮されているのは素晴らしいことだと思います。私はあなたの懸念に同意します。例外をスローする唯一のレイヤーは、例外を定義したレイヤーでなければなりません。

つまり、null の戻り値があいまいな場合、キーをnull. そうでない場合 (これは XML コメントに記載する必要があります!)、null 戻り値は常に同じことを意味し (値が見つからない)、ドメイン層でコードと例外処理のオーバーヘッドを節約できます。「値が見つかりません」がコントローラー層で本当に例外的なイベントである場合は、そこで例外を定義してスローします。

「格納されたnull有効な場合、IDictionary<T>:によって確立されたセマンティック パターンを使用し、キーが見つからないことが本当に例外的である場合bool TryGetObjectById(int id, out object value)にのみ例外をスローするバリアントを含め、バリアントGetObjectById(int key)の呼び出しに関連するキーストロークを節約したいTry...道路。

于 2012-04-19T15:21:34.243 に答える
0

よく見かけるパターンは以下の2つです。

1) リポジトリ自体が例外をスローする必要があり、アイテムの取得の失敗を処理する場合は、呼び出し元のメソッドを try / catch ブロックでラップする必要があります。例外を処理するのは呼び出し元の責任であるため、このパターンがアプリケーションの最有力候補になると思います。あなたのリポジトリがキャッチしSqlExceptionないか、永続化レイヤーの例外が正しくスローされると思いますか? その場合は、リポジトリに例外をスローさせ、スタックをバブルアップさせる必要があります。

そうでなければ....

2) コンテナーにラップされたオブジェクトを公開して、失敗または成功を通知します。

public class RepositoryItemContainer<DataType>
{
    public DataType Object { get; set; }
    public bool WasFound { get; set; }
}

次に、値を返すだけでなく、このラッパーを返すと、コードは何をしたいのかを決定できます。

var repoItem = _repo.GetObjectById(11);

if(repoItem.WasFound)
   var item = repoItem.Object;

else
   throw new ApplicationSpecificException("Wasnt found yo!")
于 2012-04-19T15:02:20.573 に答える
0

以下にいくつかの考慮事項を示します。

  1. 例外的 な状況Exceptions用です。したがって、DB にオブジェクトが存在しないことが例外的な状況であると思われる場合は、現在の方法で実装してください。

  2. 例外的なケースでない場合は、メソッドを実装して and を発生させず、当然、クエリが見逃された場合にをException返します。自然に見え、実装したリポジトリ クラスを使用する開発者にとって期待される動作を維持します。nullid

  3. DBContainsId(long id)で必要なの存在を最初にチェックする種類のメソッドを追加できます。idこれも良い選択かもしれませんが、私は個人的には 2 番目の点を好みます。

お役に立てれば。

于 2012-04-19T15:03:13.297 に答える