😎

人月の神話_16章_読書ノート

2024/12/16に公開

概要

16章の節立てに即して内容をまとめていく。
本章でブルックスはソフトウェア開発での困難を、それに固有の「本質的な困難」と本質的ではないが現時点では困難であるような「偶有的な困難」があるとして分析を始める。これまで行われてきたソフトウェア開発での困難の改善(高水準言語の登場、タイムシェアリング、プログラミング環境の統一)は主に偶有的な困難の減少に寄与しており、また現時点で期待されている解消方法もすべてが偶有的な困難の解消を目指しているとする。
本質的な困難への解決には
・なるべく自主制作せず購入すること
・プロトタイピングを利用して、迅速に要件を固めていくこと
・反復型開発で、ソフトウェアを育てていくこと
・優秀な設計者を個別に育てること
の4点を挙げている。

感想

ソフトウェア開発の本質的な困難への解決方法は現代でも適用可能な普遍性があると感じた。
一方で、本文で挙げられている偶有的な困難に関しては、現代においてはほとんど解消済みであると思う。
(詳細な感想は追記していく。)

ここから、16章の内容。

アブストラクト

ブルックスはソフトウェア開発には下記の「本質的作業」「偶有的作業」があると規定し、これまでは偶有的作業を効率化することによって生産性向上を実行してきたと主張する。

  • 本質的作業(essential task)
    • 抽象的なソフトウェア的な要素を組み合わせて、複雑な(設計上の)概念構造を作成すること
    • [原文]the complex conceptual structures that compose the abstract software entity
    • 要件定義、仕様策定、設計に対応する(私的補足)
  • 偶有的作業(accidential task)
    • 本質的作業の成果物を実際にプログラムし、実行可能な機械語へ変換すること
    • 実装に対応すると考えられる(私的補足)

本書で挙げられている過去の効率化の要因は以下である。これは現代でも当てはまるだろう。

  1. ハードウェアの制約
  2. 扱いにくいプログラミング言語
  3. 機械を使用する時間の不足

最終的なブルックスの提案は以下の4点である。

  1. 市場にある製品を利用し、自作が不要なものを作らないこと。
  2. 要件を確定させるための計画的な反復プロセスの一部として、迅速なプロトタイピングを活用すること。
  3. 実行、使用、テストしながら、機能を徐々に追加することで、ソフトウェアを有機的に成長させること。
  4. 次世代の優れた設計者を発掘し、育成すること。

現代的な視点から見れば、1の重要性は変わらないだろうし、2、3に対してはアジャイル開発という手法が生まれたことで応急処置的な対応ができるようになってきていると思う。問題は4だろう。自信の観測する限り、ソフトウェア産業全体としての教育の軽視が見られると思う。統計的な手法で正当性が示された教育方法ではなく、単なる経験に基づく教育、個別の会社でしか通じない方法での教育がなされているのが現状だろう。これを教育の軽視といわずになんといえようか。

イントロ

ブルックスは狼人間とソフトウェア開発を共通の構造があるという。狼人間は慣れ親しんだ人間が狼になってしまうという物語だが、他方でソフトウェア開発もある時までは計画通りに進んでいるようにみえるが、スケジュールの遅延・予算の膨張・バグだらけのプロダクトという怪物になってしまうという。これへの解決策を「銀の弾」と呼ぶ。
実際のところ、このような銀の弾は存在しないが、医療が徐々に進歩してきたような形でソフトウェアエンジニアリングも進歩するだろうと予言している。

難しい必要はあるのか?-本質的な困難

アリストテレスにならって、困難を「本質的なもの(ソフトウェアの性質に内在する困難)」と「偶有的なもの(本質的でない、今日のソフトウェア作成に付随する困難)」に分けて考え、さらに「ソフトウェア構築の難しい部分は、この概念構造の仕様化、設計、およびテストにあるのであり、それを表現し、その表現の忠実性をテストする作業にはない」と主張している。後者の作業は設計書の書き方、設計書の書き方、コーディングのことを指しているのだろう。
そのうえで、本質的な困難として次の4つを挙げている。

  1. 複雑性
  2. 同調性
  3. 可変性
  4. 不可視性

複雑性

  • どのパーツもすべて相異なる
    • PCのハードや、ビル、自動車には部品の重複がたくさんある
  • 大量の状態が存在する
    • PCのハードも多くの状態があるが、比べ物にならないぐらい多い

その結果、次のようなことが導かれる

  • 要素を追加するたびに異なる要素を追加することになるので、複雑性が増加しやすい
    • (実際は非線形に増加する(n要素があれば、n^2で増えるだろう))(私的)
  • 複雑すぎて全体の理解も、状態の列挙も不可能になる
    • 信頼性が低下する
    • 不可視性が高まる
  • 副作用なしに拡張ができず、新機能追加が困難になる

同調性

  • 人為的な複雑性へ対応する必要がある
    • インターフェースや、時代に適合しないといけない
  • 従わせやすいと思われているために、実際に従わなければならない

可変性

  • 常に変化の圧力にさらされている
    • 思考の産物であるため、変更コストが認識されにくい
    • 役立つと認識された製品には、元の設計限界を超えた要求がされがち
    • PCのハードが変更されても生き残るように変化しないといけない
    • 文化的な変化への対応も要求される
    • 自動車などのハードに比べて、変更頻度が著しく多い

