開放閉鎖の原則
SOLID の O - ソフトウェアの構成要素は拡張に対して開かれ、修正に対して閉じているべきという設計原則
開放閉鎖の原則とは
開放閉鎖の原則 (Open-Closed Principle, OCP) は、SOLID 原則の O にあたり、「ソフトウェアの構成要素は拡張に対して開かれ (Open)、修正に対して閉じている (Closed) べき」という設計原則である。
Bertrand Meyer が 1988 年の著書「Object-Oriented Software Construction」で提唱し、Robert C. Martin がポリモーフィズムを活用した形に再定義した。新しい機能を追加するとき、既存のコードを変更せずに拡張できる設計を目指す。
なぜ重要か
既存コードを修正すると、そのコードに依存する全箇所に回帰リスクが生じる。決済処理に新しい決済手段を追加するたびに if-else を追加していると、既存の決済手段のロジックが壊れるリスクがある。OCP に従えば、新しい決済手段を「追加」するだけで、既存コードには触れない。
違反の典型例
// ❌ OCP 違反: 新しい割引タイプを追加するたびに既存コードを修正
function calculateDiscount(order: Order): number {
if (order.type === 'regular') {
return order.total * 0.05;
} else if (order.type === 'premium') {
return order.total * 0.10;
} else if (order.type === 'vip') { // ← 追加のたびに修正
return order.total * 0.15;
}
return 0;
}
新しい顧客タイプが増えるたびに calculateDiscount を修正する必要がある。修正のたびに既存の割引ロジックが壊れるリスクがある。
OCP に従った設計
// ✅ OCP 準拠: インターフェースで拡張ポイントを定義
interface DiscountStrategy {
calculate(order: Order): number;
}
class RegularDiscount implements DiscountStrategy {
calculate(order: Order): number { return order.total * 0.05; }
}
class PremiumDiscount implements DiscountStrategy {
calculate(order: Order): number { return order.total * 0.10; }
}
// 新しい割引タイプの追加: 既存コードを修正せず、新しいクラスを追加するだけ
class VipDiscount implements DiscountStrategy {
calculate(order: Order): number { return order.total * 0.15; }
}
function calculateDiscount(order: Order, strategy: DiscountStrategy): number {
return strategy.calculate(order);
}
VipDiscount を追加しても、RegularDiscount や PremiumDiscount のコードには一切触れない。これが「拡張に対して開かれ、修正に対して閉じている」状態だ。
OCP を実現するパターン
| パターン | 仕組み | 適するケース |
|---|---|---|
| Strategy | インターフェースで振る舞いを差し替え | アルゴリズムの切り替え |
| Template Method | 基底クラスで骨格を定義、サブクラスで詳細を実装 | 処理フローが共通の場合 |
| Observer | イベントリスナーの追加で機能拡張 | 通知・イベント処理 |
| Decorator | 既存オブジェクトをラップして機能追加 | 横断的関心事の追加 |
過剰適用の罠
OCP を厳密に適用しすぎると、すべての分岐をインターフェースとクラスに分離することになり、コードが過度に抽象化される。2〜3 種類しかない分岐を Strategy パターンで実装するのはオーバーエンジニアリングだ。
判断基準は「この分岐は今後増える可能性が高いか」である。決済手段や通知チャネルのように拡張が予想される箇所には OCP を適用し、変更の可能性が低い箇所には素直な if-else で十分だ。
さらに掘り下げるなら関連書籍が参考になる。