場面
14世紀初頭のイングランド。サリー州の小村オッカム——ロンドンから南西に約40キロの、記録にも残らないような小さな村——から来たフランシスコ会の修道士は、当時最も論争的な神学者の一人になっていた。
ウィリアム・オブ・オッカムは普遍論争の渦中にいた。「馬」という概念は実在するのか、それとも人間が頭の中で作った言葉の便宜に過ぎないのか——唯実論と唯名論の対立は、当時の知識人たちにとって死活問題だった。教会の権威と神学体系が絡み合っていたからだ。
しかしオッカムは論争の火花を散らしながら、脇道で方法論的な原則を磨いていた。彼の言葉は後世に「オッカムの剃刀」として知られることになる。「必要なければ、エンティティを増やすな(Entia non sunt multiplicanda praeter necessitatem)」。
シンプルな方がいい、ということではない。それは軽薄な美学だ。オッカムが言っているのは認識論的な節度だ。あなたが目の前の現象を説明するのに、なぜそのエンティティ(概念・仮定・要素)を導入する必要があるのか。それがなければ説明できないのか。できるなら、切れ。導入するものすべてが負債だ。その存在を正当化する義務が生じる。
彼が生きた14世紀は、スコラ哲学が盛んに「天使は何体まで針の頭の上に立てるか」のような議論を繰り広げていた時代だ。オッカムの剃刀はそうした複雑化の衝動への処方箋だった。「それを仮定しなければ説明できないのか?」という問いが、剃刀の刃だ。
6世紀後、この原則は科学から工学へと染み渡っていった。
1960年代、ロッキードの伝説的な航空機エンジニア、ケリー・ジョンソンは設計チームに言い続けた。「Keep it simple, stupid(KISS)」——馬鹿でも修理できるくらい単純にしろ。戦場で、限られた工具しか持たない整備士が修理できなければ、どんな精巧な飛行機も使い物にならない。複雑さは実際に人を殺す。
1970年代のベル研究所。ケン・トンプソンとデニス・リッチーたちがUnixを作ったとき、哲学が暗黙の合意として存在した。「一つのことをうまくやれ(Do one thing and do it well)」。lsはファイルを列挙する。ファイルを削除しない。ファイルを圧縮しない。複数のプログラムをパイプで組み合わせれば、組み合わせ爆発的に複雑なことができる。しかし各ピースは単純に保つ。
そして1999年。ケント・ベックが「エクストリームプログラミング(XP)」の中で「YAGNI」を説いた。“You Aren’t Gonna Need It”——あなたはそれを必要としないだろう。今必要のない機能を今作るな。今必要のない抽象化を今作るな。必要になったときに作れ。
これはオッカムの剃刀の工学的定式化だ。「今説明できないものを仮定するな」が「今必要のないものを作るな」に翻訳された。
答え
追加するものすべてが正当化の負債を負う。エンティティ(コード・抽象・依存・機能)は必要性を証明できない限り、デフォルトで存在してはならない。「将来必要になるかもしれない」は正当化ではない。剃刀を当てろ。
CSへの翻訳
YAGNIは機能についての原則として知られているが、オッカムの剃刀の切れ味はそれより深いところまで届く。
抽象化もオッカムの剃刀の対象だ。インターフェース・基底クラス・プラグインアーキテクチャ・ファクトリーパターン——これらはすべて、将来の変化を吸収するための「仮定のエンティティ」だ。その仮定が当たれば負債は清算される。しかし外れれば、永遠に正当化できないエンティティが残る。コードベースの複雑さとして。
Rubyの設計者まつもとゆきひろは「不必要な複雑さは罪だ」と言い、Pythonの「Zen of Python」(Tim Peters, 1999年執筆・2004年にPEP 20として公式化)にはこうある。「シンプルは複雑より良い。複雑は難解より良い(Simple is better than complex. Complex is better than complicated)」。これもオッカムだ。
依存ライブラリもオッカムの剃刀の対象だ。ライブラリを追加するたびに、そのライブラリの存在を正当化しなければならない。セキュリティアップデートの追跡、バージョン競合の解決、ライセンスの確認。「日付フォーマットのためだけにmomentjsを入れる」のをやめてネイティブのIntl APIで済ます——それが剃刀の動きだ。
設計への示唆
「後で拡張できるように」という言葉は、オッカムの剃刀への挑戦状だ。その設計を今正当化できるか?
❌ 剃刀を無視した設計(エンティティを増やす)
// 「後でプラグインが必要になるかもしれない」という理由で
interface NotificationPlugin {
send(message: string, config: PluginConfig): Promise<void>;
}
class NotificationPluginRegistry {
private plugins: Map<string, NotificationPlugin> = new Map();
register(name: string, plugin: NotificationPlugin): void { /* ... */ }
get(name: string): NotificationPlugin { /* ... */ }
}
class NotificationFactory {
constructor(private registry: NotificationPluginRegistry) {}
create(type: string): NotificationPlugin { /* ... */ }
}
// 結果:誰かがメール一本送りたかっただけなのに
// 3つの新しいエンティティが生まれた
このコードを書いた後で、プラグインが一種類しか要らないと判明したとき、このアーキテクチャは永遠に正当化されない負債になる。
✅ 剃刀を当てた設計(今必要なものだけ)
// 今必要なのはメール通知だけ
async function sendEmailNotification(to: string, message: string): Promise<void> {
await emailClient.send({ to, body: message });
}
// 後でSMS通知が必要になったとき、そのときに考える
// 二種類になったとき、共通化の圧力が生まれる
// 三種類になったとき、インターフェースを引き出す根拠が生まれる
「将来必要かもしれない」ではなく、「今実際に必要だ」が唯一の正当化だ。
オッカムのテスト:「これを削除したら何が壊れるか」。今何も壊れないなら、そのエンティティは剃刀で切られるべきだ。
ただしオッカムの剃刀には重要な限定条件がある。「必要以上に」という部分だ。単純にすればするほど良い、ではない。説明に必要な最小限を残せ、それ以上を切れ、ということだ。医薬品の副作用を記録する機能は複雑に見えても、必要なら正当化される。削るな。
flowchart TD
Start([「この機能/抽象/依存を追加すべきか?」]) --> Q1{今、具体的な\n使用ケースが\n存在するか?}
Q1 -->|いいえ| Cut[❌ 追加しない\nYAGNI / オッカムの剃刀]
Q1 -->|はい| Q2{既存の手段で\n解決できるか?}
Q2 -->|はい| Cut2[❌ 追加しない\n既存のものを使う]
Q2 -->|いいえ| Q3{追加のコスト<br/>複雑さ・保守・学習コスト<br/>が価値を上回るか?}
Q3 -->|上回る| Cut3[❌ 追加しない\nコストが価値より大きい]
Q3 -->|下回る| Add[✅ 追加する\n正当化された]
style Cut fill:#ffcccc
style Cut2 fill:#ffcccc
style Cut3 fill:#ffcccc
style Add fill:#ccffcc
エンジニアリングの引力は常に追加の方向に働く。「あった方が便利かもしれない」「将来的に必要になりそう」「せっかくだから汎用化しよう」——これらの言葉が聞こえたとき、剃刀を手に取る時だ。
剃刀の限界 ── テスラーの複雑性保存則
ただし、剃刀には切れない領域がある。1980年代、Apple の UI 研究者だったラリー・テスラーは観察した:「アプリケーションの複雑性には、削減不可能な最小値がある。複雑性は消えない、移動するだけだ(Tesler’s Law of the Conservation of Complexity)」。
たとえばメール送信機能。エンドユーザー側の入力フォームを単純にすればするほど、裏側の自動補完・バリデーション・スパム判定・送信失敗時のリカバリは複雑になる。逆にユーザーに毎回詳細を入れさせれば、バックエンドはシンプルになるがUIは複雑になる。複雑性は系全体に保存される。
オッカムの剃刀はこの保存則の中で動く。剃刀が切り落とせるのは「不要な複雑性」だけで、「必要な複雑性」は切れない。剃刀を当てる正しい問いは「これを削除したら何が壊れるか」であって、「これを単純にしたら何が変わるか」ではない。後者は複雑性をどこかに押しつける議論で、削減ではない。
オッカムが14世紀のスコラ哲学の複雑さに抗ったように、今日のソフトウェアエンジニアは常にコードベースの複雑化の衝動に抗わなければならない。剃刀は切り捨ての道具ではなく、問いの道具だ。「これは本当に必要か?」——この問いを持ち続けることが、シンプルな設計の唯一の方法だ。
問い:直近のスプリントで追加したコードに「これを削除したら何が壊れるか」を当ててみてほしい。今すぐ何も壊れないものが一つでもあれば、剃刀が必要だ。