【第36回】クラステクノロジー アーカイブス 構造化設計入門 -1991年の論文より抜粋

最近のユーザの傾向を見ると、要求仕様をきちんとまとめて提案し、上流から下流へしっかりと定義された仕様に従って進められるウォータフォーリング・モデル的な開発が少なくなって、ニーズがなかなかまとまらず、作ってみてから判断評価して改修を加えてゆくプロトタイプ的な開発が多くなっている。
原因として考えられるのは、マシンのコストダウン、OA化によるマシンの普及に伴って、コンピュータ自体が会社にとっては珍しい投資ではなくなってきており、従って、その要員であるEDP部門にかつてのように力を入れなくなったという事情や、次々と高度化してゆくニーズをクリアするために、システム規模が巨大かつ複雑化してきて、一担当者レベルの判断では単純に仕様を決めることができなくなっているということがあげられるかもしれない。
この傾向は、今後ますます強くなるだろうし、プロトタイプ的開発はもう既に一部の世界では一般化しているとも言えるだろう。そうなると、仕様通り動けば中身はどうでも良いというSPECでは全く役に立たない。

OS/2の開発者の1人である、G.レトウィンの言葉に、「プログラムは60%の工学と20%の科学と20%の芸術から成り立っている」というのがあっ て、工業製品と言いつつも、仕様通り作っただけでは良いとは言えないプログラムの性格をよく言い表している。この20%の芸術性こそ、システムのフレキシビリティであり、こういうスキルなしに改造や第三者による保守を前提としたシステム開発は出来ない。工業製品であって工業製品でないソフトウェアを工業製品化するために、構造化プログラムが叫ばれるのである。


<構造化プログラムの条件>
クラステクノロジーでは、ジャクソン構造化設計を基本的な理論として薦めている。
これは、「良いデータ構造」を前提とした、他のあらゆる構造化理論の中の1スタイルであって、説明は豊富にあるものの、良いデータ構造がいかにより良いプログラム構造を導かという議論に終始していて、当然、現実に必要なロジックの全てをこの理論と手法の中から叩き出すことは出来ない。
現実のシステムは、データ構造を規定出来るような新規のものばかりでなく、既存の悪いデータ構造(アプリケーションの観点に立てば必ずしも悪いとは限らない)を継承して構築されるものも多い。そのどんな状況においても前提条件を掲げることなく、改造に耐えうる保守性の良い設計を達成しなければならないという問題に直面しているのである。
ジャクソン法の評価については、J.マーチン、C.マックルーアの「ダイアグラムによるソフトウェア構造化技法(Diagramming Techniques for Analysts and Programmers)に以下のような評価があるので参考までに紹介しよう。
いろいろな方法論の中では、おそらく最も学びにくく、正しく使うのが難しいものである。
分割に走る傾向があり、複雑なプログラムに適用するのは非常に難しくなる。この理由から、マイケル・ジャクソンの方式の採用を取りやめたところもある。
これは非常に変化の激しいデータベース/データ通信環境には適さない。 こういう環境ではデータベースが非常に大規模で複雑であり、ユーザーからの変更申 し入れがデータベースの構造や内容に絶えず影響を与える。この種の分割を行うと、データ構造が変わるたびにプログラムはやむを得ず大量のプログラム・ コードを捨てることになる。

前述の引用にもあるように、ジャクソンの理論は適用が難しく、現実の複雑な処理を組みあげるには開発メンバーが追いついていけない。
入力の木と出力の木を1,000STEP位のリアル処理か何かで作成出来るかどうか試行してみれば、その難解さが実に非現実的なアプローチであることに誰しも気づくと思う。
誰もが理解出来て、誰もが実践出来なければ方法論としては意味がない。
私は、協力会社のSE各氏などから具体的にどうすればいいのかわからないという指摘もあって、以下のような条件を定義して、詳細設計の基準として理解して貰っている。


