SOLID原則とは?5つの設計原則をやさしく解説【具体例付き】

SOLID原則とは、保守性と拡張性を高めるための5つの設計原則です。本記事では、各原則を具体例付きで初心者にもわかりやすく解説します。

保守性が高く、柔軟に拡張できるソフトウェアを設計するには、「良い設計とは何か?」という共通認識が欠かせません。

その基準の一つとして広く知られているのが SOLID原則 です。

本記事では、各原則の意味と、初心者にもわかりやすい具体例を通じて、SOLIDの本質を理解していきます。


SOLID原則とは?

SOLID原則とは、オブジェクト指向設計における5つの基本原則の頭文字を組み合わせたものです。

頭文字名称(英語)意味(日本語)
SSingle Responsibility Principle単一責任の原則
OOpen/Closed Principle開放閉鎖の原則
LLiskov Substitution Principleリスコフの置換原則
IInterface Segregation Principleインターフェース分離の原則
DDependency Inversion Principle依存性逆転の原則

1. 単一責任の原則(SRP)

定義:「クラスは、たった1つの責任のみを持つべきである」

1つのクラスが複数の機能を持っていると、変更が複雑になります。

責任を明確に分けることで、変更の影響範囲を限定できます。

悪い例:計算と印刷が同じクラスにある

class Report {
    public function calculate() { /* 計算処理 */ }
    public function print() { /* 印刷処理 */ }
}

良い例:クラスを役割ごとに分離

class ReportCalculator {
    public function calculate() { /* 計算処理 */ }
}

class ReportPrinter {
    public function print() { /* 印刷処理 */ }
}

2. 開放閉鎖の原則(OCP)

定義:「ソフトウェアは拡張に開かれ、修正に閉じていなければならない」

つまり、「変更ではなく拡張で対応できる設計」にするということです。

悪い例:種類が増えるたびに既存コードを修正

class Shape {
    public function draw($type) {
        if ($type == 'circle') { /*...*/ }
        elseif ($type == 'square') { /*...*/ }
    }
}

良い例:ポリモーフィズムで拡張可能にする

abstract class Shape {
    abstract public function draw();
}

class Circle extends Shape {
    public function draw() { /*...*/ }
}

class Square extends Shape {
    public function draw() { /*...*/ }
}

3. リスコフの置換原則(LSP)

定義:「親クラスを継承した子クラスは、親として扱っても破綻しないようにすべき」

悪い例:継承したのに期待を裏切る

class Bird {
    public function fly() { /*...*/ }
}

class Penguin extends Bird {
    public function fly() {
        throw new Exception("ペンギンは飛べません");
    }
}

良い例:インターフェースで飛べる鳥だけ抽象化

interface Flyable {
    public function fly();
}

class Sparrow implements Flyable {
    public function fly() { /*...*/ }
}

class Penguin {
    // 飛べないのでFlyableを実装しない
}

4. インターフェース分離の原則(ISP)

定義:「クライアントは使わないメソッドへの依存を強いられるべきではない」

1つの大きなインターフェースよりも、複数の小さなインターフェースの方が望ましいという考え方です。

悪い例:大きすぎるインターフェース

interface MultiFunctionDevice {
    public function print();
    public function scan();
    public function fax();
}

良い例:機能ごとに分離したインターフェース

interface Printer {
    public function print();
}

interface Scanner {
    public function scan();
}

5. 依存性逆転の原則(DIP)

定義:「高レベルモジュールは低レベルモジュールに依存すべきではなく、抽象に依存すべきである」

悪い例:クラスが具体的な実装に依存している

class OrderService {
    private $mysqlDb;

    public function __construct() {
        $this->mysqlDb = new MySQLDatabase();
    }
}

良い例:インターフェースに依存する

interface Database {
    public function save();
}

class MySQLDatabase implements Database {
    public function save() { /*...*/ }
}

class OrderService {
    private $db;

    public function __construct(Database $db) {
        $this->db = $db;
    }
}

まとめ:SOLID原則は"設計の土台"

SOLID原則は、オブジェクト指向における「設計の土台」となる考え方です。

  • 保守性を高めたい
  • 拡張に強い構造にしたい
  • 他の人にもわかりやすいコードにしたい

そんなときに、SOLID原則は大きな力を発揮します。

初心者にとっては「すべてを守る」よりも、なぜこの原則があるのか? を理解することが重要です。

実務の中で少しずつ意識して取り入れていきましょう。

編集部

編集部

SOLID原則とは?5つの設計原則をやさしく解説【具体例付き】