3

現在作業中のコードベースである例外の混乱をクリーンアップしようとしています。

基本的な設定はこちらです。

私は次のような多くのクラスによって実装されるインターフェースを持っています:

public interface TerminalMessage<E> {

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

これらのクラスは、IOException、InterruptedExceptionなどの多くの異なる例外をスローします。

今のところ、キャッチされた例外に対してgetMessage()を呼び出し、このメッセージをuiコードに中継するだけです。

ユーザーに偽のメッセージが表示されたり、不要な例外が発生したりすることがあるため、これはあまり便利ではありません。

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

ただし、ラッピングを実行する場所がわかりません。例外が最初にスローされる場所(たとえば、出力ストリーム)またはすべてのsend()メソッドでラッピングを実行する必要があります。前者には多くのコードを追加しないという利点がありますが、ストリームがTerminalExceptionではなくIOExceptionをスローする方が理にかなっています。

上記の設計では、ユーザーに表示されることがある悪いメッセージも実際には解決されないため、スローされた例外をユーザーにとって有用なものに変換する方法に関するヒントがあれば便利です。

ありがとう!

4

3 に答える 3

2

エラーコードのような有用な情報が含まれている場合、カスタム例外は非常に良い考えです。

すべてを TerminalException でラップするだけですが、原因を忘れないでください

また

最初にスローされた TerminalException を使用します。

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); 
     } 
 ´               

   }

} 
于 2012-04-24T07:48:15.120 に答える
1

もう 1 つのオプションは、次のようにテンプレート メソッド デザイン パターンを使用し、その中の例外を「制御」することです。

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) {
        }
    }
}

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

于 2012-04-24T07:57:10.993 に答える
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つは、その場所で例外を処理する方法がわからない場合、上の例外レイヤーを処理する方法を知っている可能性が低いことです。その後、2 つのケースだけが発生する可能性があります。何らかの形式で例外をユーザーに表示するか、システムを適切な方法でクラッシュさせる必要があります。属性 isManagable はまさにこれについてです。例外が管理できない場合は、システムを停止する必要があります。したがって、例外は、一般的なエラー ハンドラーのアプリケーションのトップ レベルでのみ処理されます。このようにして、例外の爆発を防ぐことができます。

于 2012-04-27T17:35:15.243 に答える