章: 第1章: オブジェクト指向の深化
「修正するたびに別の場所が壊れる」——その原因を特定できていますか?
「このコード、手を入れるたびに予期しない場所が壊れる」——チームで共有した経験ではないでしょうか。
原因のほとんどは、クラスが複数の責務を抱え込んでいるか、依存関係が複雑に絡み合っていることにあります。
SOLID原則は、そうした「変更に弱いコード」を避けるための5つの指針です。一度身につけると、設計の判断が格段に速くなります。
SOLID原則とは何か
SOLID原則は「変更に強いコード」を書くための5つの指針です。それぞれの頭文字をまとめた名称で、オブジェクト指向設計の出発点として世界中で使われています。
| 原則 | 名称 | 一言で言うと |
| S | 単一責務の原則 | 1クラスは1つの理由でのみ変更される |
| O | 開放閉鎖の原則 | 拡張には開いて、修正には閉じる |
| L | リスコフ置換の原則 | 親クラスを子クラスで安全に置き換えられる |
| I | インターフェイス分離の原則 | 使わないメソッドに依存させない |
| D | 依存性逆転の原則 | 抽象に依存し、具体に依存しない |
チェックポイント: 「このクラスを修正する理由が2つ以上ある」と感じたら、Sの原則(単一責務)が崩れているサインです。
悪い例 vs 良い例:Sの原則(単一責務)
<?php
// NG: 請求書クラスが「書式化」と「保存」を両方担っている
class Invoice {
public function format(): string { /* ... */ }
public function save(): void { /* DBに保存 */ }
}
// OK: 責務ごとに分離する
class InvoiceFormatter {
public function format(Invoice $inv): string {
return $inv->id . ': ' . $inv->total;
}
}
class InvoiceSaver {
public function save(Invoice $inv): void {
// DB保存処理
}
}
SOLID違反が引き起こすコスト比較
| 観点 | SOLID違反のコード | SOLID準拠のコード |
| 修正の影響範囲 | 1箇所変えると別の責務まで影響 | 変更箇所が1クラスに限定される |
| テストのしやすさ | DBや外部依存がテストに混入する | 単独で単体テストできる |
| 再利用性 | 不要なロジックがセットでついてくる | 必要な部品だけ使える |
| 拡張コスト | 機能追加のたびに既存コードを変更 | 新クラスの追加で対応できる |
チェックポイント: 「このクラスのテストを書くとき、DBのモックが必要になる理由は何か?」と自問すると、責務の混在に気づきやすくなります。
なぜ今SOLID原則を学ぶのか
規模が小さいうちはSOLID違反は気になりません。しかしクラスが増えるほど、違反はバグと修正コストに直結します。
- 責務が混在したクラスは、変更のたびに副作用が起きやすい
- 具体実装への依存は、テストで差し替えが効かなくなる
- 拡張に修正が必要な設計は、新機能追加のたびに既存コードが壊れるリスクがある
SOLID原則を早い段階で身につけると、「このクラス、後で修正が怖い」という感覚が消えていきます。
チェックポイント: 「責務の境界を先に決める」「依存の向きを確認する」「差し替えテストを行う」の3ステップが設計見直しの出発点です。
まとめ & 次のステップ
- SOLID原則は「変更に強いコード」を設計するための5つの指針
- Sの原則(単一責務)は「このクラスが変わる理由は1つだけか」を問うこと
- クラスが増えるほどSOLID違反の修正コストは膨らむため、設計段階で意識する価値がある
- 「テストが書きにくい」「修正が怖い」という感覚はSOLID違反のサインとして活用できる
次回はSOLID原則の実践編として、O(開放閉鎖の原則)を中心に「既存コードを変えずに機能を追加する」設計を手を動かして学びます。