開放閉鎖の原則

SOLID の O - ソフトウェアの構成要素は拡張に対して開かれ、修正に対して閉じているべきという設計原則

SOLID設計原則

開放閉鎖の原則とは

開放閉鎖の原則 (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 を追加しても、RegularDiscountPremiumDiscount のコードには一切触れない。これが「拡張に対して開かれ、修正に対して閉じている」状態だ。

OCP を実現するパターン

パターン 仕組み 適するケース
Strategy インターフェースで振る舞いを差し替え アルゴリズムの切り替え
Template Method 基底クラスで骨格を定義、サブクラスで詳細を実装 処理フローが共通の場合
Observer イベントリスナーの追加で機能拡張 通知・イベント処理
Decorator 既存オブジェクトをラップして機能追加 横断的関心事の追加

過剰適用の罠

OCP を厳密に適用しすぎると、すべての分岐をインターフェースとクラスに分離することになり、コードが過度に抽象化される。2〜3 種類しかない分岐を Strategy パターンで実装するのはオーバーエンジニアリングだ。

判断基準は「この分岐は今後増える可能性が高いか」である。決済手段や通知チャネルのように拡張が予想される箇所には OCP を適用し、変更の可能性が低い箇所には素直な if-else で十分だ。

さらに掘り下げるなら関連書籍が参考になる。

関連用語