/note/tech

システムを作る人がまず理解すべきシステム思考の基礎

要約:

■ 1. システム思考の本質と必要性

  • 定義: 物事を個別に捉えるのではなく、全体の関係性や相互作用を理解する考え方
  • 普遍的スキル: どんな分野でも応用できる基本的な教養であり、システムを構築する立場の人には特に重要
  • 実践としての性質: システム思考は知識ではなく実践であり、テニスと同様に本を読むだけでは身につかず日々の開発の中で体得していく必要がある
  • プラモデルと生態系: プラモデルは説明書通りに組み立てれば完成形が予測できるが、実際のソフトウェアシステムは生態系に近く、すべてが相互に影響し合い予測困難な振る舞いを見せる
  • 現代開発の特徴: マイクロサービス、API連携、非同期処理、分散システムでは個々の部品の品質だけでなく相互作用が全体の振る舞いを決める

■ 2. 今日から始められる小さな習慣

  • 違和感に気づく: バグが発生したらすぐに修正せず立ち止まって「このバグ、前にも似たようなことがあったな」という違和感に気づく
  • 多角的な問いかけ: 技術的な問題か、仕様の理解が曖昧だったのか、チームのコミュニケーションに課題があったのかなど多面的な視点で問いかける
  • 図を描く習慣: コードを変更する前に紙やホワイトボードに簡単な図を描き、どのモジュール・チーム・ユーザー機能に影響するかを考える(最初は5分で構わない)
  • PRの説明文の充実: 「何を」変更したかだけでなく「なぜ」その実装を選んだのか、他にどんな選択肢があったのか、何を考慮したのかを書く(3ヶ月後の自分のため)
  • 特別なツール不要: これらは特別なツールも会議も不要で、明日のコーディングから始められる

■ 3. 線形思考の限界

  • 線形思考の特徴: 予測可能で、合理的で、再現可能で、手続き的で、二元論的で、トップダウンで、制御に関心を持つ思考
  • 因果関係の単純化: 「if this, then that」の因果関係に支配され、ソフトウェアシステムが意図通りに正確に動作することを期待する
  • 非線形性の現実: APIの応答速度改善が別のサービスに負荷を集中させる、キャッシュ導入がデータ整合性問題を頻発させるなど、単純な原因と結果の連鎖ではない
  • 予測不可能性: 部分間の関係が何が起こるかに影響を与え、一つの変更が思わぬ波及効果を生み出し、事前に完全に予測することはできない
  • システム思考への第一歩: 非線形性を理解し、それと共に働く方法を学ぶこと

■ 4. システムの定義

  • 包括的な定義: 共有された目的に奉仕するために相互作用し相互依存する、相互関連したハードウェア・ソフトウェア・人々・組織・その他の要素のグループ
  • 全体の構成: 開発しているWebアプリケーション、それを使うユーザー、運用チーム、ビジネス要求のすべてが一つのシステムを構成している
  • システム思考の定義: 一緒に実践すると非線形思考スキルを向上させる、基礎的な思考実践のシステム

■ 5. 生産と理解の非対称性(AIコード生成の事例)

  • AIによる開発速度の向上: 数分で数百行のコードが生成されるが、修正しようとした時に予想以上に時間がかかる
  • 非線形性の典型例: コードを安全に変更するにはまず理解が必要で、コードが流入する速度と人間が理解する速度の間に決定的な非対称性がある
  • 氷山モデルでの分析:
    • 出来事:「AIで開発が速くなった」
    • パターン:「変更に時間がかかるようになった」
    • 構造:「生成速度と理解速度の不均衡」
    • メンタルモデル:「速さこそが価値」「生産量で生産性を測る」
  • レバレッジポイント:
    • メンタルモデルの変革:「速く書けることが価値」から「理解できることが価値」へ
    • フィードバックループの再設計:AIが生成したコードに「なぜこのアプローチを選んだか」を必ず追記、コードレビューで「理解できるか」をチェック
    • 適切な制約:プロトタイピングではAIを積極的に使い、本実装では人間が設計してから使う

