攻撃的プログラミングには、例外ブレークポイントが便利

柴田 芳樹さん*1のブログを読んでいて、ふと目にとまったコメントがありました。

  • 結果として、APIの実装コードでは不正パラメータの検査されていない。あるいは、検査はしているが例外をスローすることなく、単純にリターンしている。※

(中略)
※ 検査はしているが単純にリターンしていると、その不正と思われる値が本当に不正なのか、正常値の範囲の一つなのかが不明瞭となります。


コメント:
全例外をキャッチして、適当な別の例外にラップしてスローしたり、キャッチはするけど何の処理もしないで戻り値を返す人も時々いますね。FileNotFoundException をキャッチして-1を帰したりとか。

FileNotFoundExceptionをそのままスローしてくれればファイル名やパスが間違っている可能性に即座に思いあたるのに、-1や別の例外を帰されると、そのエラーが何であるかを追跡するだけで丸一日を浪費させられたりします。
しかも、それが当たり前と思い込んでいて、-1を帰すことの何が問題かを全員が分かってなかったりするから達が悪い。
by TM (2010-09-28 05:42)

防御的プログラミング(2):柴田 芳樹 (Yoshiki Shibata)

コメントにあるようなプログラムに、自分も遭遇したことがあります。
防御的プログラミングと真逆の、攻撃的プログラミングというような物です。


そういうのには、例外ブレークポイントが役に立ちました。

例外ブレークポイント

ある例外が発生したら、その発生箇所でブレークしてくれる機能です。
もし、例外を握りつぶすようなコードに遭遇したら、あたりを付けてこれを使うと、手早く問題を解析できます。

eclipseの場合

「実行」から「Java例外ブレークポイントの追加」を開き、発生してそうな例外を選択します。
詳細な設定が必要な場合、デバッグ画面の「ブレークポイント」タブで、該当のブレークポイントのプロパティを開いて設定します。

  • 指定のパッケージ・クラス内で発生した場合だけブレークする、あるいはブレークしない。
  • 指定のスレッド内で発生した場合のみブレークする。
  • キャッチされなかった場合にブレークする、キャッチされた場合にブレークする
Visual Studio.NETの場合

デバッグ」から「例外」を開き、例外の種類とブレークするタイミングを指定します。


ちなみに、これで NullPointerException を常にブレークするように設定しておくと便利です。

そもそも・・・

防御的プログラミングをしていれば、そもそもブレークポイントが必要になることがあまりないような気がします。
どこで間違えたかがすぐにわかるし、どこを直せばいいかもはっきりするからです。


ただ、元記事にあるように、「防御的プログラミング」を知らない人が多い気がします。
自分も、他社の人とお話をしていたときに防御的プログラミングをすることを提案したら、思いっきり「はぁ?」って反応をいただきました。
その人が書いたプログラムは、案の定、不明瞭なプログラムになっていました。
ずっと本人が保守をするならまだしも、チームを抜けて丸投げ*2するので、かなり迷惑でした。
(このプログラムの修正は、以前に書いた爆発物処理班のような心境でやるはめに・・・)


この経験で、防御的プログラミングの大切さを、改めて知ったような気がします。

*1:技術書の翻訳を手がけている方。この方が翻訳した Effective Java (第二版)のおかげで、きちんとした基礎を身につけることができました。直接お礼が言えないのが残念です・・・。

*2:ドキュメントの代わりにJavaDocが書いあったものの、防御的プログラミングを理解していないので、あまり意味をなしていませんでした。