2012-04-24 21 views
2

私は現在取り組んでいるコードベースである例外混乱を解決しようとしています。例外処理をどのようにクリーンアップできますか?

基本設定はこれです。そのまま

public interface TerminalMessage<E> { 

    // Override for specific return data type. 
    public E send(TerminalStream stream) throws Exception; 
} 

これらのクラスは、などのIOException、InterruptedExceptionある

ようなさまざまな例外の多くがスロー:

私はこのようになりますクラスの多くで実装されたインタフェースを持っています現在、キャッチされた例外に対してgetMessage()を呼び出し、このメッセージをui-codeに中継します。

私はときどきユーザーに偽のメッセージを表示し、私は望ましくない例外を捕まえるので、これはあまりいいことではありません。

私はこれらすべての種類の例外をラップするカスタム例外クラス(TerminalException)を作成しようと考えています。

しかし、ラッピングをどこで行うべきかわからないのは、例外が最初に(出力ストリームなどで)スローされる場所や、すべてのsend()メソッドでラップする必要があるということです。前者は多くのコードを追加しないという利点がありますが、ストリームがTerminalExceptionではなくIOExceptionをスローすることは私にとって意味があります。

上記の設計では、ユーザーに表示されるときどき悪いメッセージが実際には解決されないため、スローされた例外をユーザーにとって有用なものに変換する方法のヒントも素晴らしいでしょう。

ありがとうございます!

+2

この記事を読むことを強くお勧めします。http://onjava.com/pub/a/onjava/2003/11/19/exceptions.html?page=2 – aviad

答えて

2

カスタム例外は、エラーコードのような有用な情報があれば、非常に良いアイデアです。

ちょうど投げ最初TerminalExceptionを使用し、あなたのTerminalExceptionですべてを包むが、原因に

OR

を忘れないでください:

public class MyException extends Exception{ 
    String errorMessage; 

    public MyException(String message, Exception cause){ 
    super(); 

    if(cause instanceof MyException){ 
     // already wrapped 
     errorMessage= cause.getErrorMessage();   
     initCause(cause.getCause()); 
    } 
    else{ 
     // not my Exception 
     errorMessage=message; 
     initCause(cause); 
    } 
´    

    } 

} 
+0

このように、IOExceptionを最下位にラップするTerminalExceptionをスローします。レベル(私のカスタムストリームクラスで)は大丈夫でしょうか? – monoceres

+1

@monoceres私はあなたがいつも「合理的」な例外をキャッチしなければならないと言います。ストリームクラスが、IOExceptionが提供するよりも多くの情報(ファイル名、ファイル内の行番号、または重要な状態など)を追加できる場合は、それをキャッチして、情報とIOExceptionを含む新しい例外を原因としてスローします。新しい情報を追加できない場合は、可能なレイヤーにバブルアップしてください。もちろん、好きなだけ何度もこれを繰り返すことができます。それは意味があります。 – siegi

1

別のオプションは、テンプレートメソッドを使用することができデザインパターンとその内のexeptionsを「制御する」次のように:

public abstract TerminalMessage<E> { 
    public abstract E doSend(TerminalStream stream); 
    public E send(TerminalStream stream) throws Exception { 
     // do common stuff here 
     try { 
      doSend(stream); 
     } 
     // catch more specific exceptions first 
     // handle all the exceptions accordingly here, thus controlling 
     // in one central location what will be thrown externally 
     catch(Exception) { 
     } 
    } 
} 

このようにして、すべての派生クラスの例外処理は同じでローカライズされ、派生クラスは特別な処理を行う必要はありません。

0

私が試した多くのデザインから、これは私が喜んでいくつかのプロジェクトで使用する最後のものです。

public enum ExceptionCodes { 
     IOException("ioexception", false), 
     UserNotFound("usernotfond", true); 

     private static final String BUNDLE_NAME = "SOME_bundle_name"; 

     private final String bundleCode; 
     private final String isManagable; 

     ExceptionCodes(String bundleCode, String isManagable) { 
      this. ... 
      ... 
     } 

     public String message() { 
      // eventually get locale from somewhere, for example some threadLocal 
      return SomeBundleResolver.resolve(BUMDLE_NAME, bundleCode); 
     } 

     public Boolean isManagable() { 
      return isManagable; 
     } 
    } 

    public class MyGenericException extends RuntimeException { 
     private final ExceptionCodes exceptionCode; 
     private final Throwable throwable; 

     public MyException(ExceptionCodes exceptionCode) { 
      this.... 
      ... 
     } 

     public MyException(ExceptionCodes exceptionCode, Throwable throwable) { 
      this. ... 
      .... 
     } 

     public Boolean isManagable() { 
      return exceptionCode.isManagable(); 
     } 

     public String getMessage() { 
      return (throwable == null) ? super.getMessage() : throwable.getMessage(); 
     } 

     ... 
    } 

ポイントは例外コードが1か所で管理されている点です。あなたはエラーコードのような列挙型にカスタム属性を追加することができます。例外に関する多くの問題の1つは、例外を処理する方法がわからない場合、上記の例外レイヤーを処理する方法を理解できないということです。その後、2つのケースが発生する可能性があります。いずれの例外もユーザーに何らかの形式で表示することも、システムをクラッシュさせることもできます。属性isManagableはこれに関するものです。例外がなければ、管理可能なシステムはダウンする必要があります。したがって、例外は一般的なエラーハンドラのアプリケーションのトップレベルで処理されます。この方法で、例外の爆発を防ぐことができます。

関連する問題