The Catcher in the Exception

思った事をつらつら書くよ。あとタイトルに意味はないよ。

例外は何の為に存在するのか?

例外はクラスの操作方法を間違えた事をプログラマにお知らせするものです。コンパイルエラーみたいなもんだと思ってます。



例外の使い方

どのように例外を使用すべきか?
この問いに対して、ぼくは以下のようなコーディングルールを設ける事で例外の使用方法を明示する事にしました。

  1. 非チェック例外を使おう
  2. チェック例外は使用しないようにしよう
  3. チェックメソッドを導入しよう
  4. 出来うる限り例外の発生状況を書き出そう

非チェック例外を使おう

例外はクラスの操作を間違えた時に投げるべきです。


Iteratorを例にします。
Iteratorはnextメソッドで値を取得し、hasNextメソッドで次の値があるかどうかを確認するという使用方法があります。
これ以外の使用方法……例えば、hasNextメソッドで次の値があるかどうかを確認せずにnextメソッドを使う、という方法をとった場合、値が取得できなくなるとnextメソッドはNoSuchElementExceptionをスローします。
nextメソッドがNoSuchElementExceptionをスローするのは、クラスの使用方法を間違ったからです。決して値が取得できなくなった事をお知らせする為にスローされたのではありません。


例外はクラスの使い方を強制するものです。だから基本的に非チェック例外を使用し、クラスの使い方を間違ったら例外によりプログラムが強制的に停止するようにすべきです。



チェック例外は使用しないようにしよう

例外はコンパイルエラーと同等のものであると思っています。
コンパイルエラーを無視するとプログラムが動かないように、例外が発生するとプログラムが動かないような処置をすべきです。
そうなると、チェック例外というのは邪魔な存在です。例外によってプログラムを停止させる事を前提とした場合、try〜catch構文をわざわざ書くのは面倒です。しかも場合によってはプログラムを停止させずに続行するようなコードを書く場合もあるでしょう。
例外が発生するならプログラムを停止させるなら、チェック例外は使用する必要はないと思います。



チェックメソッドを導入しよう

クラスの内部状態をお知らせするチェックメソッドを作りましょう。
IteratorでいうところのhasNextメソッド、コレクションのisEmptyメソッドなどが該当するでしょう。
例外に頼るコードは、チェックメソッドを使って置き換えましょう。
もちろん、クラスの実装がバレるようなチェックメソッドを作れというわけではありません。クラスを外側から見た時に必要となるチェックメソッドを実装すべきです。



出来うる限り例外の発生状況を書き出そう

例外をコンパイルエラーのように扱うのなら、例外が何故発生したのかをなるべく詳しくプログラマに知らせるべきです。
コンパイルエラーの状態が詳しく表示されないコンパイラが嫌がられるように、例外も発生状況が詳しく書かれていないのは不都合です。
具体的には、例外が発生した時のフィールドの値を例外のインスタンスに格納しておくと良いと思います。
もちろん、これも不用意に内部実装をさらけ出す必要はありません。