はじめに
変更しやすい設計を考えるとき、「責務を分ける」「依存を弱くする」といった個別の考え方だけでは、どこを見直すべきか判断しにくいことがあります。SOLID原則は、変更理由、機能追加、部品の置換、インターフェース、依存方向という5つの観点から設計を確認するための原則です。
SOLIDは、クラスやインターフェースを増やすための規則ではありません。実際に起こる変更を想定し、その影響を必要な範囲へ限定するために使います。この記事では、5つの原則の意味と、注文処理を例にした使い方を解説します。
この記事で分かること
- SOLID原則とは何か
- 5つの原則が確認する問題
- 注文処理へ適用する考え方
- 設計レビューでの使い方
SOLID原則とは
SOLID原則とは、ソフトウェアの役割と依存関係を整理し、変更の影響を必要な範囲へ限定するための5つの設計原則です。名称は、5つの原則の英語名の頭文字から構成されています。
原則ごとに確認する問題は異なりますが、共通する目的は、どこを変更し、どこを変更しなくてよいかを明確にすることです。変更しやすい設計を重視する理由は、良い設計より「変更できる設計」が重要な理由で説明しています。
| 略称 | 原則 | 主に確認すること |
|---|---|---|
| S | 単一責任の原則 | 異なる理由で変更される責務が混在していないか |
| O | オープン/クローズドの原則 | 新しい種類を追加するたびに安定した部分を修正していないか |
| L | リスコフの置換原則 | 実装を置き換えても利用側との約束を守れるか |
| I | インターフェース分離の原則 | 利用しない操作へ依存させていないか |
| D | 依存性逆転の原則 | 業務処理が具体的な技術へ依存していないか |
SOLIDを構成する5つの原則
単一責任の原則(SRP)
単一責任の原則は、同じ関係者から求められる変更をまとめ、異なる関係者から求められる変更を分ける考え方です。一つのクラスに一つの処理だけを書くという意味ではありません。注文金額の計算、データ保存、通知文面のように変更理由が異なる詳細を分けることで、関係のない変更が同じ場所へ集まることを防ぎます。責務が混在する背景は、責務が曖昧なクラスはなぜ生まれるのかで説明しています。
オープン/クローズドの原則(OCP)
オープン/クローズドの原則は、機能の拡張には開かれ、安定した部分の修正には閉じた構造を目指す考え方です。既存コードを一切変更しないのではなく、発生しやすい変更に対して修正箇所を限定します。新しい決済方法を追加するたびに注文処理全体を修正する状態より、決済実装を追加するだけで対応できる状態を目指します。
リスコフの置換原則(LSP)
リスコフの置換原則は、同じ役割の実装へ置き換えても、利用側との約束を壊さないという考え方です。同じインターフェースを実装していても、受け付ける入力、結果、失敗の意味、処理後の状態が大きく異なれば置換可能とはいえません。利用側が実装ごとの特別な条件分岐を持たずに扱えることが判断基準です。
インターフェース分離の原則(ISP)
インターフェース分離の原則は、利用側へ不要な操作まで依存させないという考え方です。注文登録が決済の実行だけを必要とするなら、返金、管理設定、売上レポートまで同じインターフェースに含める必要はありません。ただし、操作を一つずつ分けるのではなく、同じ利用目的を持つ操作をまとめます。
依存性逆転の原則(DIP)
依存性逆転の原則は、業務処理と技術的な実装の両方を、業務側で定めた抽象へ依存させる考え方です。注文処理が特定の決済サービスやデータベースの操作方法を直接知ると、技術の変更が業務処理へ波及します。「決済する」「注文を保存する」という役割を境界として定め、具体的なサービス側がその役割を実現することで、依存方向を業務側へ向けます。
5つの原則は、内部の役割をまとめ、外部との依存を必要な範囲へ絞る点でつながっています。この関係は、凝集度と結合度の違い|高凝集・低結合が望ましい理由と判断方法で扱う考え方とも共通します。
注文処理をSOLID原則で見直す例
注文を登録するクラスが、金額計算、データ保存、決済サービスの呼び出し、通知まで直接担当しているとします。さらに、決済方法ごとの条件分岐を持ち、返金や管理機能まで含む大きな決済インターフェースへ依存している状態です。
| 原則 | 確認する問題 | 設計の方向 |
|---|---|---|
| 単一責任 | 計算、保存、決済、通知が異なる理由で変更される | 変更理由の異なる詳細を分ける |
| オープン/クローズド | 決済方法を追加するたびに注文処理を修正する | 決済実装を追加できる境界を作る |
| リスコフの置換 | 決済実装ごとに結果や失敗の意味が異なる | 利用側との約束をそろえる |
| インターフェース分離 | 注文処理が返金や管理機能にも依存する | 注文処理が必要とする操作だけを分ける |
| 依存性逆転 | 注文処理が特定サービスのAPIを直接知っている | 注文処理を決済の役割へ依存させる |
5つの原則ごとに新しい層やクラスを作る必要はありません。まず異なる理由で変わる処理を分け、次に種類が増える部分や技術を交換する部分へ、必要な境界だけを設けます。
設計レビューでSOLID原則を使う方法
SOLID原則は、設計を点数化するチェックリストではなく、具体的な変更の影響を追うために使います。「決済方法を追加する」「通知方法を変更する」といった変更を一つ選び、次の順で確認します。
- 変更の理由と、影響を受ける範囲を特定する
- 追加や置換のたびに、安定した部分や利用側を修正していないか確認する
- 不要な操作や具体的な技術へ依存していないか確認する
すべての箇所を5原則へ完全に適合させる必要はありません。変更頻度が高い部分、変更時の影響が大きい部分、複数の実装へ置き換わる部分を優先します。
SOLID原則で起こりやすい誤解
| 誤解 | 実際の考え方 |
|---|---|
| 一つのクラスには一つのメソッドだけを置く | 処理数ではなく、変更を求める理由がまとまっているかを確認する |
| クラスやインターフェースを増やすほどよい | 実際の変更に必要な境界だけを作る |
| 既存コードは一切修正してはいけない | 予想される変更に対して、安定した部分への修正を減らす |
| すべての場所へ5原則を適用する | 変更頻度と影響を見て、効果がある場所を優先する |
原則を機械的に適用すると、単純な処理にも抽象化が増え、かえって流れを追いにくくなります。原則の名称ではなく、想定した変更を安全に行えるかで判断します。
SOLID原則で設計上の問題を確認したあと、具体的な役割分担や協調方法を検討する場合は、「デザインパターン」を解決候補として使えます。
まとめ
SOLID原則とは、単一責任、オープン/クローズド、リスコフの置換、インターフェース分離、依存性逆転という5つの設計原則です。変更理由を分け、追加や置換で安定した部分を壊さず、不要な依存を減らすための判断に使います。
大切なのは、すべての設計へ機械的に適用することではありません。具体的な変更と影響範囲を確認し、必要な場所へ境界を設けることで、変更しやすさを具体的に検討できます。


コメント