未経験者向け「安定度・抽象度等価の原則(SAP)」を解説

設計

安定度・抽象度等価の原則(SAP)とは?

安定度・抽象度等価の原則(SAP: Stable Abstractions Principle) は、「安定した(変更されにくい)コンポーネントほど、抽象度も高くあるべき」 というソフトウェア設計の原則です。

簡単に言うと

  • 変更しにくい(=安定した)コンポーネントは、抽象的(=インターフェースや抽象クラス)であるべき。
  • 逆に、頻繁に変更されるコンポーネントは、具体的な実装(=詳細なクラスやビジネスロジック)であるべき。

これを守ることで、変更しやすく、柔軟性の高いシステム を作ることができます。

SAPが生まれた背景

ソフトウェア開発では、次のような問題がよく発生します:

頻繁に変更される具体的なコードに多くのコンポーネントが依存している

  • 例えば、データベース接続の詳細を含むモジュールに他の多くのコンポーネントが依存している場合、データベースの仕様変更が起きると、システム全体に影響が出てしまいます。

安定したコンポーネントが具体的すぎる

  • 例えば、基本的なログ出力処理(めったに変更しない機能)が、特定のライブラリに強く依存している場合、別のログ出力方法に変更するのが難しくなります。

これらの問題を防ぐため、「安定したコンポーネントは抽象的に、頻繁に変更されるコンポーネントは具体的に」 というSAPが提唱されました。

抽象度の継続

SAPを適用するには、抽象度を適切に設計すること が重要です。

  • 高い抽象度(例:インターフェース、抽象クラス)
    • 変更されにくい
    • さまざまな実装に対応可能
    • 他のコンポーネントからの依存が多い
  • 低い抽象度(例:具体的なクラスや関数)
    • 変更されやすい
    • 特定の機能を実装
    • 他のコンポーネントからの依存が少ない

良い設計の例

  • 「安定しているが変更しにくい部分」(例:システム全体の基本ルール) → インターフェースや抽象クラス にする。
  • 「頻繁に変わる部分」(例:UIのデザインや特定のライブラリの選定) → 具象クラス(具体的な実装) にする。

主系列(Main Sequence)とは?

SAPを図で表すと、「安定度」と「抽象度」の関係を示す主系列(Main Sequence) という直線が出てきます。

主系列の基本概念

  • X軸(安定度 I):
    • 0(左側):変更されやすい(依存されていない)コンポーネント
    • 1(右側):変更されにくい(多くのコンポーネントから依存されている)コンポーネント
  • Y軸(抽象度 A):
    • 0(下側):具体的な実装(クラス、関数など)
    • 1(上側):抽象的な概念(インターフェース、抽象クラス)

主系列の直線 は、「安定したコンポーネントほど抽象的であるべき」 というSAPの原則を示します。

除外すべきゾーン(回避すべきエリア)

SAPを適用する上で、避けるべき設計パターン が2つあります。

「不安定な抽象」ゾーン(左上)

  • 抽象度が高いのに、安定していないコンポーネント
  • 例:頻繁に変更されるインターフェースや抽象クラス

悪い例

Java
// 頻繁に変更される抽象クラス(本来は変更されにくいべき)
abstract class UIFramework {
    abstract void render();
}

問題点

  • UIの仕様は頻繁に変更されるのに、抽象クラスとして定義されているため、変更のたびにすべての実装クラスに影響を及ぼす。

「具体的な安定」ゾーン(右下)

  • 具体的なのに安定しているコンポーネント
  • 例:システムの基盤に特定のライブラリを強く依存させる

悪い例

Java
// ログ機能を特定のライブラリに強く依存
class Logger {
    public void log(String message) {
        System.out.println("Logging: " + message); // これが変更しにくい
    }
}

問題点

  • Logger は多くのコンポーネントから依存されるが、具体的すぎるため、変更が困難になる。

主系列からの距離(D値)

D値(Distance from Main Sequence) は、コンポーネントが主系列からどれくらい離れているかを示す指標です。

計算式

Java
D = |A + I - 1|
  • D = 0 に近い → 良い設計(主系列上)
  • D が大きい → 変更に弱い設計(不安定な抽象、具体的な安定)

具体的な良い設計の例

Java
// 変更されにくい(安定した)抽象クラス
interface Database {
    void connect();
}

// 変更されやすい(不安定な)具体クラス
class MySQLDatabase implements Database {
    public void connect() {
        System.out.println("Connecting to MySQL...");
    }
}

なぜ良いのか?

  1. Database インターフェースは変更されにくい → 安定している
  2. 具体的な MySQLDatabase は変更されやすい → 変更がしやすい

D値が0に近く、主系列上にあるため、良い設計となる!

まとめ

SAPのポイント

  1. 安定したコンポーネントほど抽象的であるべき
  2. 頻繁に変更される部分は、具体的な実装にすべき
  3. 主系列を意識して設計し、D値を小さくする
  4. 「不安定な抽象」「具体的な安定」のゾーンを避ける

SAPを意識すると

  • 変更しやすく、拡張しやすいシステム が作れる!
  • 不安定な変更が広がるのを防げる
  • 長期的に保守しやすいコード になる

コメント

タイトルとURLをコピーしました