「設計の5原則」とは
ソフトウェア開発での「設計の5原則」とは、特にオブジェクト指向の設計で用いられる5つの原則です。
その5つの原則の頭文字をとって、「SOLID」とも呼ばれます。
この原則を守ることで、開発をしやすくし、維持保守もしやすくなります。
注意点
あくまで、「原則」なので、常にすべてを守る必要はないです。
これらの原則を「いつ適用するか」ということについても考える必要があります。
デザインパターンと何が違うの?
デザインパターンは、これらの原則の実現方法のパターンであることが多いです。
かぶる部分もあり、どの原則を用いたデザインかを考えると、実際に設計をする際にとっても活きてきます👌
具体的な原則名
SOLIDの相性で呼ばれる5つの原則は以下の通りです。
- Single-responsibility principle
(単一責任の原則) - Open / Closed principle
(開放閉鎖の原則 / オープン・クローズドの原則) - Liskov substitution principle
(リスコフの置換原則) - Interface segregation principle
(インターフェース分離の原則) - Dependency inversion principle
(依存性逆転の原則)
原則の解説
SOLIDがSOLIDであることをご紹介したので、ここからは和名で解説をさせていただきます!
単一責任の原則
クラスの責任は、単一であるべき
という原則です。
クラス実装が大きく変わる場合、そのクラスの役割が変わる、という場合が多いですね。
そのため、改修が生じても最小限に抑えるために、それぞれのクラスの責任を小さくしていきましょう、という意図です。
画面開発において、画面クラスと内部でパラメータを持つクラスに分ける。
画面は内部からパラメータをもらって描画のみをし、内部は画面からもらったパラメータで計算をするだけにする。
こうすることで、画面の改修、計算の改修などが生じた際、改修箇所と、影響範囲を明確にしやすくなる。
※実際はもっと細かく分けます。
このように、責務に応じてクラスが増えていくため、設計時のクラス設計管理が難しくなることがあります。
また、責務でクラスを分けたがゆえに、クラス間の依存関係が複雑になってしまうこともあります。
そして、単に「責務が単一」と言っても、どこからどこまでを「単一」とみなすかも問題になってきます。
これは設計者によるところもあるので、実際のデザインパターンでどうなっているか、ぜひ見てみてください!
※現在GRASP周りで記事執筆中。。。少々おまちを。。
開放閉鎖(オープン・クローズド)の原則
拡張に対してオープン
修正に対してクローズド
という原則です。
拡張に対してオープンとは、クラスに拡張性をもたせ、機能追加を受け入れやすくする、といった意味です。
修正に対してクローズドとは、修正を行う際、既存のソースコードは変更せずに修正を行う、という意味です。
仕様修正が生じた際、コンパイルしなおす範囲を最小限にするための原則です。
どちらも継承やポリモーフィズムなどを用いて実装されます。
この原則を用いた設計は、GoFのデザインパターンでもよく使用されています。
ただし実際には、これを完璧に実装するのは難しく、全体には求められることがないのが実情です。
実際の現場では、ここは仕様変更絶対にされない処理だから妥協箇所を寄せる、とかよくあります。。。
リスコフの置換原則
派生型であるサブクラスは、その基本型であるスーパークラスと置換可能でなければならない
という原則です。
オープンクローズドの原則と一緒によく出てくる原則です。
ポリモーフィズムを使用する際、この原則がとても効いてきます。
「スマホの容量は?」と聞かれた際、AndroidかiPhone気にせず回答することができます。
これはスーパークラスのスマートフォンが、その派生型であるサブクラスのAndroidとiPhoneが同じ「容量」を持っていて、リスコフの置換原則が満たされています。
一方、プレステと任天堂スイッチは同じ「ゲーム機」ですが、おんなじゲームはできませんよね。
これはスーパークラスの「ゲーム機」から、サブクラスへの置換はできません。
こういった感じのイメージです!
実際には、
- 基本型にない関数を派生型で作ってはいけない
- 基本型にある関数を、派生型で無視してはいけない
といった原則ですね。
リスコフの置換原則に違反した場合、オープンクローズドの原則にも違反します。
インターフェース分離の原則
クライアントに、使わない関数への依存を強要してはいけない
という原則です。
インターフェイスクラスを作る際には、抽象メソッドの実装を強制してしまいます。
そこで、クライアント側が最適なものを扱えるようになることを考えて実装をしていかなければなりません。
インターフェイス分離の原則に違反すると、
- 単一責任の原則
- リスコフの置換原則
にも違反することが多いです。
依存性逆転の原則
プログラムの中核クライアントに、使わない関数への依存を強要してはいけない部分は、詳細部分に依存してはならない。どちらも抽象に依存すべき。
抽象は実装に依存してはならない。実装が抽象に依存すべき。
という原則です。
オープンクローズドの原則とほとんど似ています。
具体的には
- 具体的なクラスへのポインタを保有する変数があってはいけない
- 具体的なクラスから、派生するクラスがあってはいけない
- 基本クラスで実装されているメソッドを、再定義するメソッドがあってはいけない
といった原則になります。
これは具体化できるので、メリデメがはっきりします。
なんでもやりすぎは良くないってことになってきますね。。。
まとめ
今回は、設計の5原則についてわかりやすくまとめてみました。
設計周りの原則や、GRASPパターン、GoFのデザインパターンなどもあるので、ぜひ一緒に勉強してみてください!
わからないことがあれば、twitterにて質疑応答し、記事に反映させていただきます!
お気軽にお問い合わせください!