はじめに
SOLID原則とは SRP, OCP, LSP, ISP, DIPの5つの原則の頭文字を綴ったものです。
これら5つの原則はとても大切なようで、沢山の有名なアーキテクチャを支えているようですね。
それぞれどのような原則なのでしょうか?
せっかくなのでプログラミング初心者である私が頑張って説明してみようと思います。
おねがい
もし修正・補足・図を提供してくれる方がいらっしゃいましたら、気軽に編集リクエストをお願いできればと思います!
SRP: 単一責務の原則
単一責務の原則は、「どのモジュールもたったひとつのことだけを行うべき」と誤解されます。
確かにそのような原則も存在します。ひとつの関数はたったひとつのことだけを行うべきというものです。
正しくは、モジュールはたったひとつのアクターに対して責務を負うべきです。
ここで言うアクターとは、変更を望む人たちをひとまとめにしたグループの事です。
OCP: オープンクローズドの原則
オープンクローズドの原則とは、ソフトウェアの構成要素は拡張に対しては開いていなければならず、修正に対しては閉じていなければなりません。
この原則を達成すると、そのソフトウェアの特定の構成要素は、他の構成要素の影響を全く受けなくなります。また、機能追加をする際も既存の構成要素が受ける影響は限りなく少なくなります。
LSP: リスコフの置換原則
リスコフの置換原則で望まれるのは、下の例で登場するような置換可能な性質だそうです。
クラスAはクラスBを使っていて、そのBをCに置き換えた際にAの振る舞いが変わらない場合、CはBの派生形である。 と言えます。
もうちょっと詳しく知りたい方はこの記事が割と詳しく解説していたのでどうぞ。
ISP: インターフェイス分離の原則
インターフェイス分離の原則では、必要としないものとの依存を切り離し、予期せぬトラブルの発生を抑えれます。
例えば以下のようなクラスがあったとします。
User1はこのSampleクラスのmethod1に対して依存しているとします。
しかし、User1のソースコードは実際に使っていないmethod2にも意図せず依存しています。なぜなら、method1とmethod2は同じSampleクラスに対して詳細な実装がされているからです。
class Sample {
method1() {}
method2() {}
}
この問題を解決するには、各操作をインターフェイスに分離すれば良いです。
interface User1Sample {
method1: () => void;
}
interface User2Sample {
method2: () => void;
}
こんな感じですね。
User1の依存をUser1Sampleインターフェイスにしたら、User1はmethod2との意図しない依存関係から開放されました。
DIP: 依存関係逆転の原則
依存関係逆転の原則は柔軟なシステムの作り方を教えてくれます。
最も柔軟なシステムは、ソースコードの依存関係がインターフェイスだけを参照している場合です。
さいごに
2018年の今SOLID原則はもう時代遅れなのでしょうか?
数あるGoFのデザインパターンはもう時代遅れなのでしょうか?
いえいえ、そんなはずはありません。なぜなら、今も昔も「順次」「選択」「反復」を組み合わせてコードを書いているのです。
多少シンタックスシュガーでヒューマンフレンドリーになったりした所で、結局は使われている素材は同じです。