ソフトウェアの“設計”は大きく機能設計(What)と構造設計以降(How)に分けることができます。そのどちらにもついても品質が問われますが、一般に、構造設計以降の品質について議論されることが多いようです。
機能設計の品質が悪いと、いくら構造設計以降の成果物の品質が良くても、顧客の信用は得られません。顧客の要求を満たしていなければ、どうしようもない訳です。
構造設計以降の品質についてはコード化されたプログラム(モジュール)のテストを開始した直後に決定的に明らかになります。品質が良いプログラム(モジュール)は一発目のテストでストーンっと走ります。品質が悪いプログラム(モジュール)は20、30ステップ毎にズッコケます。テストしながらソース・コードを見直すということを繰り返すようでは話になりません。このような悪戦苦闘しているSEやプログラマがいることに気づいていないプロジェクト管理者がいたとすれば最悪です。設計段階から何も見ていない状態だったのです。SEやプログラマを追加したり、交代させ、納期を大幅に遅れて納入できたとしても、顧客の信用は失墜してしまいます。
SEやプログラマの成果物を、制度としての第三者のチェックなしに放任することほど危険なことはありません。旨く行く場合もあるし行かない場合もあります。常に良いかどうかは保証できません。工程毎に成果物の品質をチェックする必要があります。このことについては既稿:レビュー・ファーストで述べましたのでそちらを参照してください。
本稿では設計の良し悪しがソフトウェアの品質に大きく関与していることを述べたいと思います。
機能設計は文章で表現します。機能設計の品質とは利用者が必要とする機能が曖昧なく網羅し、利用者と構造設計以降の設計者に理解できるように記述されているかどうかということです。簡潔で正確に表現されていなければなりません。
機能設計は調査・分析から始めます。実現すべき機能が十分調査されていなければどう書いて良いか緒に着くことができません。何をどうしたいのかを整理するために、検討項目一覧を作成し(新たな項目が見つかり次第追加していく)、検討会と組み合わせます(検討項目一覧サンプル:EXCEL)。最初に関係者が一堂に会し、主催者(議長)が実現したいことの概要を提示します。議論は実現すべきことの理解から始まります。理解できれば概要(漠とした考え・期待していること)の具体化に入ります。関係者はいろいろな考えを持っていますので、意見を聞き、あるいは文書にしてもらい、実現すべきことを細部に到るまで表現する必要があります。こうした作業を円滑に進めるための手段として検討項目一覧と検討会は大変役立ちます。検討会の成果は議事録にまとめます。検討会は何回かに分けて進めますので議事録が必要です(議事録サンプル:WORD)。
このようにして検討会が進められる中で機能設計の素材(議事録の中に記載されている資料)が揃っていきます。十分に素材が準備できたところで機能設計の執筆を開始します。関係者の中の主要メンバが中心となって機能設計を担当します。はじめに機能設計書の目次案を作成します。目次案は機能設計の執筆を開始する前に作成し、体系的な記述となることを目指し、また、執筆を分担し、進捗状況を把握するためにも役立ちます(目次案サンプル:EXCEL)。
機能設計の執筆が終われば、利用者と構造設計以降の設計者を交えてレビューを行います。利用者の要求が盛り込まれているか、利用者が容易に使えるか、効果が発揮できるか、記載されている機能の技術的実現性、盛り込まれた機能の実現に必要な費用、などがレビュー観点として重要です。近年、使用できる既存のソフトウェアが多数存在するので、そうしたソフトウェアの使用で賄えるかどうかを見極めることもこの段階で行います。既存ソフトウェアを使用する際の注意点は、そのソフトウェアが目的の機能を満足させるものか、信頼性はあるのか、保守性はどうか、権利関係に問題はないのか、等々多岐にわたります。業務システムの設計の場合、業務フローを用いて組織の各部署とソフトウェア・システムの関連を明らかにしておき、この業務フローを用いて各部署の利用者とソフトウェアの機能についてレビューするのが効果的です。
機能設計の品質評価の基準は、期待された効果を発揮できる仕様になっているか、仕様に漏れ・曖昧さ・矛盾がないか、不要な機能がないか、限界値(トランザクション数、スループット、レスポンスタイム等)が明示されているか、構造設計者が理解できる表現になっているかなどです。
構造設計以降の設計では、複雑さの排除がソフトウェアの品質向上のキーです。複雑さの排除の1つはプログラム(モジュール)に存在する局所的な複雑さを最小化するものであり、2つ目はソフトウェア・システム全体に及ぶ大局的な複雑さの最小化です。このことについてはGlenford J. Myers氏が1978年に著した「ソフトウェアの複合/構造化設計:近代科学者」で明らかにされています。当時話題になっていた構造化設計で解決 しようとしていたのは局所的な複雑さの最小化ですが、Myers氏はそれだけではソフトウェア・システムの大局的な複雑さを最小化できないと指摘し、問題の解決には、プログラム(モジュール)の強度と結合度という視点からモジュールの強度を最大化し、かつモジュール間の結合を最小化する考え方について明らかにしています。
構造化設計による局所的複雑さは、当時のプログラミング言語で許していたGOTO文が論理を分断し、プログラム(モジュール)を分り難くしていましたので、GOTO文なしでプログラミングできるような制御文の導入が図られました。while文(for文)、case文(select文)、release 文、exit文などにより、プログラムの制御構造がより分り易くなり、制御の分断を回避できるようになりました。これらの制御文は現在使われているプログラミング言語では常識になっていますが、当時は革新的だったのです。
ところが、これらの制御文を導入したところで、ソフトウェア・システムの大局的な複雑さを解決できる訳ではありません。
複数の機能の実現に際し、それらの機能を実現するコードに共通部分が多いという理由で、1つのプログラム(モジュール)にまとめてしまうと、後日それらの中のある機能の追加・変更が必要になったとき、当該プログラム(モジュール)の更新は大変複雑になります。他の機能の実現に影響することがないことを保証する必要があるからです。Myers氏はこのようなプログラム(モジュール)の強度は低いとして、関係がない機能を寄せ集めたプログラム(モジュール)は避けるべきと指摘しています。機能とプログラム(モジュール)の関係を、1)情報的強度、2)機能的強度、3)連絡的強度、4)手順的強度、5)時間的強度、6)論理的強度、7)暗号的強度の7つのカテゴリに分け、具体的な構造と特徴を説明しています。1)と2)の強度が最も強く、番号順に弱くなっています。強度が強いプログラム(モジュール)ほど望ましいのです。
プログラミング言語の外部データや共通データ(これらはモジュール間で自由に参照・操作できる)、PL/I言語などにあるポインタ・データはどのモジュールでどのデータを操作しているのか不明瞭にすることがあります。外部データや共通データはどのプログラム(モジュール)が参照・操作しているか明示的に分らないため、後日そうしたデータの位置や属性などの変更が必要になったとき、関係しているプログラム(モジュール)の洗い出しの手間が掛かったり、変更忘れが不具合の要因となります。外部データや共通データ、ポインタ・データを通して複数のプログラム(モジュール)が癒着してしまうのです。Myers氏はこのようなプログラム(モジュール)間の結合度を、結合度が弱い順に、1)非直接結合、2)データ結合、3)スタンプ結合、4)制御結合、5)外部結合、6)共通結合、7)内容結合の7つのカテゴリに分け、具体的な構造と特徴を説明しています。プログラム(モジュール)間の結合度が弱いほど望ましいのです。
オブジェクト指向言語はある程度、上記の問題を避けられる仕様になっていますが、プログラミング言語だけで防止できる問題ではありません。プログラム(モジュール)の強度の問題は、クラス、インスタンス、メソッドを使うことにより、Myers氏が述べた情報的強度となるように誘導されていますが、メソッドの引数に機能コードを持たせて論理的強度のプログラム(この場合メソッド)が作成できます。このようなメソッドは分りにくいものとなります。また、外部データや共通データ、ポインタ・データなど、プログラム(モジュール)の結合度を強めるデータがJavaなどには存在しませんが、データベースを経由して同様のコードを作成できます。従って、オブジェクト指向言語だけでソフトウェア・システムの複雑さを解決できる訳ではありません。
ソフトウェアの設計と品質の関係で最後に指摘しておきたいことはソフトウェア・アーキテクチャです。ソフトウェアの設計は、決められた方式に従って仕様書(要求、機能、構造、インターフェースなどの仕様書)を書くだけではなく、思考を容易にし、理解し易い、拡張性・保守性が良い、性能が良い、などを考慮ておかなければなりません。こうしたことは、設計指針あるいは設計条件として、設計に先立って規定しておく必要があります。そしてSEやプログラマがそうした設計指針や条件を十分理解し、準拠した行動をとることが必要です。これらはソフトウェア・アーキテクチャの問題です。 ■