チェック済み例外

C++の例外機構のテストをしている。C++の例外機構には、「例外仕様」と、Javaのようなtry〜catch構文がある。

C++の例外仕様は奇妙だ。単に奇妙なだけならまだ救えるのだが、使える気がしない。C++の例外仕様は「この例外しか出ない」と宣言する。「契約による設計の概念」に近い。しかし、これに違反すると(デフォルトでは)一発でプログラムが落ちる。C++みたいに複雑なプログラムの中で、例外が(宣言したもの以外は)出ないことを保障するなんて、ライブラリをまったく使わないとかじゃない限り不可能ではないだろうか? 実際に、Microsoftの実装系では、例外仕様は無効化されているようだ。

予想外だったのはそれだけではなかった。どうも意図した通りに動作しないので調べていたら、どうやら僕は恐ろしい勘違いをしていたようだ。Javaは、「チェック済み例外」を機構を取り入れている。これが当たり前だと思っていた。しかし、その他の言語(C++だけでなくC#も)では、「チェックなし例外」になっているということだった。

参考 → http://www-6.ibm.com/jp/developerworks/java/040618/j_j-jtp05254.html

これまで、当然のように、チェック済み例外を用いて設計していたのだが、これはJavaの中の世界の設計技法だったのか! 僕はプログラミング、特に、オブジェクト指向は、Javaのみで育ったから気がつかなかった。まったく、SUNに騙されたのはこれで何度目だろう。

SUNという会社はでかいことを言うのが好きだが、それらは、大袈裟で使えないことばかりだ。しかし、たまに奇跡を起こす。僕にとっては、チェック済み例外の機構は奇跡の一つだ。

チェック済み例外がなぜ良いかは、参考のURLの中で言われている通り、例外のドキュメンテーションが完備されることだ。しかしこれでも言い足りない気がするので追加したくなった。

J2EE Design and Development (参考文献)は私が読んだJava開発やJ2EEなどの本の中で最高のものの一つですが、その著者のRod Johnsonはもう少し穏健な立場を取っています。彼は例外をいくつかの範疇に分け、それぞれに対して方策を特定しています。一部の例外は基本的に二次的な戻りコード(通常はビジネスルール違反を知らせます)であり、一部は「何かがえらくおかしくなった」の類(例えばデータベース・コネクションをしようとして失敗、など)です。Johnsonは最初の範疇にはチェック済み例外(代替戻りコード)を、後の範疇にはランタイム例外を使うように主張しています。「何かがえらくおかしくなった」範疇では単純に認識するのみで、どの呼び出し側でもこの例外を効果的に処理することはできない、従って途中にあるコードにはほとんど影響を与えずに(そして例外の飲み込みの可能性もほとんどなく)伝達されてスタックを一番上まで上がって行くかもしれない、と認識するのです。

安定的な層と不安定な層があるとする。設計の段階で、不安定な層が安定的な層に、どのような例外を上げるかが定義される。不安定層のコードの実行の中で「何かがえらくおかしくなった」の場合でも、安定的な層にどの例外をあげるべきかは決まるはず。単純にそれを上げたら良いのではないだろうか。ちなみに、これがIOExceptionという例外であっても、僕は、実装の詳細をさらけ出しているとは思わない。設計のときに、「何かがえらくおかしくなった」ということを表すものとして、その名前を選んだにすぎない。

このところ、僕は、何とかC++にチェック済み例外と同等の仕組みを入れることができないか考えている。Stroustrup先生は、「C++の設計と進化」の中で、「例外仕様のランタイムチェックだけをサポートし、静的チェックはツールにまかせることにした」と書いている。しかし、そのようなツールは見つかっていない。