達人スターターキット・写経5日目 & アサートと例外

実は昨日終わってましたが。ただ、ちょこっと考えるところがあったんで、行き帰りの電車の中で考えてました。


今回のお題は、オーディオ/ビデオ制御用インターフェースについて。といっても、与えられたことはそんなに難しくありませんでした。秒数を引数に受け取ってテープを進めたり戻したりするメソッドに対して、ユニットテストを用意しなさいというものだったので。

問題は、明示的に指定されていないことに対しての制限について。例えば、今回の場合だったら引数の秒数は業務上マイナスにはなり得ないけど、マイナスが入ってきたらどうするの?とか。

このようなときの対応法としては、↓のような対応が考えられます。

  1. 異常系の入力を握りつぶす
  2. 例外を出力する
  3. アサート文で前提条件を明示しておく

1番は論外でしょう。ただ、この異常系を握りつぶすってのは自他共に含めて意外とやりがちなのですよね。問題なのは、後から見たときに意図して握りつぶしているのか、それとも例外処理を忘れただけなのかが判断しにくいこと。

ということで、2番か3番に絞られるでしょう。

理想から言えば、2番のように正常系・異常系あらゆる場面を想定して異常な場合は例外を出力するべき。ただ、通常ありえない状況(例えば、標準機能・マスタが壊れているとき)などは、逐一例外定義するのも冗長な気がします。

現実的な路線は、3番のようにプログラマが各自の意思で都度アサート文で内部的な条件を明示するぐらいかなと。ただ、設計書とソースコードで乖離していると言えばそうだし、かといって設計書にも逐一アサート文で表明している条件を記述していっても2番と一緒で冗長になるだけだし…。

Javaのドキュメントには、

アサーションは、public メソッド内の引数チェックに使用しないでください。

引数のチェックは通常、メソッドの仕様 (または規約) の一部になっており、アサーションの有効/無効ににかかわらず、この仕様に準拠する必要があります。

という指針があります。

ただ、現プロジェクトのR/3・ABAPに関して言えば、この辺はまた違ってくるのですよね。というのは、ABAPプログラムではprivateという概念がなくて全てpublicだから*1。つまり、どこからでも呼ばれる可能性があるのですよね。

これをpublicだからといって常に引数チェックすると冗長になりがちだというのは、先に述べた通り。じゃあ、どうするの?と考えた中での自分なりの結論。

基本的な方針として、「アドオン機能依存のものは例外出力、標準機能に依存するものはアサートで前提条件明示」と考えました。もちろん、アドオン機能関連でも起こりえないと判断できるものならばアサート文でもいいということにします。

最悪、アサートで前提条件を表明しておけば、その条件に合致しない状況が起こった場合でも(その場でダンプ発生するため)すぐに判断できるはずです。その後に、例外として考慮すべきか異常データとして切り捨てていいかは方針として打ち出されるでしょう。


さて、ここからやることはこの考えを啓蒙すること。上述したように、異常系を握りつぶすことを平気でやってる人もチラホラ見かけます。けど、それだといろいろ危ないので、プログラム内部条件を表明するものとしてアサート構文を導入しましょうと。

けど、アサートって何?って感じな人が(少なくとも現プロジェクトでは大多数)なので、そこから説明か…。


こういうとき、他の言語を触ったことがある人は理解が早いのですが。ま、仕事で触る以外にコンピュータに触れたくもない人も多いことだから、そこまで求めるのは酷なのかな・・・><

*1:ABAP Objectは別だけど、実プロジェクトでは積極的に使われていないので、とりあえず対象外とする