防御的プログラミングとカバレッジ [プログラマー現役続行]
防御的プログラミングでは、外部からの呼び出しから防御します。しかし、それ以外に、自分自身の誤りに対して防御するということがあります。
次のコードは、『Effective Java 第2版』(p.147)に掲載されているコードです。
後々の保守や機能追加で定数値が追加され、
このようなプログラミングは、呼び出しパラメータの不正値の検査と同様に、障害を短時間で調査するためには重要です。
一方、このような防御的プログラミングを行っていないソフトウェア開発組織では、テストによるコードカバレッジは、単体テストでは100%でなければならないという目標値を設定してしまいます。当然、上記のコードでは100%は無理です。
ソフトウェアの開発効率、特に、障害の短時間での原因調査と対策を行うのに有効なのはコードカバレッジ100%ではありません。有効なのは防御的プログラミングです。上記のコードで、カバレッジを100%にするために、
コードカバレッジ100%を常に達成していますと言う開発組織があったとしたら、このような防御的プログラミングは一切行っていないことを意味すると思います。
次のコードは、『Effective Java 第2版』(p.147)に掲載されているコードです。
ここで、注目するのは、最後の// 値によって切り替えるenum 型- 問題が多い public enum Operation { PLUS, MINUS, TIMES, DIVIDE; // 定数で表される算術操作を行う double apply(double x, double y) { switch(this) { case PLUS: return x + y; case MINUS: return x - y; case TIMES: return x * y; case DIVIDE: return x / y; } throw new AssertionError("Unknown op: " + this); } }
AssertionError
をスローしている部分です。定義したenumの定数値はすべてcase
ラベルで列挙されていますので、例外がスローされることはありません。後々の保守や機能追加で定数値が追加され、
case
ラベルの追加を忘れた場合に、そのことを検出するための防御的プログラミングとなります。つまり、switch
で、default
ラベルを書いて普通の処理をするのではなく、すべてcase
ラベルで列挙し、default
ラベルではAssertionError
をスローすることで、「設計上、起きてはいけないことが起きている」ことを検出できるようにしておきます。このようなプログラミングは、呼び出しパラメータの不正値の検査と同様に、障害を短時間で調査するためには重要です。
一方、このような防御的プログラミングを行っていないソフトウェア開発組織では、テストによるコードカバレッジは、単体テストでは100%でなければならないという目標値を設定してしまいます。当然、上記のコードでは100%は無理です。
AssertionError
をスローしている部分は、どんなに頑張っても実行することはできません。ソフトウェアの開発効率、特に、障害の短時間での原因調査と対策を行うのに有効なのはコードカバレッジ100%ではありません。有効なのは防御的プログラミングです。上記のコードで、カバレッジを100%にするために、
apply
メソッドが次のよう書かれたとしてみてください。enum定数値を追加し、// 定数で表される算術操作を行う double apply(double x, double y) { switch(this) { case PLUS: return x + y; case MINUS: return x - y; case TIMES: return x * y; default: return x / y; } }
case
ラベルの追加を忘れても、コードカバレッジ100%なのです。そして、case
ラベルの追加を忘れで障害が発生しても、すぐには原因が分からないかもしれません。コードカバレッジ100%を常に達成していますと言う開発組織があったとしたら、このような防御的プログラミングは一切行っていないことを意味すると思います。
2010-06-05 05:12
nice!(1)
コメント(0)
トラックバック(0)
コメント 0