例外処理について個人的に思うことを書いてみる
Javaの検査例外の仕組みは理解はできるけど、結果的にはあまりうまくいかなかったかなというのが個人的な見解です。理由は例外をcatchさせても無視されることが多いから。
下記の本にもそれに近い見解が述べられていた気がするけど忘れた。
- 作者: Jim Waldo,矢野勉,笹井崇司
- 出版社/メーカー: オライリージャパン
- 発売日: 2011/02/24
- メディア: 大型本
- 購入: 3人 クリック: 148回
- この商品を含むブログ (37件) を見る
僕がSIerにいた頃は、開発者に例外をcatchさせてはいけないと言われたものでした。
共通チームが共通部品やフレームワークを整備して、他チームがそれを使って開発することが多いわけですが、その場合に個々の開発者が例外をcatchする必要がないように整備するのが一般的でした。
例えばStruts 1のActionのexecuteを個々の開発者は実装せず、Actionは自動生成してLogicクラスに切り出したものを実装するという感じです。例えが古い。。。
今思い返してもその方針自体は妥当だなと思ってます。
Javaの場合は検査例外をcatchしても実行時例外にラップしてthrowすることが多く、ボイラープレートなコードになりがちだし。
僕は以下のようなコードをよく書いてます。
try { ... } catch (IOException e) { throw new RuntimeException(e); }
例外をcatchしても処理を続行したい場合ってそんなに無いと思うんですよね。たいていはその場でストップして良いのではという。
変にcatchさせると下記のようのあまりよろしくないコードになりがちです。
例えば下記のようなパターンです。
例外を完全に無視しているパターン
try { ... } catch (IOException e) { }
さすがにこういうコードはそんなに見ません。
静的解析にも引っかかるだろうし。
唯一これが許されるのは、大量データを扱う処理で下手にロギングするとディスクを圧迫してしまうケースです。
例外をロギングしているけどstacktraceを捨てているパターン
import org.apache.log4j.Logger; ... private static Logger logger = LoggerFactory.getLogger(Hoge.class); ... try { ... } catch (IOException e) { logger.error(e); ret.put("error", e.getMessage()); }
APIサーバー実装する場合にユーザには例外のメッセージだけJSONで見せて、詳細のstacktraceは別途ロギングするパターンはよくありますよね。一見良さそうに見えて、stacktraceがロギングされてません。
というのに最近Azkabanで遭遇してpull requestしました。
https://github.com/azkaban/azkaban/pull/905
正しくはlogger.error(e.getMessage(), e);を使うこと。というかlog4jだとコンパイルではじけないからslf4j使うほうが良いんだろうな。
検査例外が無いPythonやRubyだったらこういうこと起きないんだろうなと思いきや、例外をexcept, rescueして元のstacktraceが消えているコードを見ることがあるので検査例外の問題ではないのかもと最近は思い始めております。