<木構造による構造化プログラミング>
1. トップダウンによるモジュール化であること
2. 同じネストのモジュール同志は均一なウェイトを持つように分割する
3. GO TO文は、下へのものであれば必要な範囲(セクション内)で許す。上へのGO TOは許されない
4. いかなるレベルであっても、ボトムアップの設計を加味してはならない
5. 末端の葉は20STEP位までの含みがあってよいが、IF文やLOOP文が内在していてはいけない
6. レベル毎に1モジュール1ファンクションを実現していなければならない
7. 制御の流れは、フラグ(プログラム内で制定された複合条件)ではなく、データそのものによって決定されなければならない

以下に、各項目の解説を簡単に行ってみよう。


1と4は全てを蔽う大原則である。これは、トップダウンの方がボトムアップより望ましいといったような意味では全くない。トップダウンでなければならないのである。
この点では、ボトムアップに若干の容認を与えているジャクソンの意見(構造的プログラム設計の原理2,6、JSD法14章非下降型のJSD)とは相入れな いものがある。ジャクソンがトップダウンでは解決出来ないとして挙げた例(図1参照)は、現実のプログラミングの中では、日常茶飯事のケースで、ファイル のアクセスやエラー処理、メッセージ出力などのプログラム全体で共通処理と位置付けられる処理は全てこういう形に帰結するであろう。


トップダウンでモジュールを分解するときに、上位で処理すべきだった条件を見落としてモジュール化してしまった場合も、このように同じ処理が末端に重複し て現れたりするが、そういう設計ミスがないのなら、ここで現れるPJ、PKなどのモジュールはプログラムの随所に現れる共通処理と考えることが出来、何ら トップダウンの設計方針を否定する要因とはならない。 また、図1もルールに従うならば図2のように表記されるべきである。
(以下抜粋文)


逆に、トップダウン設計中、1つのコンポネントを2つ以上のより高 いレベルのコンポネントの一部として取り扱おうとするなら、次のような構造をつくり出す
これは木ではない。PJはPD、PE、PFから到達しうるし、PEはPAあるいはPから到達しうる。PFはPBあるいはPから到達しうる。このようにある 特定の実行に対して、PJの文脈は、PJが呼ばれる前のプログラムによってとられる道によって決まる。この不確実性が、よく、難しさと、エラーのもとにな るのである。
(構造的プログラム設計の原理 2-6より抜粋)



Pというモジュールの1レベル下の処理を線を交差させずに表記重複しているモジュールは、実際のプログラムではPERFORMでCALLされるだけなので、コーディングが増えることもない。

ボトムアップの設計は、ある特定の結果を出すルートを作成するために他の部分が従属的になり、全体として偏った、バランスの悪い改修の効かないプログラムになりやすいので十分に警戒しなければならない。
トップダウンの考え方の指針としてデマルコは、J.ワインバーグの全体把握の法則(The Lump Law)というのを紹介している。
「何かを学びたいのなら、すべてを学ぼうとしてはならない」
私はチームメンバーにこう言う事にしている。
「明後日の事を全く考えずに明日の事だけを考えろ」

2と6は特に重要である。トップダウンでモジュールを分解する場合の基本的な考え方である。
モジュール化の基本要因は、データ構造とは特に関係のないAP上のファンクション(機能)である。
これは、上位のモジュールを分解して細分化された単位が、読むとか書くとかチェックとか検索というようなAP上のカテゴリになっていなくてはならないということだ。
即ち、上位のモジュールであればある程、仕様を表現する単位であるということだ。従って、そのモジュール自体はステップの大小、ロジックの複雑さに依存せず、また次元の違うモジュールが同一ネスト上に同居することもない。
このことは、ある仕様だけを極端に細分化し、ある仕様を同一レベル上で大まかなままで放置するというアンバランスな分割を防止する効果がある。また、第三者が仕様を追う時にもトップダウンで理解することが出来る。
1モジュール1ファンクションというのは、そのレベルで分割されたモジュール群がAP上の割り切れる単位群に分割されているということである。0.5ファンクションでも1.5ファンクションでもいけない。
APとして捉えた場合の機能として認知出来る単位でなければならないのである。

