SOLID 原則

オブジェクト指向設計の 5 つの基本原則で、保守性と拡張性の高いコードを実現する

設計原則オブジェクト指向

SOLID 原則とは

SOLID は、Robert C. Martin (Uncle Bob) が提唱したオブジェクト指向設計の 5 つの基本原則の頭文字である。保守性、拡張性、テスト容易性の高いコードを実現する。

5 つの原則

原則 名前 一言
S 単一責任 (SRP) クラスの変更理由は 1 つだけ
O 開放閉鎖 (OCP) 拡張に開き、修正に閉じる
L リスコフ置換 (LSP) サブタイプは親と置換可能
I インターフェース分離 (ISP) 使わないメソッドに依存しない
D 依存性逆転 (DIP) 具象ではなく抽象に依存

S: 単一責任の原則

// ❌ 1 つのクラスに複数の責務
class UserService {
  createUser(data: UserInput) { /* DB 操作 */ }
  sendWelcomeEmail(user: User) { /* メール送信 */ }
  generateReport(users: User[]) { /* レポート生成 */ }
}

// ✅ 責務ごとに分離
class UserRepository { create(data: UserInput) { /* DB 操作 */ } }
class EmailService { sendWelcome(user: User) { /* メール送信 */ } }
class ReportGenerator { generate(users: User[]) { /* レポート生成 */ } }

O: 開放閉鎖の原則

// ✅ 新しい通知方法を追加しても既存コードを変更しない
interface Notifier { notify(message: string): Promise<void>; }

class EmailNotifier implements Notifier { async notify(msg: string) { /* メール */ } }
class SlackNotifier implements Notifier { async notify(msg: string) { /* Slack */ } }
// 新しい通知方法を追加: 既存コードの変更なし
class SmsNotifier implements Notifier { async notify(msg: string) { /* SMS */ } }

D: 依存性逆転の原則

// ❌ 具象に依存
class OrderService {
  private db = new DynamoDBClient({}); // 具象クラスに直接依存
}

// ✅ 抽象に依存
class OrderService {
  constructor(private repo: OrderRepository) {} // インターフェースに依存
}

SOLID の過剰適用に注意

SOLID は指針であり、全てのコードに厳密に適用する必要はない。Lambda の単純な CRUD 関数に SOLID を厳密に適用すると、過度な抽象化で複雑になる。

ケース SOLID の適用度
複雑なドメインロジック 厳密に適用
共有ライブラリ 厳密に適用
単純な Lambda 関数 緩やかに適用
スクリプト 不要

SOLID 原則の関連書籍も参考になる。

関連用語