■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 2009年04月27日 Java総合講座 - 初心者から達人へのパスポート vol.150 セルゲイ・ランダウ バックナンバー: http://www.flsi.co.jp/Java_text/ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ [このメールマガジンは、画面を最大化して見てください。] ======================================================== ◆ 01.SOAPのアプリケーション(Webサービス) ======================================================== 「契約による設計(Design By Contract)」(あるいは「契約によるプログラミング (Programming By Contract)」)は、Eiffel(エッフェル)というオブジェクト指向 言語の創始者であるバートランド・マイヤー(Bertrand Meyer)が、その著書「 Object-oriented Software Construction」の中で提唱した、ソフトウエアの品質および 生産性を向上するための考え方です。 ここで言う「契約」はあくまで比喩的に使っている言葉であり、我々が商取引などで 行っている本当の契約とは違います。平たく言うと、「約束ごと」と言い換えたほう が分かりやすいでしょう。 「契約による設計(Design By Contract)」は、プログラムが仕様通りに作られてい ることを確証するための方法として考えられたもので、クラス(のメソッド)側と クラス(のメソッド)の呼び出し側との間の約束ごとをプログラムの中に明記する という方法を取ります。 この約束ごととは何かというと、「あなたがこういう条件(事前条件(precondition)) に従えば、私はこういう結果(事後条件(postcondition))をもたらすことを約束しま す。」という内容の宣言です。 噛み砕くと、「メソッドに渡す引数の値が予め決められた条件(事前条件)に従って いれば、このメソッドは仕様通りの結果(事後条件)を返します。(逆にもし、引数の 値が、決められた条件に従っていない場合は、どんな結果を返すか保証できません。)」 ということです。 具体的にどのようにして約束ごとを明記するかというと、プログラム内にAssertion (表明)と呼ばれるコードを入れることによって事前条件や事後条件を明記します。 実際に、 「宿泊日数(numOfNights)は1以上でなければならない。」 「宿泊人数(numOfLodgers)は1以上でなければならない。」 という事前条件をAssertionを使って明記してみましょう。 Javaでは、このAssertionは次のようなコードで表記します。 assert numOfNights >= 1; assert numOfLodgers >= 1; あるいは、(numOfNightsやnumOfLodgersは整数なので)上記の条件は、 assert numOfNights > 0; assert numOfLodgers > 0; というふうに書いても同じです。 なお、一般にassertの右側には普通の論理式を記述できるので、 上記の2行の文は、 assert numOfNights > 0 && numOfLodgers > 0; のように1つの文にまとめてもかまいません。 そしてもし、上記の条件を守らなかった場合は、これらのassertというコードを 実行したときにAssertionErrorというエラーが発生します。 といっても、ここまでの説明だけでは、まだ何のためにAssertion(assertという コード)を入れるのか、よく理解できないかもしれません。 というわけで、実際に簡単なプログラムを書いて、このassertの機能をテストして みましょう。 下記のような(AssertTestというクラス名の)クラスを作成してみて下さい。 -------------------------------------------------------- public class AssertTest { public static void main(String[] args) { try { AssertTest test = new AssertTest(); test.warikan(5, 0); } catch (AssertionError e) { System.out.println("Precondition failure!"); } } public int warikan(int numOfNights, int numOfLodgers) throws AssertionError { assert numOfNights > 0 && numOfLodgers > 0; return numOfNights * 50000 / numOfLodgers; } } -------------------------------------------------------- このwarikan()というメソッドは、事前条件として引数のnumOfNightsとnumOfLodgersが どちらも0より大(つまり、正の数)でなければならないという仕様になっています。 そして、その仕様をassertのコード、すなわち assert numOfNights > 0 && numOfLodgers > 0; で表明しています。 これを保管(コンパイル)してから実行してみましょう。 これを普通に実行しても、assertの機能は働きません。 実は、普通に実行すると、assertのコードが無いものとして扱われて、事前条件の チェックは行われません。そして、そのまま return numOfNights * 50000 / numOfLodgers; の行まで実行されて、0で割り算をしてしまうために(0で割り算してはいけないことは 数学で習ったことと思います)例外ArithmeticExceptionが返ってきます。 このような例外が返ってくると、一見、warikan()メソッドが悪いと思ってしまうかも しれませんが、本当はwarikan()メソッドを呼び出したmain()側が事前条件に違反して いることが悪いのです。 このことを確証するためには、assertの機能を有効にしておく必要があります。 assertの機能を有効にするためには、実行時にオプションの -enableassertions または、その省略形である -ea を指定する必要があります。 これは、コマンド・ラインでは、 java -ea AssertTest のように指定すればいいし、Eclipseで実行する場合は、パッケージ・エクスプロー ラー内でAssertTest.javaを右クリック→「実行」→「構成および実行」を選択し、 「引数」タブをクリックして、「VM引数」の欄に -enableassertions または、 -ea を入力してから「実行」ボタンをクリックすればいいです。 (ただし、この「構成および実行」のウインドウに設定したVM引数は、必要なくなった ら削除しておいてください。さもなければ、あとで、普通に実行した場合(つまり、 AssertTest.javaを右クリック→「実行」→「Javaアプリケーション」を選択した 場合)にも、そのままVM引数が有効のままになってしまいます。) こうしてassertのコードがはいっているメソッドをテストすると、事前条件が満たされ ていない(違反している)場合には、ただちにAssertionErrorを投げてメソッドが終了 してしまいますから、要するにメソッドは実行されないことになります。 そもそもこの場合は、事前条件に違反した呼び出し側が悪いのであって、こういう 場合にはメソッドをテストしても意味がないわけなのです。こういうときにもし assertのコードを入れておかないと(あるいはassertのコードを入れてあってもassert の機能を有効にしていないなら)、メソッドが実行されて、おかしな結果(今回は ArithmeticException)が返ってきて、メソッドが悪いのではないかと疑って、メソッド を修正しようとしてしまう恐れがあります。 仕様に正しく従っている場合には、そのような修正は不要(そのメソッドが悪いの ではなく、メソッドを呼び出している側が悪いのであり、修正すべきなのは呼び出し 側)なはずなのであり、このような修正は間違い(もしくは余計なこと)なのです。 今回は、簡単なプログラムでテストしたので、Assertionのありがたみが実感しにく かったかもしれませんが、実際のソフトウエア開発では、はるかに複雑なプログラム を扱うことになりますから、assertのコードを入れておかないと、こういった見極め が困難になり、生産性を大幅に落とすことになり、ひいては品質を上げるために大変な 苦労をすることになってくるのです。 ただし、このassertのコードはテスト時のみに有効にすべきものであり、テストが すべて完了(テストで不具合が判明したものがすべて修正されて、最終的にテスト 結果がすべて合格になったとき)になって、本番運用に入るときには、上記の -enableassertions または、 -ea のオプションは外します。(このとき、プログラムには一切変更は加えません。あく まで実行時オプションが変わるだけです。) (次回に続く) では、今日はここまでにします。 ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ★ホームページ: http://www.flsi.co.jp/Java_text/ ★このメールマガジンは 「まぐまぐ(http://www.mag2.com)」 を利用して発行しています。 ★バックナンバーは http://www.flsi.co.jp/Java_text/ にあります。 ★このメールマガジンの登録/解除は下記Webページでできます。 http://www.mag2.com/m/0000193915.html ★このメールマガジンへの質問は下記Webページにて受け付けて います。わからない所がありましたら、どしどしと質問をお寄 せください。 http://www.flsi.co.jp/Java_text/ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ Copyright (C) 2009 Future Lifestyle Inc. 不許無断複製 |