ハクソク

世界を動かす技術を、日本語で。

ソフトウェア工学の法則

概要

ソフトウェアエンジニアリングの法則は、システム設計・チーム運営・意思決定に影響を与える原則やパターンの集まり。
主な法則には、組織構造、計画、品質、スケール、設計、意思決定など幅広い分野が含まれる。
各法則は、現場での実践やプロジェクト運営に重要な示唆を提供。
代表的な法則をカテゴリごとに日本語で要約。
実践的な知識としてエンジニアやマネージャーに有用。

ソフトウェアエンジニアリングの主な法則と原則

  • Conway's Law
    • 組織のコミュニケーション構造が、その組織が設計するシステムに反映される傾向
  • Premature Optimization (Knuth's Optimization Principle)
    • 時期尚早な最適化は多くの場合、害となる
  • Hyrum's Law
    • API利用者が十分に多い場合、すべての観測可能な挙動に依存するユーザーが現れる
  • Boy Scout Rule
    • コードを改善してからコミットする習慣
  • YAGNI (You Aren't Gonna Need It)
    • 必要になるまで機能追加を控える原則
  • Brooks's Law
    • 遅延したプロジェクトに人員を増やすと、さらに遅延する
  • Gall's Law
    • 複雑なシステムは、動作する単純なシステムから進化する
  • Law of Leaky Abstractions
    • すべての非自明な抽象化には、どこかで漏れが生じる
  • Tesler's Law (Conservation of Complexity)
    • 複雑さは消せず、移動しかできないという原則
  • CAP Theorem
    • 分散システムでは一貫性・可用性・分断耐性のうち2つしか同時に満たせない
  • Second-System Effect
    • 小さな成功システムの後継は過剰設計になりやすい
  • Fallacies of Distributed Computing
    • 分散システム設計者がよく陥る8つの誤った前提
  • Law of Unintended Consequences
    • 複雑なシステムの変更には予期せぬ結果がつきもの
  • Zawinski's Law
    • すべてのプログラムは最終的にメールを読む機能を持つよう拡張される傾向
  • Dunbar's Number
    • 一人が維持できる安定した人間関係の上限は約150人
  • Ringelmann Effect
    • グループが大きくなるほど個人の生産性は低下
  • Price's Law
    • √n人が全体の50%の仕事をする
  • Putt's Law
    • 技術を理解する人は管理しない、管理する人は技術を理解しない
  • Peter Principle
    • 階層組織では無能レベルまで昇進する
  • Bus Factor
    • 離脱でプロジェクトが危機に陥る最小人数
  • Dilbert Principle
    • 無能な社員ほど管理職に昇進しやすい
  • Parkinson's Law
    • 仕事は与えられた時間をすべて使って膨張する
  • Ninety-Ninety Rule
    • 最初の90%の開発で90%の時間、残り10%でさらに90%の時間が必要
  • Hofstadter's Law
    • 常に予想より時間がかかる
  • Goodhart's Law
    • 指標が目標になると、その指標の有効性が失われる
  • Gilb's Law
    • 測定できるものは、測定しないより良い
  • Murphy's Law / Sod's Law
    • 失敗する可能性があるものは必ず失敗する
  • Postel's Law
    • 自分は厳格に、他者には寛容に対応
  • Broken Windows Theory
    • 小さな問題も放置せず修正する
  • Technical Debt
    • 開発速度を遅くする全ての負債
  • Linus's Law
    • 十分な人数が見れば、バグは浅い
  • Kernighan's Law
    • デバッグはコーディングの2倍難しい
  • Testing Pyramid
    • 単体テストが多く、統合テストは中程度、UIテストは少数が理想
  • Pesticide Paradox
    • 同じテストの繰り返しは効果が薄れる
  • Lehman's Laws of Software Evolution
    • 現実を反映したソフトウェアは進化し続けるが、限界もある
  • Sturgeon's Law
    • 全体の90%は駄作
  • Amdahl's Law
    • 並列化による高速化は直列部分で制限される
  • Gustafson's Law
    • 問題サイズを大きくすれば並列処理の効果は増す
  • Metcalfe's Law
    • ネットワークの価値はユーザー数の2乗に比例
  • DRY (Don't Repeat Yourself)
    • 知識は一意に管理
  • KISS (Keep It Simple, Stupid)
    • 設計はできるだけシンプルに
  • SOLID Principles
    • 保守性・拡張性を高める5つの設計原則
  • Law of Demeter
    • 直接の友達(オブジェクト)だけとやり取り
  • Principle of Least Astonishment
    • 驚きが最小となる挙動を目指す
  • Dunning-Kruger Effect
    • 知識が浅いほど自信過剰
  • Hanlon's Razor
    • 悪意よりも愚かさや不注意で説明できる
  • Occam's Razor
    • 最も単純な説明が正しいことが多い
  • Sunk Cost Fallacy
    • 投資した分に執着し、撤退できなくなる心理
  • The Map Is Not the Territory
    • モデルや図は現実そのものではない
  • Confirmation Bias
    • 自分の信念を補強する情報を重視する傾向
  • The Hype Cycle & Amara's Law
    • 短期的な効果を過大評価し、長期的な影響を過小評価
  • The Lindy Effect
    • 長く使われているものほど今後も続く可能性が高い
  • First Principles Thinking
    • 複雑な問題を基本要素まで分解し再構築
  • Inversion
    • 逆の結果から問題解決を考える手法
  • Pareto Principle (80/20 Rule)
    • 80%の問題は20%の原因から生じる
  • Cunningham's Law
    • ネットで正しい答えを得る最善策は、間違った答えを投稿すること

上記はソフトウェアエンジニアリング分野で広く知られる法則や原則の要約。
実務での意思決定・設計・チーム運営・品質管理など、多岐にわたる場面で活用可能。

Hackerたちの意見

ボイドの反復法則は見たことないな。「複雑さを分析する際、迅速な反復は深い分析よりもほぼ常に良い結果を生む。」ボイドはOODAループを発明したんだよね。
それ、めっちゃいいね!もっと多くの人に理解してほしいな。経営者やビジネス系の人たちは、いつも最初に計画を立てたがるみたい。でも、ある程度は理解できるけど、ソフトウェアを作るにはあまり効果的じゃないって学んだよね。特に最初の段階では、すべての問題を事前に考えるのは無理だし。問題を解決するために柔軟なアーキテクチャにリファクタリングする方が、学びながら適応できない硬直したアーキテクチャを設計するよりもずっといいよ。
これを読んでいる人には、ソフトウェアエンジニアリングは実際にやっている人から学ぶのが一番だよ。実際にやっている人が書いた教科書を読んでみて。
おすすめはある?「データ集約型アプリケーションの設計(DDIA)」を読んだんだけど、すごく良かったよ。でも、マーチン・クレプマンが書いたもので、彼はアカデミックな人だよね。PEPを読むのもいいよ。機能Xについて「なんで気にするべきか」を理解するのに役立つから。
これらの「法則」は内部矛盾が多すぎて、こうやって全部並べると、自分が正当化したいことを正当化するための法則を選ぶことができる。難しいのは、どの法則をいつ破るべきか、そしてその理由を知ることだね。
これは機械学習エンジニアリングにおいても二重に当てはまるよ。避けるべき手法を知ることは、うまくいくかもしれない手法を知ることと同じくらい重要なんだ。特に、データサイエンスの技術は、重要なチームや組織の決定を下すために必要で、データ駆動型の機械学習だけでなく、少し統計を理解しておくことも大事だよ。
DRYはこの例の代表だね。特にコンピュータサイエンスの人たち(私はEEEのバックグラウンドだけど、うちにも問題はあるけどこれはその一つじゃない)を見てると、似たようなことをする二つの関数を書くのを避けるために、概念的な複雑さを宇宙の彼方に飛ばしてしまうことがあるよ。
ポステルの法則とハイラムの法則は典型的な例だね。ポステルは受け入れることに寛容であれと言ってるけど、ハイラムの法則はAPIの観察可能な全ての挙動は最終的に誰かに依存されることになるって言ってる。だから、間違った入力を受け入れて静かに修正することに甘いと、その甘さに依存するユーザーベースができちゃうんだ。後でそれを厳しくすると、ドキュメント化されていなくても破壊的な変更になる。寛容でいることがハイラムの表面積を得る方法なんだ。俺がたどり着いた解決策は、コントロールできる境界(内部APIや設定解析)では受け入れることに厳しく、クライアントのアップグレードを強制できない外部の境界では寛容でいることだよ。でも、そのヒューリスティックは自分がどのカテゴリーにいるかを知る必要があって、これがしばしば難しい部分なんだよね。
アマゾンのリーダーシップ原則もそうだった。かなり合理的なガイドラインだけど、議論になると、結局は自分の主張を有利にするためにどれを一番うまく武器にできるかにかかってくるんだよね。他のいくつかの原則を犠牲にしても。それもまあ、いいのかもしれないけど、どうだろうね :)
法則ではなく、私が最も有用だと感じているデザイン原則の一つで、あまり知られていないものなんだけど:理想的なケースでは、機能を削除するのがディレクトリやファイルを削除するのと同じくらい簡単になるようにコードを構造化すること。
あなたの原則が適用される最小の機能単位は何?例えば、HNの各コメントには、文脈に応じて「親」「前」「次」「フラグ」「お気に入り」などのボタンが含まれる行があるよね。いつか「フラグ」機能を削除したいとしたら、各ボタンはそれぞれ別のファイルにすべき?それぞれのボタンファイルを参照する「コメントヘッダー」テンプレートファイルはどうなるの?
特徴はシステムの基本的なユニットの組み合わせから生まれるもので、通常はそれ自体が一級のユニットではないよね。例を挙げてもらえる?
機能同士は必ずしも直交してるわけじゃないし、特徴はお互いに影響し合うことが多いよね。「無関係な機能間の結合を避ける」っていうのがもっと現実的だと思う。
こうやって全部まとめて共有できるのはいいね。HNの皆に楽しんでもらうために、今の職場で若手にDRYを気にしすぎるなって言ってることで知られてるやつを追加しとくよ。> フェンの法則:コピー&ペーストはタダ;抽象化は高くつく。追記:これって、既にある関数にすごく似た新しい関数が必要な時みたいな状況を想定してるんだ。若手はコピー&ペーストが悪いと思い込んで、既存の関数にパラメータを追加して両方のケースを抽象化しようとするんだよね。俺の言いたいことは、待って、抽象化のコストを考えてみて、二つのユースケースが後で分かれる可能性はあるのか、同じビジネスオーナーがいるのか、みたいなことだよ。
同じような雰囲気だけど、違う角度から:> 11. 抽象化は複雑さを取り除くわけじゃない。複雑さをお前が当番の日に移すだけだ。出典:https://addyosmani.com/blog/21-lessons/
それを「法則」と呼ぶのはちょっと無理があるかな。もっと役に立つヒューリスティックみたいなもんだよ。実際のエンジニアリングは、いつそれを破るべきかを正確に知ることだね。
カーリーの法則が抜けてるな: https://blog.codinghorror.com/curlys-law-do-one-thing/ 「変数は一つの意味だけを持つべきで、他の状況で異なる値を持つべきじゃない。一度に二つの意味を持つべきじゃないし、床用のワックスとデザートのトッピングの両方であってはいけない。一つのことを意味し、それを常に意味するべきだ。」
俺はいつもこれをPOSIWIDで名前を付けて呼び出すんだ。
> フロアポリッシュとデザートトッピングの両方であってはいけない。レストランの近くで4年間清掃員として働いてたから、フロアポリッシュとデザートトッピングについてちょっと知ってる。だから、この法律は君が思ってるよりも普遍的じゃないかもしれない。ハイになるって言われたら、フロアポリッシュをデザートトッピングとして試してみる人もたくさんいるよ。
「このサイトは使用制限に達したため、一時停止されました。詳細についてはサイトの所有者にお問い合わせください。」AWSやAzureにもこんな機能があればいいのに。
修正したよ。
> このサイトは使用制限に達したため、一時停止されました。詳細についてはサイトの所有者にお問い合わせください。法律0:インフラを修正せよ。
これはCloudflare PagesやVercelから無料で提供できる静的ウェブサイトみたいだね。ほぼ無制限のクォータがあるのに... それでも、すでに使い尽くされてるのが皮肉だよね、ソフトウェアエンジニアリングのサイトなのに :)
法律1:キャッシングはパフォーマンスの90-99%を占める。
法律は破るためにある。
「パフォーマンスなんて関係ない!」
ウェイバックマシンが助けてくれるよ :D https://web.archive.org/web/20260421113202/https://lawsofsof...
正しく静的ウェブサイトをホストできない人が、ソフトウェアエンジニアリングについて教えようとしてるの?すごいね。どうせAIのスラップ用のバイブコードされたコンテナだと思うけど。
修正した、ありがとう!
このコレクション、いいね。見た目も良くて、各アイテムに役立つコンテキストが加わってる。もちろん、ブラウジングしてると、同意できないものも見つけたよ:テストピラミッド:https://lawsofsoftwareengineering.com/laws/testing-pyramid/ これは逆だと思う。別のコメント者のWillAdamsが「ソフトウェアデザインの哲学」(実際には「ソフトウェアデザインのためのヒューリスティックのセット」と呼ぶべきだけど)について言及していて、そこでは小さな(一般的な)インターフェースと深い実装が重要な概念なんだ。似たようなヒューリスティックは「Clojureの要素」(ザカリー・テルマン)にも出てきていて、彼は「原則に基づいたコンポーネントと適応システム」について話してる。一般的な考え方は、インターフェース、つまり自分のものがどこでつながり、他の人に使われるかを大事にすべきだってこと。コンポーネントの影響力は、そのインターフェースのサイズに反比例し、実装のサイズに比例する。テストとの関連で言うと、アーキテクチャ的に細かいテスト(スタックの下の方)は、実装にモラセスを注ぎ込むようなもので、実際に重要なこと、つまりユーザーが気にするインターフェースに焦点を当てるべきなんだ。もちろん、開発者としては自分のコードのユーザーでもあるし、全体のプログラムを構成するためのビルディングブロックを作ってる。そういうビルディングブロックのための例のテストがあるのは便利で、ある程度必要だと思う。ただ、反対したいのは、小さなテスト(メソッドや関数ごと)でテストするために部品をバラバラにしたり、分けたりしなきゃいけないという暗黙の前提ね。表面積がどうあるべきかを考える時間を取る代わりに。もし部品を組み立ててるときに超細かいテストが必要なら、それを書けばいいし(できればREPLを使うのがベスト)、でもコードがまとまって、契約や表面積を設計し始めたら、それらを保持する必要はないと思う。
その状況では、邪魔になるまでそのまま置いとくのが一般的な知恵だと思う。コストになるまでは、ちょっとは価値を提供させておけばいいんじゃないかな。