A Philosophy of Software Design ch2 The Nature of Complexity

APoSDソフトウェア設計勉強メモ

出典: 


The Nature of Complexity

  • 敵はch1にて論じたとおり「複雑性」
  • 敵を知ること

    • 複雑性って何?
    • システムの、本来不要な複雑性を、どのようにして見極める?
    • システムの複雑性の原因?
  • 複雑性を認識することは重要なスキル

    • 設計上の選択肢が複数ある場合、よいものを選べる
    • 複雑だと感じたら、別の設計を試して再度評価する
    • そのうち、単純/複雑な設計につながるテクニックがわかってくる
  • 本章は以降の章の前提となる内容

Complexity defined

  • 本書における複雑性の定義

ソフトウェアシステムの構造に関連して、理解や変更を難しくするもの

    • あるコード片がどう動くか理解困難
    • 小さな改良すら労力甚大
    • システムを改良するためにどこを触ればいいか定かでない
    • あるバグを修正するさい、別のバグが埋め込まれる
  • costとbenefitでもとらえられる

    • 複雑: 小さな改良に大きな労力
    • 単純: 小さな労力で大きな改良
  • システムの規模や機能とは必ずしも関係ない

    • 大きくて作り込まれたシステムでも、開発者が仕事しやすければ複雑ではない
    • 小さなシステムでも複雑なものはある

      • 【所感】前職
  • 複雑性を表す数式(定性的)
C = Sum(c_pt_p)
  • 数式の意味

    • where…

      • p: プログラムの、ある部分(part)
      • c_p: pの複雑性
      • t_p: pをプログラマが触る時間
    • t_pが小さくてもCへの寄与を小さくできることが重要
    • ほとんど触られない部分に複雑性を隔離できれば、複雑性を完全に排せたのとほぼ同じ効果が得られる
  • 複雑性は、コードを書いた本人よりも読む人のほうが気づきやすい

    • 自分にとって単純でも、他の人にとって複雑ならそれは複雑なのである
    • 複雑性を指摘されたら、意見の隔たりから何かを学ぶチャンス
    • 自分のみならず、他の人にとっても仕事をしやすいコードを

Symptoms of complexity

  • 複雑性の3要素

    • 変更の増幅

      • 何箇所直すねん!?ってやつ
      • 共通化で解消

        • 【補】共通化の際にはコンテキストに留意しよう
    • 認知の負荷

      • 例: Cの「mallocしたら忘れずにfreeする」など

        • 【補】C++のRAIIは認知の負荷の低い例かと

          • コンストラクタにリソース獲得、デストラクタにリソース解放を紐付ける
          • コールスタックをpopしたら自動的にリソースが開放される
          • 例外が投げられてstack unwindingされてもリソース開放される
          • プログラマがリソース解放を意識しなくていい
      • コードは短ければよい、というものではない理由

        • 数行しかないが、その数行が非常に理解困難なケースなど
    • 分からないことが分からない

      • どこを触ればいいかわからないやつ
  • 後のものほど悪い

    • 分からないことが分からない

      • どのコードに変更を加えればよいかわからない

        • cf. 「変更の増幅」は鬱陶しいが、少なくともどこを触れば良いかはわかる
        • cf. 「認知の負荷」も、変更コストこそ高くつくが、変更自体は正しそう
      • 変更すべき内容を特定するために、コードを全行読むほかない
  • 良い設計の、最も重要な目的のひとつは、システムを明瞭にすること

    • 認知の負荷/分からないことが分からないの逆
    • どこを触ればよいか、すぐに当たりをつけられる

Causes of complexity

  • 複雑性の原因

    • 依存
    • 不明瞭
  • 依存による複雑性

    • 複雑さをもたらす依存の例

      • 全ページの背景色に#FF0000って書いてある
      • すべてのページ間に依存がある
    • 改善例

      • 全ページの背景色はbgColorを参照するようにする
      • bgColor = #FF0000
      • 依存が明確

        • 各ページがbgColorに依存していることが明確
        • bgColor変数の利用箇所は容易に検索・特定できる
  • 不明瞭による複雑性

    • 例: 意味の薄い変数名

      • time
    • 例2: 数量に単位がない
    • 「依存による複雑性」にも関連する

      • 依存があるかどうか定かでないケース

        • 【補】同じ#FF0000を見つけたとして、本質的に同じ色なのかたまたま一致しているだけなのかわからない
    • 原因

      • ドキュメンテーションが不適切
      • 設計の問題

        • 重点的なドキュメンテーションが必要だというのは、設計がまずい危険信号
  • 複雑性の3要素との関連
変更の増幅 認知の負荷 分からないことが分からない
依存 o o
不明瞭 o o

o = causes

Complexity is incremental

  • 小さな依存や不明瞭が積み重なって、手に負えない複雑性になる
  • 「ちょっとくらい複雑性を持ち込んでもかまへんか…」
  • 開発者全員がこういった姿勢で毎回の変更を行うと、システムは急速に複雑になってしまう
  • ひとたび蓄積した複雑性を取り除くのは難しい

    • 依存や不明瞭を1つ取り去ったところで焼け石に水
  • 複雑性の増大を遅くするために、3章の”zero tolerance”の考えを導入せよ

Conclusion

  • 複雑性とは、依存と不明瞭の積み重なり
  • 複雑性は、変更の増幅、認知の負荷、分からないことが分からないを引き起こす
  • 結果、新機能開発のために、コードに多くの変更を加えなければならなくなる
  • 変更のための情報(どこをどう触ればよいか)を得るために多くの時間が必要になる

    • 最悪、見つからないことも
  • 複雑なコードベースは変更が困難で危険を伴う