SOLID原則について(Clean Architecture 読書メモ)
SOLID原則は、ソフトウェアのオブジェクト指向設計における5つの原則を表しています。
- 単一責任の原則(Single Responsibility Principle)
- オープン・クローズドの原則(Open-Closed Principle)
- リスコフの置換原則(Liskov Substitution Principle)
- インターフェース分離の原則(Interface Segregation Principle)
- 依存関係逆転の原則(Dependency Inversion Principle)
これらの原則は、ソフトウェア設計において、保守性や拡張性、再利用性などを確保するために重要な考え方です。以下では、それぞれの原則について説明します。
1. 単一責任の原則(Single Responsibility Principle)
単一責任の原則は、クラスやモジュールが持つべき責任を1つに限定する原則です。つまり、1つのクラスやモジュールが複数の責任を持つことを避け、1つの責任に徹するように設計することが求められます。
違反例:
上記のクラス Employee は、名前や住所の設定や給与の計算など、複数の責任を持っています。このため、変更が発生した場合に影響範囲が広くなり、保守性や拡張性が損なわれる可能性があります。
改善例:
改善例では、Employee クラスは名前や住所の設定や給与の計算の責任を持ち、EmployeeReport クラスは勤務時間の報告の責任を、EmployeeRepository クラスはデータの永続化の責任を持つようにしました。これにより、各クラスは単一責任を持ち、変更に伴う影響範囲が限定されるようになります。
2. オープン・クローズドの原則(Open-Closed Principle)
オープン・クローズドの原則は、クラスやモジュールは、拡張には開かれ、修正には閉じているべきであるという原則です。つまり、既存のクラスやモジュールを変更することなく、新しい機能や要件を追加することができるように設計することが求められます。
違反例:
上記のクラス Rectangle と Circle は、それぞれ長方形と円の面積を計算するクラスです。しかし、新しい図形を追加するたびに、クラスを修正する必要があります。
改善例:
改善例では、図形を表すインターフェース Shape を作成し、各図形は Shape インタフェースを実装するようにしました。これにより、新しい図形を追加する場合でも、新しいクラスを作成し、Shape インターフェースを実装するだけで済むようになります。
3. リスコフの置換原則(Liskov Substitution Principle)
リスコフの置換原則は、クラスの継承に関する原則であり、派生クラスは、基底クラスの代わりに利用できるべきであるという原則です。つまり、基底クラスのインターフェースを継承したクラスが、基底クラスの代わりに使用できるように設計することが求められます。
違反例:
上記のクラス Rectangle と Square は、それぞれ長方形と正方形の面積を計算するクラスです。しかし、正方形は長方形の特殊ケースであるにもかかわらず、Square クラスでは幅と高さが同じ値であることを強制しています。
改善例:
4. インターフェース分離の原則(Interface Segregation Principle)
インターフェース分離の原則は、クライアントが利用するインターフェースを、必要な機能だけに限定する原則です。つまり、インターフェースが持つメソッドやプロパティを、使用するクライアントにとって必要なものだけに絞り込むことが求められます。
違反例:
上記のコードでは、複合機を表す Machine インターフェースを定義しています。しかし、すべての機器が必ずしもすべての機能を備えているわけではないため、Printer クラスや Scanner クラスでは、必要のない機能を実装していることになります。
改善例:
改善例では、機能ごとにインターフェースを分離し、MultiFunctionPrinter クラスは必要なインターフェースを実装することで複合機の振る舞いを実現します。SimplePrinter クラスや SimpleScanner クラスでは必要最低限の機能だけを実装しているため、余分なコードが存在しなくなりました。
5. 依存関係逆転の原則(Dependency Inversion Principle)
依存関係逆転の原則は、上位モジュールが下位モジュールに依存すべきではなく、抽象化に依存するべきであるという原則です。つまり、コードの依存関係を抽象化によって切り離し、より柔軟な設計を実現することが求められます。
Clean Architectureでは、依存関係を管理するために、依存性逆転原則 (DIP)を使用することが推奨されます。DIPに従って、高水準のモジュールは低水準のモジュールに依存するべきではなく、両方のモジュールは抽象的なインタフェースに依存するように設計するという考え方です。
違反例:
上記のコードでは、UserService クラスは UserRepository クラスに依存しています。このため、UserRepository クラスに変更があった場合、UserService クラスも変更しなければなりません。
改善例:
改善例では、UserService クラスが UserRepository インターフェースに依存するようにしました。このため、InMemoryUserRepository クラスのように、UserRepository インターフェースを実装するどんなクラスでも、UserService クラスのコードを変更せずに使用できます。このように、依存関係をインターフェースに対して行うことで、実装に依存しないコードを書くことができます。
まとめ
SOLID原則は、ソフトウェアの構造や設計を良くするための原則であり、より柔軟な設計を実現するために重要な考え方です。特に、クラスやモジュールの単一責任や、オープン・クローズドの原則は、より柔軟な設計を実現するために重要な考え方です。また、リスコフの置換原則やインターフェース分離の原則は、インターフェースの設計に関する重要な考え方であり、依存関係逆転の原則は、コードの依存関係を切り離すための重要な考え方です。これらの原則を理解し、実践することで、より柔軟で保守性の高いソフトウェアを実現することができます。
Discussion