で、今日は、前に書いたとおり、DBの話
で、その話を始めるにあたり、まず、ここで取り上げるDBのプログラムというのは、どういうのをさすかについて、規定しておきます。
たとえば、モデルの中、あるいは、Viewやコントローラーから直接DBにアクセスするようなプログラムは、今日の話題から除きます。
なぜなら、たとえば、StrutsのActionクラスから直接SQLを発行するプログラムをテストする方法は、SQLを発行しているかどうかの問題にかかわらず、Actionクラスのテスト方法になります。
Viewについても、Viewのブラックボックステスト(項目と、その値チェック法の組み合わせ)で行い、DBにアクセスしているかどうかは、付加的な問題だし、モデルについても、そのテスト方法は、単体のホワイトボックス、ブラックボックスとしての、モジュールの引数の境界値テストに落とし込めてしまいます。
それらについては、このブログのほかで話しているので、そっちを見てください。
今日の話の対象は、DBや、ファイル、プロパティなど外部入出力に関して、直接操作をするクラスの設計とテスト方法です。
これには、いくつかあります。
1.DBの場合なんですけどO/Rマッピングを使う
2.J2EEなら、セッションBean
3.入出力用のハッシュマップを使い、テーブルごとにクラスを作成する
→この場合、テーブル定義書から自動生成する
4.入出力用のハッシュマップを使い、1つのクラスで行う
→実はテーブルごとに、クラスがなくてもかまわない。。
■■ このようなクラスが必要になった背景
では、なぜ、このようなクラスが必要になったのか、つまり、モデルから直接SQLを発行しないのかについての理由を書区と同時に、これらのクラスで要求される内容をかきます。
(1)実は、テーブル項目がよく動いてしまう。
ふつう、ウォーターフォールで開発した場合、テーブルの項目は(プログラム開発前に仕様がかたまるから)動かないはずです。
しかし、IT1レベルでのミスがあると、そのバグ修正のために、項目は動きます。
(アジャイルの場合も、動くことはありえると思います。もちろん、バグ修正でも動くと思います)
その項目修正のたびに、SQL文を修正するということになりますが、そうすると、おおきな開発の場合、項目の変更は、1日や2日では、修正があがってきません(メールで流せばいいと思うかもしれないが、関係者がわからないので、だれにメールを回すべきかすら、確定できないことがある)。
その間テストできないと困ります。
なので、以下の要求を満たさないといけません
(1-あ)項目が変わって、変更項目に修正しても、コンパイル、リンクでエラーにならない
(たとえば、その項目のgetter,Setterなどを作ってしまった場合、項目が削除されて、そのgetterも削除してしまったら、まだ修正していない人が、いた場合、そのメソッドを呼び出しているので、リンクできず、作成できない。これは、絶対に避けなければならない。同様に、クラスに項目があるのもまずい)
(1-い)項目が変わっても、変更期間内は、古い項目における値が以前と同様に取得できるようにして欲しい
ただし、変更期間後は、古い項目における値は取得できないようにしてほしい
できれば、警告をだしてほしいが、Javaのコンパイラのように、コンパイル時だけでなく、実行時にできるカラクリのほうが、のぞましい。
この理由は、次のとおりです。
項目変更、テーブル変更があった場合、朝会(あさかいとよんでね、別に社歌を歌い、社長の説教を聴くのではなく、朝、進捗報告を行い、変更点、問題などについて報告する会のこと。朝に限らず、夕会、昼会、夜会などもあることがある。スクラムでう、デイリースクラムに相当するんだと思う)で報告されると思います。
朝会で報告が合った場合、マネージャーはその旨を報告し、プログラマーは修正し、修正後、単体テストを行い、構成管理にのせます。
ということは、プログラマーが単体テストを行う時点で、修正はなされていないといけません(じゃないとテストできません)。ところが、そのとき、その修正している(単体テストをやっている)プログラムを呼び出している人たちもいます。その人たちが、IT1を行うには、修正前のプログラムの状態で呼び出しているわけです(単体テスト中=修正プログラムはまだ来ていない)。
だから、その人たちのために、修正前の状態でも、呼び出せないといけません。
さらにさらに、マネージャーがすべてのプログラムを把握してるわけではないので、修正連絡漏れがありえます(というか、普通あります)その人たちにわからせるためには、プログラムをよびだしたら、どの部分のどの項目が変わったのかを、知らせてあげないといけません。そのため、古い項目で呼び出されたら、メッセージが出ることが望ましいです。
これをまとめると、(1-い)になります。
(2)実は、データベースでいくか、ファイルでいくかを決めかねるときがある
(アジャイルはもちろん)ウォーターフォールでも、この項目を、DBにいれるか、ファイルでもつか、サーバーに置くべきか?クライアントローカルで持っておいたほうがいいか、決まらないで開発することがある(実際ウィリアムのいたずらは。、そういう開発に携わったことがある)。
このとき、ある皮をかぶせてしまい、その中で、DBアクセスするか、ファイルでいくか(プロパティファイルで行くか)、サーバーとアクセスするかを吸収して欲しい。その上のモデルレベルでは、リソースは何であれ、その(皮の)クラスにアクセスすればいいようにしてほしい。
というか、そうしないと、開発が進まない。
なので、以下の要求を満たさないといけません
(2-あ)DBもファイルも、リモートアクセスも、ぜんぶひっくるめて、あるクラスを呼べば、とにかく、レコードを取得できるようにしてほしい。DBもファイル等のリソースの違いは、このクラスで吸収して欲しい。
(2)実は、データベースを手配できないで、CSVでやってほしいときがある
IT1フェースだと、いいんだけど、単体フェースだと、そんなにDBを用意できないときがある
(単体を開発しているチームが、「お持ち帰り」で、DBソフト持ち出し禁止の場合など)
そういうとき、CSVで単体はとりあえず、確認してもらいたいことがある
なので、以下の要求を満たさないといけません
(3-あ)Jarまたはクラスを変えただけで、DBアクセス用、CSV用が切り替わって欲しい
CSV用は、指定されたとことに1テーブル1ファイル、ファイル名=テーブル名の形で入っていて欲しい。
で、これらの要望を満たすと、O/Rマッピングを使うのではなく、普通
3.入出力用のハッシュマップを使い、テーブルごとにクラスを作成する
4.入出力用のハッシュマップを使い、1つのクラスで行う
になってくると思います。
ということで、3についてですが。。。
えー(@_@!)
これの設計方法と、テストの話(=ここからが本題)
を書こうと思ったら、もう、こんな時間だ。。
本題に入ってないじゃん(^^;)
お仕事しないといけないので、とりあえず、ここまで。