問題。文字列の指定位置にあるマルチバイト文字が何バイトで構成されているか判定する関数を考える。その関数の引数として、与える文字列の長さに等しい値を、判定すべき文字の位置(インデックス)として指定した場合、この関数仕様は以下いずれが望ましいか。
- 成功とし、0バイトと判定する
- 例外(対象が見つからない)とする
- 例外(引数不正)とする
答え。1または2だと思います。個人的には1です。ただし不正バイト検出時は「1バイト」と返す仕様であることが前提ですが。
理由。関数単体で考える限り、どの仕様でも良いでしょう。ですが、この関数の機能説明を読むとマルチバイト文字の数を数える用途に応用できると感じます。であれば、その使い方を含めたより広い使い方ができるような仕様にすべきです。ということで仕様3を前提に、そのような用途に使ったコードをためしに書いてみると次のようになるでしょう(Javaで記載):
int charCount = 0;
int index = 0;
while( index < str.length() ) {
try {
index += GetCharLengthAt( str, index );
charCount++;
}
catch( IllegalArgumentException e ) {
break;
}
}
System.out.println( "Number of characters: " + charCount );
一見すると問題無いように感じますが、一つ問題があります。引数不正は一般的にランタイムエラーではなく「プログラムエラー」、つまり(少し雑に言うと)「基本的にcatchしてはいけない例外」です。というのは、この類の例外をcatchしてしまうと(1)何らかのミスを犯して不正な引数を指定してしまった場合と、(2)正常に文字列の末尾に到達した場合が、区別できなくなります。というわけで、そのような例外をcatchさせることを助長する外部仕様になる点で、仕様3は避けるべきだと考えるべきでしょう。なお考え方としては、例外機構の無いC言語などでも同じです。
関数(メソッド)の外部仕様を設計する場合、ソレ単体および「ソレがどう使われうるか」も考慮に入れるとより使いやすい設計が可能になります。
以上、暇つぶしにでもなれば幸いです。