ミドルウェアの発達によってハードの変更へは対応しやすくなったと思うが、それ以外の部分は全くもって改善されていないと思う。

不可視性

  • 本質的に空間的なものでないので、空間的な表現ができない

不可視性に関してはUMLなどによって改善されていると思われる。UMLは1994年に出現し、UML2.0が2004年に策定されている。原論文が出版されたのが1986年であり、時代的な制約を強く受けている。この時代にはIDEF0, IDEF1Xなどがあったはずだが、これは本文で批判されているデータフロー図などに当てはまるだろう。

偶有的な困難を解決したブレークスルー

  1. 高水準言語
    • 機械的な複雑さを取り除き、抽象的なプログラム構造にのみ集中できるようになった
    • 高水準言語の複雑さがますにつれて、その部分に時間がかかるようになってくる
  2. タイムシェアリング
    • CPUの割当て時間を細かく分割し、割り込み処理が可能なようにする技術のこと
    • 「大昔には個人用コンピュータがなく、大型コンピュータを共用しており他の利用者の処理を待つ必要があった。この技術によって(各プログラムの実行時間が伸びるものの)待ち時間が解消された。」
    • 現在では当然のようにPCのCPUやOSにも応用されており、明確に言及されることは少ない
    • コンパイル時間や実行時間の短縮などによって、思考の中断が防がれるようになった
    • 人間の認知限界にまで達したところで、恩恵が得られなくなる
  3. 統一されたプログラミング環境
    • UNIXやInterlispなどの統合開発環境が提供されるようになった
    • 統合ライブラリの提供や、ファイルフォーマットが定まり、プログラムの相互運用性が高まった

銀の弾を期待して

  1. Adaなどの高水準言語の進歩
  2. オブジェクト指向プログラミング
  3. 人工知能
  4. エキスパートシステム
  5. 「自動」プログラミング
    • 問題の仕様を記述することで問題を解決するプログラムを自動生成する技術のこと
    • バルナスによる定義「要するに、自動プログラミングとは常に、その時点で利用可能なプログラミング言語よりも高水準な言語を用いたプログラミングの婉曲表現に過ぎない。」
    • バルナスの定義に依拠すれば、問題の仕様ではなく、解決方法の仕様を明確にしなければならない
    • 例外もあり、それは以下3点をみたすようなもの
      • 問題が比較的少数のパラメーターで簡潔に特徴付けられる
      • 解決策のライブラリとして、多くの既知の解法が存在する
      • パラメーターに基づいて解法を選択する明確な規則が広範囲に分析されている
  6. ビジュアルプログラミング
    • フローチャートなどではプログラムを生成するには貧弱すぎる(不十分)
    • 表示画面に限界があり、思考の広がりに対して不十分
    • 基本的にソフトウェアの視覚化自体が困難なものである
  7. プログラム検証
    • プログラムの検証(テスト)自体に時間がかかる
    • 検証(テスト)が完全にできるようになっても、仕様書とプログラムの整合性のチェックのみで、仕様書自体の完全性を担保してくれるものにはなりえない
  8. 環境とツール
    • ここで課題とされていることは、現在ではVSCodeなどのIDEや、GitHubなどで完全に解消されている
  9. ワークステーション
    • PCのパワーが強くなれば、思考に使える時間が十分に確保できるだろう

概念的な本質への有望なアプローチ

開発工程での偶有的な事項に関しては、下の方程式によって制約づけられている。

総作業時間 = {(各作業の頻度) × (各作業に書かかる時間)}

しかし、本質的な事項である概念構造を作成する部分は別の手法を考えないといけない。
現在期待できそうな手段は以下の4つだ。

  1. 購入VS.自主制作
    • 市場にあるソフトウェアはゼロから作るよりも安いし、すぐ使え、メンテナンスもされる
    • ハード/ソフトのコスト費がハードのほうが多いときは、大金を払うことができる企業しかシステムを導入できず、カスタム化させる余裕もあった
    • 現在では、大きなコストもかけずにデフォルトのシステムの導入ができるので、むしろシステムに業務を合わせている
  2. 要件の洗練化と迅速なプロトタイピング
    • 顧客とエンジニアが一緒に働いても十分な要件定義をすることは不可能
    • プロトタイピングという方法によって解決可能かも
  3. 反復型開発-ソフトウェアを「作る」のではなく「育てる
    • 当初は建築との類比で語ることで視野が広がった
    • ソフトウェアシステムは複雑すぎて、建築のたとえが有用性を失った
    • まずはスタブを動かすだけのプログラムから肉付けをしていくことで開発するのが有用
  4. 偉大な設計者を育てる
    • 良い」設計は教えることができ、教育組織も設立されている
    • 「偉大な」設計は標準的な教育によって生むことはできない
    • サリエリ(良い設計者)とモーツァルト(偉大な設計者)のような差がある
    • 偉大な設計による製品は以下
      • Unix、APL、Pascal、Modula、Smalltalk、Fortran
    • そうやって育てるか?
      • 優れた設計者を発見する
      • キャリアメンターを配置し、キャリアファイルを作っておく
      • キャリア開発計画の考案、維持を行う
      • 育成中の設計者同士が刺激し合えるような機会を作る

Discussion