(注記:これらの章における「本質的」といった言葉の用法について、17章の「Accident」の項で著者は補足をしている。著者は実装作業を本質的でない仕事に分類しているが、実装作業を軽視しているわけではない。開発の難しさを2種類に分けて考えたということが要点である。)
- データとその関係性、アルゴリズム、及び、機能(functions)の呼び出しという相互に影響を与える概念で構成される複雑な構造を創り出すことがソフトウェア開発において本質的な仕事である。メモリサイズや計算速度といった様々な制約を満たしながらプログラミング言語を用いてその構造を実装する作業は本質的な仕事ではない。
- ソフトウェア開発で難しい点は、概念的レベルの構造に対する仕様、設計、及び、テストであり、実装作業や実装が忠実に行われているかのテストではないと、著者は信じている。もしこれが正しいならば、ソフトウェア開発はいつまで経っても難しいままであり、特効薬は根本的に存在しない。
- 高級言語、タイムシェアリング、プログラミング環境によって本質的でない仕事を減らすことには成功してきた。
- 残っている仕事のほとんどが本質的な仕事であるならば、本質的でない仕事を例え完全に無くしたとしても、大幅な改善にはならない。
- 単独で大幅な改善をもたらす特効薬のようなものは見当たらないが、複数の革新を地道に積み上げていくことで大幅な改善を達成できるはずである。
ソフトウェアの本質的な難しさ
複雑さ
- ソフトウェアは本質的に複雑である。
- 自動車や建築物にあるような同じ部分の繰り返しがない。なぜなら、同じ処理は1つのサブルーチンにまとめられるからだ。
- 状態数(numbers of state)が多い。
- ソフトウェアにおけるスケールアップは、比例させて単純に大きさを何倍かにすることではなく、要素の数を増やすことだ。多くの場合、それらの要素は比例よりも複雑な形で相互影響するため、ソフトウェア全体は規模に比例する以上に複雑になる。
- この複雑さが開発もマネジメントも難しくしている。
- 複雑さ故に概要を理解するのも難しい。ソフトウェアの説明から複雑さを除こうとするとたいてい本質的な部分まで除いてしまうことなる。
- この複雑さは学習と理解のための莫大な負担を生む。そして、その負担は人員交代を大惨事にしてしまう。
周りに合わせることを要求されること
- 多くの場合、既存のややこしい仕組みやインターフェイスに従ってソフトウェアを作る必要がある。
- その既存のもののややこしさの大半は、物理法則のようなものではなく、気まぐれで作られた何の道理もないものである。そして、そのややこしさは様々な人々によって作られ異なっているのだ。
- ソフトウェアの方が従わなくてはならない理由
- 最も後から登場したから
- 最も従わせやすいと思われているから
- いかなるケースでも、多くのややこしさは他のインターフェイスに従うことから発生している。よって、この多くのややこしさは、ソフトウェアを単独で再設計したところでどうにもならない。
頻繁な変更
- 顧客に渡った製品に手を加えることが最も多いのはソフトウェアである。建物・自動車・コンピュータハードウェアのどれよりも頻繁に変更が行われる。
- 変更が多い理由の一部
- 機能という最も変更を要求されやすいものをシステムの中で体現するのはソフトウェアである。
- ソフトウェアは他の物と比べて変化させやすい。建物も実際に変更されるが、変更のコストが高いことを皆分かっており、それが気まぐれな変更を防いでいるのだ。
- 成功したソフトウェアは変更される。
- 機能拡張が要望される。
- その長い寿命の間にハードウェアが変化していく。
目に見えない
- ソフトウェアは目に見えないし、視覚化することも出来ない。
- ソフトウェアの構造を制約し単純化する方向には進んでいるが、本質的に視覚化不能なままである。その構造全体を1枚(1種類)の図で表すことはできない。また、その構造はたいてい平面的でも階層的でもない。(図にするのに適したそういう性質を持った構造になっていない。)
本質的な難しさへの対策
既製品のソフトウェアを買う。
- どんなソフトウェア製品でも、それを一から作るよりは買う方が安い。しかも、即座に手に入る。さらに、ドキュメントや保守が優れている場合も多い。
- 根底にあるのは、 n 人のユーザーで同じソフトを使えばユーザーあたりの開発コストは 1/n になることである。別の見方をすれば、n の数のコピーが利用されるならば、開発の生産性も n 倍になるということである。
パッケージソフトを1つのコンポーネントとして利用する。
(以下、第19章の「Buy and Build – Shrink-Wrapped Packages As Components」より)
- ソフトウェアの生産性を根本的に向上させるには、より高いレベルでモジュールやオブジェクトを組み合わせて作るしかない。
- 既存のパッケージソフトを1つのコンポーネントとして他と組み合わせ、より機能が多くよりカスタマイズされたシステムを作るやり方は方向性として有望だ。
- ただし、1つのパッケージソフトを中心としたカスタマイズや拡張では間に合わず、複数のパッケージソフトを連携させる必要がある場合には、それぞれのパッケージソフトが連携に適したインターフェイスを持っていることが必要となる。
ラピッドプロトタイピングを用いて仕様の改良を繰り返し行う。
- 何をつくるべきか、つまり、顧客の要求が何なのかを明らかにすることは開発で最も難しい部分だ。
- 実際にソフトを作って顧客が実際に試すことを1回もしないうちに、完璧な仕様を作ることは不可能だ。
- よって、プロトタイプを作り、顧客に試してもらって、仕様を繰り返し直していくことは重要である。ここでいうプロトタイプは、重要なインターフェイスと基本機能だけは動いて基本的な作業だけはできるソフトウェアである。
- このための手法とツール、つまり、プロトタイプを作って仕様を直していくサイクルを回すための手法とツールは、本質的な難しさへの対策として最も有望なものの1つである。
育てるように少しずつソフトウェアを作っていく。
- ソフトウェアを建築物にたとえて、事前に正確に設計して欠陥無く作れると考えるのは止めよう。むしろ生き物を育てることのようにソフトウェア開発を考えよう。
- まずダミーを呼び出すだけだが動きはするプログラムから始めて、そこに肉付けをする形でソフトウェアを作っていこう。
- このアプローチを取ることで、トップダウンで設計することやプロトタイプを作成することにもなる。また、常に動くシステムが手元にあることになる。そして、動くシステムは開発者にやる気を出させる。
優れた設計者を育成する。
- ソフトウェアの設計において、ダメな設計と良い設計の違いは設計手法かも知れないが、良い設計と優れた設計の違いは設計者が優れているかどうかである。
- 設計者の違いの影響は小さくない。平均的な設計者と優れた設計者では10倍近い差がある。歴史的にも、Unixのような胸をわくわくさせるようなソフトウェアの多くは卓越した設計者が1人か少数で設計したものである。
- 優れたマネージャーも足りないが、優れた設計者はもっと足りない。優れたマネージャーを見つけたり育てたりするのと同じく、優れた設計者を見つけ育てる努力をするべきであり、組織はそのための仕組みを用意するべきである。(そのための具体的な著者の提言は「Great designer.」の項を参照のこと。)
17章で触れられているその他の対策
- p. 210 後ろから2段落目:再利用と交換とが可能なコンポーネントによるアプローチ。
- p. 212 2段落目の列挙:階層化されたモジュールやオブジェクトによってソフトウェアを作っていく。
- pp. 222-225 ソフトウェアの再利用は対策になり得る。数学用のソフトのように、専門用語により機能の特定が容易で、かつ、作るのが難しいソフトは、新しく作るよりも既存のコンポーネントを探す方がコストが低いことが明白であり、実際再利用が行われている。しかしながら、そのような再利用に向いた分野は限られている。そうでない分野では、再利用可能なソフトウェアコンポーネントを作ることがそもそも難しい。再利用のためには、どの部分に汎用性があるかを適切に見極め、さらに良い設計と素晴らしいドキュメントが必要である。当然、再利用しないソフトに比べ開発コストは上昇する。作る難しさだけでなく、さらに、再利用可能コンポーネントを使う難しさもある。プログラミング言語の機能を組み合わせて実現されたコンポーネントは、言語の機能よりも当然複雑になる。よって、どのコンポーネントをどのように使えばどのようなことができるかを利用者は学習する必要がある。したがって、この学習を容易にする方法の研究が必要である。
この要約作成者の個人的メモ
- p. 186 最後の文:高級言語の改良もある程度を越えると、高級言語の複雑な構成要素をめったに使わない人にとっては負担となる。
- p. 190 人工知能には期待していない。なぜなら、異なる分野で共通に利用できる技術が少なく、それぞれの分野・問題に応じた作業が大半であるからだ。また、人工知能であることがプログラミングの実践の中に大きな違いを生んでいるようにも見えない。
- p. 193 微分方程式の解き方のような問題、つまり、いくつかのパラメータで記述され、解法が十分研究されているような問題においては、ソースコード生成システムは強力だ。
- p. 194 グラフィカルプログラミングまたはビジュアルプログラミングからは素晴らしい成果は出てこないだろう。なぜなら、前述の通りソフトウェアは視覚化するのが難しいからだ。
- p. 195 プログラム検証(verification)は余りに労力がかかるため、内容のあるプログラムはほんのわずかしか検証されてこなかった。しかも、難しいのは適切な仕様を探し出すことであるのに、プログラム検証が出来ることはプログラムが仕様に合っているかの確認だけである。よって、検証技術は特効薬にはならないだろう。
- p. 219 電動ドリルや電動ノコギリのようにカスタマイズできて様々に使えることはパッケージソフトにとって重要である。なぜなら、それによってエンドユーザーが自分のしたいことがパッケージソフトの組み合わせで出来るかもしれないと思うようになり、パッケージソフトを使うことに抵抗感がなくなるからである。多くのケースで、カスタムソフトの方が良いとパッケージソフトに抵抗するのは、ソフトウェア関係者ではなくエンドユーザーである。
オブジェクト指向プログラミングについて
- p. 189 最後の段落:オブジェクト指向プログラミングは、設計の表現の難しさという本質的でない難しさしか取り除けない。
- p. 221 James Cogginsの意見より:小さなカプセル化は小さな利益しかもたらさないので、粒度が大きいクラスが重要である。そして、その大きなクラスの設計には、顧客(ユーザー)の知見が重要であり、そのため、顧客の協力が重要である。
- p. 221 David Parnasの意見より:オブジェクト指向はソフトウェア設計(design)の1種類として教えられるべきだったのに、特定のツールを使うことがオブジェクト指向だと教えられてしまった。その結果、人々は、オブジェクト指向言語を使ってまずい設計を行った。
- p. 273 (第19章より)再利用できるように設計されテストされたクラスライブラリは、第1章で述べたプログラム製品に類するものであるという事実について、多くの人々は無視することを選んだ。汎用的で、頑健で、テストされ、ドキュメントも付いた製品相当の品質を持つクラスを作るための初期コストを支払わないまま、クラスのかなりの再利用を無駄に願う人々もいる。
(第1章で著者は、単なるプログラムに比べプログラム製品は少なくとも3倍のコストがかかるとしている。)
他の章はこちらから:
「人月の神話」の要点
人月の神話の要点・ポイントをまとめています。原著に基づき、人月の神話の要点・ポイントを主に箇条書き形式でご紹介しています。