図3の構造図は、0.5ファンクションのモジュール化の例である。画面処理で、検索、追加、削除の処理区分があって、各処理の終わりでセットされた画面情報を最後の画面出力(D$SEND)命令で出力するというプログラムである。
この画面出力は、それぞれの検索、更新、削除の画面出力処理の中で発行されるファンクションの一部であったのだが、これを設計したSEは、おそらく D$SENDを一箇所で発行してプログラムのコーディングを減らしたか、または、画面に出力するという結果を意識したボトムアップの設計をしたのだろう。
この設計の良くないところは以下の2点である。

 [1] 改造しにくい(改造によって設計が変わる)
 [2] 上から読んだだけでは仕様が判りにくい

[1]の意味は、例えば、削除処理の後にはエラーでない場合に限り初期画面出力(D$SENDF)命令を使いたいというような改修が発生したりすると、画面出力命令を共通に使えると判断した旨味がなくなるどころか、削除で尚且つエラーでない条件で初期画面出力を行う例外コーディングを追加しなければならな い。即ち、各処理区分における画面出力形式、出力画面の変更が常にこのプログラム全体の構造を脅かすことになる。これは、ファンクションが中途半端に分解 されたことに原因がある。

[2]の意味は、例えば保守にまわったユーザが検索時の画面の表示を変更しようとする時に、検索処理はモジュールとして、他の更新、削除から完全に独立し ていないため(画面出力を共通に使っているため)、通常は検索処理の中だけを見て改修出来るのだが、更新、削除の内容も調べないと改修可能の判断が出来な い。これではトップダウンでもモジュール化した意味がない。モジュールの独立性が保たれていない設計である。

5は、厳密な規定ではなく、あくまで原則である。
ユーザの方も、あるモジュール以下の仕様はSPECではなく、直接プログラムの方を参照することが多いので、これはその時の状況によって変化すると考えてよい。

3は、GO TO文の基本的な肯定である。
今まで呪文のように言われ続けたように、GO TO文は本当に有害なのだろうか?1968年のダイクストラ教授のNATO会議以来、構造化プログラミングにとって、GO TO LESSは必要十分条件のように叫ばれているが、現実のプログラムでそんなことを行ったら、プログラムは入れ子のお化けになってしまうだろう。HIPOを GO TOなしで書き続けた人は良く判ると思う(正式のHIPO規約にGO TOはないが、ローカルには使う人が多い)下へ制御を飛ばしたり、SKIPしたりするたびにPERFORMが増えてゆくのだ。


クヌースの制限つきGO TO文の使用を認める意見や、ヨードンの「構造化手法によるソフトウェア開発」の中の構造化プログラミングの記述の中でも、GO TO文を使わないことの是非が詳細に論じられているので、ここでは結論だけを述べる(論理的な例証を必要とする方はそちらを精読されたい)。
プログラムの適度で健全な簡潔さを保つためにも下へのGO TO文は必要であり、制限を設けて(この場合はセクション内)使用すれば何ら害はない。GO TO LESS=構造化プログラミングという考えは、確かにセンセーションナルで面白いが(議論の題材として)、あまり現実的なアプローチとは言えないと、私は思う。

7は、フラグ処理の否定である。これこそ、出来れば完全になくしたいものである。制御の条件は、誰にでも分かる単純で冗長な記述で表現されるべきである。 IF A-FLG=1 よりも、IF XX-DATA>100 AND XX-STATUS=00 という冗長なコーディングを採用するということである。
フラグ処理は改修に弱い。なぜなら、制御条件が判定の場所に完全に揃っていないからである。これは、部分的な修正を行うときの足かせとなる。
1つのフラグなら特にこれらの問題はないが、フラグは往々にして複合化して使用されることが多く、修正すればする程、直しにくく、判りにくいプログラムになってゆく。冗長だと判っていても、データの内容そのもので判定していれば部分的に修正出来るので改修には強いし、第三者にも理解しやすい。
私の上司が口癖のように語っていた極意がある「データをして語らしめよ」。
やはり、シンプルというファクターは重要である。



■引用文献■
原著:Principles of Program Design (1975) Academic Press
著者:M.A.ジャクソン (Jackson, Michael A.)
訳者:鳥居 宏次
出版:日本コンピュータ協会 / 発売:科学技術出版社 (1980)