プログラミング初心者がアーキテクトっぽく語る

見苦しい記事も多数あるとは思いますが訂正しつつブログと共に成長していければと思います

SOLID原則

SOLID原則というオブジェクト指向の設計原則がある。

コードの交換可能性、変更容易性、再利用性を向上するための設計指針だ。設計時だけでなく、変なコードを見つけたときにその違和感を言語化するのにも役立つ。

オブジェクト指向には優れた設計原則が多数存在するが最も広く認知されているのがこのSOLID原則だろう。

SOLID原則は5つの原則の集合だ。5つの原則の頭文字S、O、L、I、Dを取ってSOLID原則と呼ばれている。

5つの原則の要点をまとめると以下の2点に集約される。

  • クラスやメソッドの責任は小さく
  • 多態性を使う

オブジェクト指向の設計では耳にタコができるほどよく聞く言葉だが、「いつ」「なぜ」それが大事なのかが体系化、言語化されている点がSOLID原則の重要な点だ。

SOLID原則を理解することで適切なメソッド設計、クラス設計のヒントを得られるだろう。


1. Single Responsibility Principle:単一責任の原則

クラスやメソッドの役割は1つ。変更タイミングも同じ。Stakeholderも一人。

変更タイミングが異なる機能が複数あると1つを変更したとき残りの機能も確認・試験する必要がある。

Stakeholder Aの要望による変更でStakeholder Bが影響を受けると、Stakeholder Bの信頼を失うことになる。

同じような趣旨の原則として凝集度に関わる共通閉鎖原則(The Common Closure Principle)がある。


2. Open/Closed Principle:オープン/クロースドの原則

拡張に対しては開き、変更に対しては閉じる。

なにか機能を追加するとき、新しいクラスを追加することは自由だけど既存クラスの変更は最小限に留めるということ。フレームワークがよい例。

if文の多いメソッドはOCP違反のサインだ。多態性を利用して機能追加のたびにelse if文が増えるような状況を避けよう。


3. Liskov Substitution Principle:リスコフの置換原則

サブクラスの振る舞いを統一するということ。多態性を活用するときの必須条件であり、OCPの前提条件になる。

Javaのような静的型付け言語ではサブクラスがインタフェースに違反したらコンパイラに怒られる。自然とLSPが守られるので神経質になる必要はない。

一方、Pythonのような動的型付け言語でDuck Typingするときはプログラマが強く意識する必要がある。


4. Interface Segregation Principle:インターフェース分離の原則

特定のサブクラスが使わないメソッドをインタフェースに含めないこと。

大きなインタフェースはサブクラスに不要な不便を強いる。でもたまに商用コードで見かけるな。なんでだろう?使わなくなったメソッドか?


5. Dependency Inversion Principle:依存性逆転の原則

上位クラスで下位の具象クラスをnewしてはならない。

「下位クラス名 obj = new 下位クラス名();」と下位クラスの具体的な名前がコードに記述されるということはその下位クラスに上位クラスが縛られるということだ。本来は下位クラスが上位クラスに縛られるべきであり(※)、そのような依存方向性は見直さなくてはならない。

※安定度・抽象度等価の原則(上位クラスが安定していること)、安定依存の原則(安定しているクラスに依存すること)

解決策の1つにDependency Injectionがある。インタフェースをコンストラクタやセッタメソッドの引数で受け取って利用するのだ。これによって依存関係が下記のように変化する。

  • Before
上位クラス (uses)→ 下位クラス
  • After
上位クラス (uses)→ インタフェース ←(implements) 下位クラス

上位クラスと下位クラスが疎結合になり独立性、交換可能性が改善する。レイヤの境界の実装に向いている。

Dependency Injectionの効果については個人的には「逆転した」というより「緩衝材を注入した」と捉えた方が理解しやすい。