Cで作っていたライブラリを、Androidで動かそうと移植している。
まあ、NFC関係ですわ。
そうなると、Cでは戻り値でエラーを返していたところが、Androidでは例外で返すようになっているところがある。
そんなときは、例外をcatchしてエラー値に変換していた。
そしてエラーの戻り値としてenumを定義し、catchして変換をするようなことを書き始めて、ふっと思った。
「このまま例外で処理したらいいんじゃないの?」と。
例外を返すようにして、呼び出しの一番上でcatchするようにすると、ソースの見栄えが非常によろしい。
ret = proc1();if (!ret) {
return ERR1;
}ret = proc2();if (!ret) {
return ERR2;
}
とか、
ret = proc1();if (ret) {
ret = proc2();}if (ret) {
ret = ....
とかが、
try {
proc1();proc2();proc3();...}catch(xxxException e) {
xxx;}catch(yyyException e) {
yyy;}
みたいになって、ロジックとエラー処理を別々に書ける。
まあ、エラーの種類によって動作を変えることもあるだろうけど、見通しはよくなると言うのはわかる。
そうなってくると、エラーが起きたときに、戻り値で返すのか例外で返すのか、がだんだんわからなくなってきた。
C++では、例外のコストがけっこう高いのと、組込みのC++は例外が外されてることもあったので、実はそんなに使ったことがない。
Cでは、gotoとラベルを使って、(ソースの見た目上は)似たようなしくみを実現しているのを見かけたことはあるが、私自身は戻り値で知らせる派であった。
ただ、例えば引数がNULLだったり範囲外だったりしたら、お仕事ではチェックしてエラーを返したりするけど、自分でやるときはassert()で落としたりしている。
これがJavaだと、NullPointerExceptionとかIllegalArgumentExceptionがあるので、それを返すだけになっている。
assert()だとNDEBUGで無効になるし、なによりアプリが落ちる以外の選択肢しかないのが厳しい。
「ダメなんだけど、何も死ぬことはない」という状態だ。
この辺については、自分の中で整理をしないといかんですな。
僕は引数に問題があって例外が発生した場合はthrowsで呼び出し元に処理してもらって、それ以外はtry-catchでメソッドの中で処理する・・・って感じにしていますが、これ難しいですよね。他の人はどうしてるんだろ
返信削除引数の間違いなんて大したことじゃないから戻り値で、と思ったんですが、どのメソッドにもありがちなのに戻り値だけでこれを表現するのは難しいから、例外がよいんですかね。
削除Cとかだと、関数の戻り値はとりあえずintにして、戻り値は正常/異常を返す、みたいなやり方もあり、これはこれでわかりやすかったのですが、引数で戻り値を返すことができるからかなぁ、とも思ったり。
考察はまだまだ続きます!