■ 6. 概念的完全性

  • フレッド・ブルックスの言葉: 「概念的完全性はシステム設計において最も重要な考慮事項である」
  • 定義: システム全体が一つの統一された設計思想で貫かれている状態
  • Unixの例: 「すべてはファイル」という設計思想により、cat、grep、sedといったシンプルなコマンドを組み合わせて複雑な処理ができる
  • 欠如した状態: あるAPIはRESTful、別はRPC風、あるデータはJSON、別はXML、エラーハンドリングも部分によって異なるなど、多くの良いアイデアが調整されずにバラバラに実装されている
  • 保つための実践: 「このシステムの核となる考え方は何か」を常に問い続け、新機能が既存の設計思想と一致しているか確認する
  • 効果: システムを理解しやすく、保守しやすく、拡張しやすくする

■ 7. 関係性が効果を生む

  • ドネラ・メドウズの定義: 部分が一緒になって、各部分が単独で生み出す効果とは異なる効果を生み出すこと
  • マイクロサービスの例: 個々のサービスは完璧に動作していても、通信パターン・データの流れ・障害の伝播の仕方によってシステム全体の振る舞いは大きく変わる
  • ECサイトの具体例: セール時に検索サービスへのアクセスが急増すると、その負荷がカートサービスに波及し最終的に決済が遅延する
  • 人も含むシステム: コードだけでなく、それを書く開発者、使うユーザー、運用するチーム、すべてがシステムの一部
  • コンウェイの法則: システムを設計する組織は、その組織のコミュニケーション構造をコピーした設計を生み出す
  • 技術と組織の不可分性: 技術的負債を解消するだけでは不十分で、なぜその負債が生まれたかという組織的・文化的な要因も同時に扱う必要がある

■ 8. 反直感性

  • 定義: 直感的に正しいと思える解決策が、実際には問題を悪化させる現象
  • ブルックスの法則: 遅れているソフトウェアプロジェクトに人員を追加すると、さらに遅れる
  • 理由: 新メンバーの教育コスト、コミュニケーションパスの増加(n人なら n(n-1)/2 の組み合わせ)、意思決定の複雑化などの隠れたコストが追加された人員の生産性を上回る
  • 日本の開発現場の例:
    • 品質が悪いからテストを増やす→無意味なテストが増えるだけで本質的な品質は改善せず、テストのメンテナンスコストが増大
    • ドキュメントが足りないから全てを文書化する→誰も読まない膨大なドキュメントが生まれ、更新されずに陳腐化
  • 真の解決策: 品質が悪いなら設計を見直す、ドキュメントが足りないならコードを自己文書化する、プロジェクトが遅れているならスコープを削減する
  • 重要な視点: 「この解決策を実施したら、他の部分にどんな影響があるか」を考え、真の解決策は問題とは違う場所にあることが多い

■ 9. 氷山モデル

  • 4つの層:
    • 出来事(Events):目に見える現象(例:本番環境でNullPointerExceptionが発生)
    • パターン(Patterns):繰り返される傾向(例:毎週金曜日のリリース後に似たようなエラーが発生)
    • 構造(Structure):パターンを生む仕組み(例:金曜日は全員がリリースを急ぐためレビューが形骸化)
    • メンタルモデル(Mental Models):根底にある考え方(例:週末前には必ずリリースしなければならない)
  • 表面的対応の限界: 出来事のレベルで対応(バグを修正して終わり)するだけでは同じ問題が繰り返される
  • 本当の解決: より深い層にアプローチすることで、構造やメンタルモデルを変える
  • 具体的な使い方: 違和感からパターンを見つけ、なぜパターンが繰り返されるのかを考えて構造を見出し、「私たちは何を当たり前だと思っているのか」と問うことでメンタルモデルに気づく
  • 階層的分析: この階層的な分析がシステム思考の核心

■ 10. 実践への統合

  • 理論ではなく道具: バグに遭遇したとき氷山モデルを思い出す、新機能を設計するとき関係性を考える、直感的な解決策を思いついたとき反直感性を疑う
  • 生態系としての設計: プラモデルのように部品を組み立てるのではなく、生態系のように全体の相互作用を設計する
  • 調和と進化: 完全な制御を求めるのではなく、システムと調和し共に進化していく
  • 準備完了: 基礎を理解したら、自己認識、問いの立て方、フィードバックループの設計、パターンの見つけ方など明日から使える実践的な方法に進む