2015年6月7日日曜日

[大規模システムの設計]特性の把握(2)

 前述した3つの記事は、いずれも概念的な説明に終始していた。「では具体的にどうするのか」という点についての記述していく。
 どのような大規模システムにも共通する汎用的な技法は限られているが、概ね次の通りである。

 (1) システムの大枠を7~10程度のサブシステムに分割する。
 (2) 必要に応じて、更に階層的にサブシステムを分割する。
 (3) 各サブシステムはAPIもしくはバッチから実施可能なエントリを持たなければならない。
 (4) 各サブシステムは、分割した全ての単位において入力に対する出力を想定したテストを作成する。
 (5) 上記(4)のテストは全て自動で実施し、結果の検証も自動でできなければならない。
 (6) 上記(5)の自動テストは、概ね3時間以内に完了できなければならない。

 あなたが大規模システムの設計者で、2つ以上クラスが上の上司(たとえば専務取締役、常務取締役、執行役員など)に、システム概要を説明しなければならないとき、いきなりA3かA2のビッグサイズの紙に数百に及ぶ機能を矢印で結んだ資料を出してはいけない。
 先にも解説した通り、大規模システムとはいかなるときでも管理可能性を失ってはならず、管理する側にとって煩雑なものであってはならないのである。人間が一度に把握でき記憶できる事項は多くて7~10程度、これを大きく逸脱した機能分割の図を出すのは危険である。数百もの機能が書かれた図を出されて、すぐにそれを理解しなさいというのは、管理可能性をその時点で失っているものと見なされる。
 少しでも「他人が見る」ということを考慮しているならば、大規模システムの機能分割は階層的なものにせねばならず、各階層も10~20の数を超えた複雑なものをなるべく避けるべきであるということが分かるだろう。A3の紙にびっしり書かれた数百の機能相関図を見て、「優秀だ」と判断されることはない。階層的に書かれた、見る人にとって分かりやすい程度の矢印で結ばれている機能相関図を出して初めて、レビューがスタートするのである。
 その他の事項についても、補足説明を記述する。
 上記(3)は実装を意識した不正な設計ではないので注意されたい。最終的にWindowsタスクスケジューラ、cron、JP1などで呼び出す単位を決める、という意味である。この単位はサービスと言ったり、ジョブといったり、タスクといったり、プロジェクトによりまちまちであるが、設計書と実際に実行するプログラム単位が揃っていないと混乱を招くので、この条項は必須である。「設計は実際にプログラムを実行する単位の記述ではありません。JP1で実施する実際のソフトウェアと、設計は別物です」というのは設計者としては正しいかも知れないが、管理者からは煙たがられるだろう。呼び出す機能単位もパラメータ分からず、JP1のジョブ設計などできないからである。このようなプロジェクトに混乱をもたらす設計及びその成果物は、いずれ意味をなさない資料とならざるを得ない。
 上記(4)~(6)は、大規模システムの変更可能性を最大限にするための仕組みである。JUnitテストに代表されるホワイトボックステストではないので注意されたい。もちろん条件分岐網羅の回帰テストができることは必要であるが、それに加えて更に、実装ではなく設計レベルの回帰テストの仕組みも用意する、ということである。
 JUnitその他のツールによるテストはホワイトボックステストであり、実装の構造に準じて作られるものであるが、上記(4)~(6)のテストはブラックボックステストである。「設計に定める機能仕様からすると、この入力に対してはこの出力、この入力に対してはこのエラーが出るはずである」といったことを自動テストとしてまとめていくものである。
 このテストは分割した機能の全てについて実施しなければならない。たとえば最上位を7つの単位に分割し、それをさらに5~10くらいの単位に分割する階層構造があった場合、最上位の7つの単位にも自動テストが必要であり、その下にある全ての階層にも自動テストが必要である。これは機能の再利用性にとって、非常に重要だからである。プログラムの変更を考えるとき、「既存機能を呼び出したい」というニーズが必ずあるはずである。このようなとき、機能単位ごとに完全な回帰テストの仕組みを持っていれば、既存機能を呼び出して意図した動きとなるか、それともインターフェース等で問題が起きるか、すぐにテストすることができる。この仕組みを持つことによって初めて、数百から数千に分割された機能を、途中のインターフェース等の問題を気にすることなく、呼び出すことができるようになる。もし問題が起きたら、既存機能のコードを流用して問題が起きない新規コードを作成し、既存機能をそのまま使ってよいという結論に到達したら、新しく追加した機能(もしくは変更した機能)そのものの回帰テストを新たに作り直せばよい。
 また上記(5)~(6)にあるが回帰テストは完全に自動化し、3時間程度で実施できなければならない。つまり、システム全体の完全なブラックボックステストを毎日実施できるようにしなければならないということである。もしもバグが出たのならば、そのバグを検証するためのテストを追加していくことにより、品質はほぼ完全にバグがゼロの、理想的な状態に近づけることができる。JUnit等による実装レベルでのホワイトボックステスト、機能単位で実施するブラックボックステスト、過去に起きたバグが起きないことを検証するための回帰テストを随時、短時間で実施できる仕組みを整えることで、大規模システムの品質を常に安全な状態に保つことができる。
 大規模システムは後戻りができない厳しいものであるからこそ、このような初期段階での考慮・ノウハウを大切にする必要がある。その他、プロジェクトの特性に応じて考慮しなければならない点は数多く存在する。携帯電話のハードウェアを駆動するためのミドルウェアと、JavaによるWebアプリケーションでは、同じ大規模システムでも全く異なる特性があることに気付くだろう。上記に挙げたような最終的な品質や、その後のメンテナンスを左右する大切な要素を決して忘れることなく、なおかつプロジェクトの特性に合わせた設計前の考慮事項を検討していかなければならない。

0 件のコメント:

コメントを投稿