2015年10月25日

エラー処理

趣味であれ仕事であれ、プログラム作成で一番頭を悩ませるのはエラー処理だと思っています。

何か新しいアルゴリズムを考案したり理解したりしてプログラムを作成するというのは、少なくとも日曜プログラミングなんかをやっている方なら非常に楽しい作業なのではないかと思います。しかし、不測の事態が起きた場合や、意図しない入力があった場合に備えてきちんとしたエラー処理を組み込もうとした途端に楽しかったはずの作業が苦痛に変わります。個人的には、デバッグ同様できるだけ避けたい作業の一つで、退屈なだけにエラー処理を考える方が苦痛に感じます。
エラー処理は、プログラムも冗長にしがちです。それを避けるために「例外処理」という機構が C++ や Java、C# などでは用意されています。例外を上手に使えば、プログラムを非常にシンプルにすることができます。しかし、C 言語などで組んでいるために既存のプログラムが例外を全く使っていない場合、そのプログラムは全て見直しが必要になるので、google のスタイルガイドでは「C++ で例外は使ってはいけない」としています。

例外処理を利用しない場合、外部から利用するための関数を作成した時に外部にエラーを通知するためには

1) エラーコードを戻り値として渡す
2) エラーメッセージを画面に出力する
3) 何もせずに戻る

くらいの方法が考えられます。
戻り値にエラーコードを返す場合、戻り値は通常、他の用途に使えなくなるので、何らかの値を得たい場合は引数を通して得る必要があります。また、エラーコード自体もきちんと管理しなければなりません。それから、エラーメッセージを出力しても、それがプログラム側に伝わるわけではなく、これだけで充分ということはまずないでしょう。何もしないというのは、外部にエラーが発生したことが検知できないことを意味しますが、結果からそれを知ることができれば充分ということも場合によってはあります。たいていは、エラーコードとエラーメッセージの組み合わせを利用しますが、それを呼び出し元がきちんと見てくれるかという問題もあり、関数が出力するエラー全てに対して一つ一つきちんと対応するコードを書いていたらキリがなく、どこかで妥協することが多くなります。

例外処理を利用すると、例外は呼び出し元に次々と伝播していきます。通常のアプリなら、メイン・ルーチンのところだけで例外を捕捉して、メッセージを出力して終了としておくだけでも十分な場合が多く、それなら途中の関数などで例外の補足時に行わなければならないことを必要最低限な部分だけ書いておけば、エラー処理部分はかなり簡潔にまとめることができます。

ということで、特に Java や C# であれば、エラー処理は基本的に例外を使うことになるし、C++ だけでコーディングするのなら迷わず例外を使うべきでしょうね。