著作一覧 |
int fooBar(...) { try { ... ...(なんかたくさん) } catch (SQLException e) { log("クラスFooのFooBarでSQLExceptionになったよ。" + e.getMessage()); log("パラメータは" + param1 + "," + param2 ... + "だった"); ... return DEFINED_COMMON_DB_EXCEPTION; } catch (Exception e) { log("クラスFooのfooBarでExceptionになったよ。" + e.getMessage()); ... return FAILED; } return SUCCESS; }
戻り値でエラーかどうかを判別させるのは設計の問題だからどうでも良い。問題は、ログがまったく役に立たないことだ。
なぜ役に立たないかと言えば、このプログラムを書いた人はきっとSQLに自信がないか、またはSQLのために与えられた引数に問題があってSQLで失敗すると予期していることにある。
予期するのであれば、あらかじめ引数をチェックすれば良い。
SQLに自信がないのであれば、まさにテストをちゃんとしておけば良い。
そして、実際、そのようにコードされていたりする。
かくして、fooBarが山ほどログを吐くのだが、すべて"クラスFooのfooBarでExceptionになったよ。null"だったりする。
何が起きているかさっぱりわからねぇ。(DBが落ちているときだけは最初のcathcのログからわかるけど)
よほどへまな奴でなければ、予期しているようなエラーは運用時には起きない(ネットワークとかIOがらみのものは除く)。起きるのは、考えてもいなかったことだ。だから例外なのだ。
したがってどこで例外になるのか、それがどんな例外なのかだってわかるはずがない。何よりも重要なのは例外の種類(Java SEの典型的な例外はgetMessage()にnullを返すことすらある)と、スタックトレース、つまりWhatとWhere(When)だ。
catch (Exception e) { StringWriter sw = new StringWriter(); e.printStackTrace(new PrintWriter(sw, true)); // autoflushって使えるのかな?(普段はPrintWriterのインスタンスを変数に入れてcloseを呼ぶようにしているのでわからない) log("例外になった。" + e.toString() + "\r\n" + sw.toString()); ... }
ちゃんちゃん。
ジェズイットを見習え |