2016-08-23 6 views
-1

サブメソッドが例外をスローすると、専用の "パッケージ"例外のカプセル化は良いとみなされますか?コンポーネントから例外をスローするのは良い方法ですか?

public String doStuff() throws UtilsException { 
     try { 
      throw new NullPointerException("test"); 
     } catch (NullPointerException e) { 
      throw new UtilsException("something occured", e); 
     } 
    } 

    //use this exception for all classes of this package/component 
    public class UtilsException extends Exception { 
     private static final long serialVersionUID = 1L; 

     public UtilsException() { 
      super(); 
     } 

     public UtilsException(String message, Throwable cause) { 
      super(message, cause); 
     } 

     public UtilsException(String message) { 
      super(message); 
     } 

     public UtilsException(Throwable cause) { 
      super(cause); 
     } 

    } 

Optional.empty()複雑なアプリのキャッチ/投げ回避するための代替だろうか?

public Optional<String> doStuff() throws UtilsException { 
     try { 
      return Optional.of("ok"); 
     } catch (NullPointerException e) { 
      LOG.error("Something append... {}", e.getMessage()); 
      return Optional.empty(); 
     } 
    } 
+1

高レベルの例外に低レベルの例外をラップすることは、いくつかの設定では良い方法かもしれませんが、 'NullPointerException'について話しているのではありません。あなたは 'NullPointerException'をキャッチすべきではありません。それはあなたのアプリケーションのすべてのレベルで同じ意味を持っています。 'Optional'は' NullPointerException'が発生したという報告ではなく、潜在的に不在の値をカプセル化します。最初に 'NullPointerException'を避けてください。あなたは 'Optional'を使ってそれを行うことができます。 – Holger

+0

NullPointerExceptionは私の設定を説明するだけのものでした。ラッピングは、例外の発生源に従うことは興味深いようです。 –

+1

あなたは本当に悪い例を選んだ。 'ClassNotFoundException'は、クラスバイトのロード中に発生した' IOException'をカプセル化します。特殊なケースは、チェック例外を許可しないAPIレイヤです。データベースへの 'Collection'ビューを考えてみましょう。そこには、下位のストレージシステムの障害をラップする必要があります。 'IllegalStateException'や' NoSuchElementException'の中に入れてください。私は、これらがより良い例を作ると思う。 – Holger

答えて

1

まず、あなたがすべき決してキャッチNullPointerExceptionが発生(または一般に実行時例外)あなたがやっているような他のリターンいろいろ書い。 これは、バグのあるサードパーティのAPIのように、実行する必要があるケースはほとんどありません。

あなたのプログラムにバグがあって、 をバブルアップしてプログラムの上位コンポーネントで処理させるときは、それらの例外(NullPointer、ClassCast、IllegalArgumentなど)が発生します。言われていること

、(そして悪名高いフレーズが来る)、それは依存...

例外は、呼び出し側がどのように決定するためにそれらを使用するためにこのように、彼らは有益である必要があり、エラーを通知するための「責任」です行う。次のことを考えてみましょう:

public void readFile(String path) throws IOException { 
    // read file content 
    return content; 
} 


try { 
    return readFile("foo.txt"); 
} catch(FileNotFound e) { 
    // For this specific scenario not finding the file is not a problem  
    return ""; 
} catch(IOException e) { 
    // This we are not expecting to happen, if the file exists we should be 
    // able to read it, otherwise we should inform the user. 
    log.error(e); 
    display("We had a problem reading the file, Check the file permissions and try again"); 
} 

あなたは上記の例でわかるように、あなたがたときに何をすべきかを決定するためのクライアントの機能を削除しますので、あなたがこの場合 で別の例外でのIOExceptionをラップするとは思わないだろうエラーが発生しました。

また、にIOExceptionが例外がオブジェクトであるため、あまりにも、あなたのメソッドがスローするエラーの種類を一般化する継承 を使用することができ、その後、呼び出し側が 何を決めることができるので、より多くの特定のエラーを投げる「ラップ」の形であることに注意してくださいする。

ラッピングする場合。

例外をラッピングするのが良い方法であり、行く方法です。 たとえば、天気情報を取得することを主な機能とするlibを作成する場合。

最初のバージョンでは、それを簡単に保ち、サードパーティのAPIを使用してその日の値を取得しました。 APIの主な方法は次のようになります。

public Weather getWeather(Date day) throws HTTPException { 
    return weather.get(day); 
} 

あなたのAPIはかなりうまくやっているけど、あなたは天気APIにあまりにも多くのリクエストをやっている気づき、 あなたは非常にすぐにそれを払って開始する必要があります。結果をデータベース表 にキャッシュすることにしました。これにより、要求の量を減らすことができます。

public Weather getWeather(Date day) throws HTTPException, SQLException { 
    Weather w = getFromCache(day); 
    if (w != null) { 
     return w; 
    } else { 
     return getAndCache(day); 
    } 
} 

今、あなたが問題を持って、あなたが最も確かに あなたのAPIのユーザーコードが壊れますので、声明をスローに、この新しい例外を追加することはできません。

あなたが考えているのは、あなたのキャッシュからwheter apiまたは のデータを取得する際に問題があった場合、apiのユーザーは興味がありません。エラーを通知するだけです。これらの例外を に包括する場合は、WeatherFetchExceptionのように、これは非常に良いケースです。私に

あなたが見ることができるように、それは本当に依存...

経験則れ、意味のあるあなたの例外を維持し、あなたがそれらをラップしたい場合、それは理にかなっているときにのみ 行いますエラーを処理する呼び出し元の機能が削除されないときに発生します。

ラッピング例外は、そのためには、間違いなく、良い方法ではありません。

関連する問題