[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[jfriends-ml 1470] Re: assertion 、事前 条件の例外スロー方法
前橋です。
著者校正終了... 現在は再校中。作業的には一区切り付きました。
高橋(徹)さん:
>「契約による設計」をキーワードにあちこちを探ってみました。
>
>> > > ◇P9
>> > > ソースコードの引数チェックにおいて、例外をthrowしているが、こ
>> > > のような処理は良いものなのか、疑問があるという意見あり。
>> > > (スレッドとは関係無い話ですが)
>> >
>> > これはEiffelとかにある「事前条件」をJavaでやってみた、ということなのでは?
>> 「有無を言わせずRuntimeExceptionで落してしまうのはよくないのでは?」
>> という意見です。開発時はよいのですが、運用時にRuntimeExceptionで落ちる
>> のはまずいよねという内容だったと思います。
>JavaReport誌1998年9月号の記事"Prevention Is Better Than A Cure"および、
>JavaReport誌1999年5月号の記事"Concurrent Contracts"(双方Mike Mannion著)
>において、Design by Contractについて解説されていました。
>前者では、Assertionの実装例と使用例が載っています。RuntimeExceptionを
>スローするかException(非RuntimeException)をスローするかについては議論が
>あるようです。
今はもう辿れませんが、昔 Sun の Web サイトにあったJava programmer's
FAQ には、Assert の実装例が載っていて、それでは RuntimeException を
投げていました。
>なお、事前条件はassertによってチェックすべきではないと述べられており、
>通常のコーディングによって引数をチェックし、例外として
>IllegalArgumentException等をスローすることを勧めています。
この手の指針は、私はちょっとどうかと思います。
例えば、年齢を引数として受け取るメソッドで、マイナスの値がやってきたら
そりゃ上位のルーチンが決定的に「バグっている」わけで、そんな状態から
処理を続けてもろくな結果が出るわきゃなかろう、と思うからです。
だから、assertでは、RuntimeExceptionを投げるどころか、スタックトレースを
吐いてSystem.exit()しちゃってもいいぐらいだと思います。JavaOSで動いてる
とかでなければ。
もちろん、呼び出され側である程度の処理をしないと引数の妥当性が
わからない、だから、呼び出し側では、とりあえず呼んでみて
IllegalArgumentExceptionをcatchする、というケースは話が別ですが。
...というのが、C 言語野郎としての私の意見なわけですが、
C だと、ムチャな引数が渡ってくる(バグっている)ということは、
どこかで深刻な領域破壊が起きている可能性が高いわけで、そういう
時には、もうそのプログラムの挙動はまるであてにならないのだとしても、
Javaの場合、基本的に領域破壊はないので、「あっちの方はバグってる
けど、こっちはまだ元気」ということを期待してもよいのかもしれません。
グローバル変数を書きかえられたりしてたら結局一緒でしょうが、その辺は
「うまくやれば」可視性の制御などにより分離できるかもしれません。
また、C の場合、例えば戻り値でエラーステータスを返しても、
呼び出し側でチェックをさぼっている可能性がかなり高く、致命的な
バグの時に悠長にステータスなんぞ返すよりもとっとと殺してしまった
方が確実にバグを捕捉できる、という事情もあるわけですが、Javaなら、
例外はたとえチェックをさぼっても最終的に捕捉できるので、安全かも
しれません。
でも、
try {
処理;
} catch (Exception ex) {
;
}
こんなことされてちゃ困るなあ... そのぐらいならいっそ、Errorを
投げる方がより確実かも。
それに、Javaだと、動的なクラスロードがあるわけで、
例えば、Javaで書いたブラウザがあったとして、変なアプレットひとつ
読みこんだぐらいでブラウザ全体がコケてしまっては困ります。
例えば、変なアプレットが、Graphicsクラスの何かのメソッドを呼んで、
その引数がムチャクチャだった場合などですね。
じゃあ、「Graphicsクラスの何かのメソッド」で「ちゃんと」引数
チェックを行なって、例外を投げて... も、処理が戻るのはその怪しげな
アプレットまでなわけで、やっぱりいまいちです。どうせなら、
そのアプレットのpaint()メソッドの呼び出し元まで戻って、
そんな腐れたアプレットはとっととアンロードしちまって、「なかったこと」
にしたいですよね。
そういうのを実現するにはどうすればいいのかなあ、というのを、
以前から考えているのですが、なんとも...
例えば、その腐れアプレットが、「フレームワーク側」のメソッドを
ごちゃごちゃに呼んで、それが妙な副作用を残していたりとかしたら...
うーん、うーん。
------------------------------------------------------------
前橋 和弥 maebashi@xxxxxxxxx
http://member.nifty.ne.jp/maebashi/
------------------------------------------------------------