3

try/catch ブロックをどこにでも置かずに例外を処理するためのベスト プラクティスは何ですか?

例外の受信と処理に専念するクラスを作成するというアイデアがありましたが、それが良い設計アイデアかどうか疑問に思っています。そのようなクラスは例外を受け取り、そのタイプまたはエラー コードに応じてそれをどう処理するかを決定し、特定の情報についてスタック トレースを解析することさえできます。

背後にある基本的な考え方と実装は次のとおりです。

public class ExceptionHandler
{
    public static void Handle(Exception e)
    {
        if (e.GetBaseException().GetType() == typeof(ArgumentException))
        {
            Console.WriteLine("You caught an ArgumentException.");
        }
        else
        {
            Console.WriteLine("You did not catch an exception."); 
            throw e;   // re-throwing is the default behavior
        }
    }
}

public static class ExceptionThrower
{
    public static void TriggerException(bool isTrigger)
    {
        if (isTrigger)
            throw new ArgumentException("You threw an exception.");
        else
            Console.WriteLine("You did not throw an exception."); 
    }
}

class Program
{
    static void Main(string[] args)
    {
        try
        {
            ExceptionThrower.TriggerException(true); 
        }
        catch(Exception e)
        {
            ExceptionHandler.Handle(e);  
        }
        Console.ReadLine(); 
    }
}

これは興味深い試みだと思いました。理論的には、main() メソッド呼び出しの周りに 1 つまたはごく少数の try / catch ブロックしか必要なく、例外クラスが再スロー、処理、ロギングなどすべてを処理できるからです。

考え?

4

4 に答える 4

6

OK、これはおそらくあなたが望む答えではありませんが...

私は一般的に、一般的な例外処理クラスのアイデアに対してアレルギーがあります。それ自体が矛盾していることがほとんど聞こえてきます。例外は例外的なイベントです。例外的なイベントは一般的な方法で処理することはできませんが、発生する可能性がある場合は処理を調整する必要があります。これは基本的に、コードで次の 2 つのことを行う必要があることを意味します。

  1. そもそも例外を回避するために、入力について防御的になる
  2. 例外をキャッチして処理するのに適した場所try..catchにブロックを配置します (これは、すべてのメソッドにブロックを配置する必要がないことを意味することに注意してください)。try..catch

では、例外をキャッチして処理する意味があるのはどこでしょうか? 要するに、コードが例外を処理できるようにする知識を持っている場所です。そうでない場合は、例外を呼び出し元に上向きにバブルさせます。すべての例外をキャッチし、何をすべきかについていくつかの一般的なデフォルトの動作を設定する必要があると私が考える唯一の場所は、アプリの最上位にあります。これは通常、UI です。

于 2011-04-06T22:49:51.497 に答える
5

実際、製品コードで同様の設計が見られないのには十分な理由があります。

まず第一に、そのような設計はコード内のtry/catchペアの数を減らすのに役立ちません (これは明らかなはずです)。特定の のステートメントの数を減らすのに役立つ可能性があります。catchtrySystem.ExceptionExceptionHandler

しかし、次は何ですか?

すべての例外は異なる方法で処理する必要があります。どうすればExceptionHandler正確に何をすべきかを知ることができますか? これを解決するには、さまざまな方法があります。たとえば、次のようになります。

  1. ExceptionHandler仮想メソッドで例外を処理するコードを派生させて配置する
  2. Action<Exception>ハンドラーに多数のインスタンスを渡し、適切なインスタンスを呼び出させる

解決策 (1) は以前よりも悪いものになります:tryブロックごとにまったく新しいクラスを作成し、一連のメソッドをオーバーライドして、以前よりも悪い結果になるようにする必要があります(コードがどのように変更されるかはすぐにはわかりません)。特定のクラスがプログラムの流れに適合します)。また、別の重要な質問に答えられないままになります。例外を適切に処理するには、コンテキスト (現在のスコープ内の変数へのアクセス) が必要になる場合があります。このコンテキストへのアクセスをどのように提供しますか?

catch解決策 (2) は、実際には避けたいと思っていたブロックを書くのと非常によく似た結果になります (それぞれActionが実質的にcatchブロックの内容になります)。より複雑で冗長な方法でのみ、同じことを行うことになります。

他にも次の問題があります。

  • ExceptionHandler例外を処理できない場合はどうすればよいですか? もう一度スローすると、元のスタック トレースが失われ、そこにある適切な情報がすべて破棄されます。
  • にバグがある場合はどうなりExceptionHandlerますか? try/を信頼できますcatch。自分で書いたコードを同じ程度に信頼できますか?

...については、ExceptionThrowerどのような利点がありますthrow new Exception();か?

例外処理はすでに複雑な問題であり、マシンに追加のギアを追加せずに正しく処理することは十分に困難です。特に彼らがあなたに新しいものを買わない場合。やらないでください。

于 2011-04-06T22:48:33.920 に答える
1

私たちのコードベースには、あなたが提案したものと非常によく似たシグネチャを持つクラスがあります。

コードに try-catch ブロックがたくさんあるのはなぜですか? いくつか例を挙げていただけますか?例外はその性質上、「例外的」であり、それほど頻繁ではありません。頻繁に例外をキャッチするべきではないだけでなく、すべての例外は異なり、ある状況で機能する同じボイラープレート コードは、おそらく他の多くの状況では適切ではありません。

例外処理が簡単である (またはコンパクトなコードが生成される) とは誰も言いませんでした。例外をキャッチして適切に処理する必要がある状況について慎重に検討する必要があります。

于 2011-04-06T22:58:34.533 に答える