頭が弱いことで有名な私は、あるとき有能な後輩からこういわれました**「設計なんてSOLID原則さえ覚えてれば大丈夫」**と...
C++勉強中でまだまだ知識不足な私にはSOLID原則なるものをまだ知りませんでした😢
だからGoogle先生に聞いてみることにしたんですね~
そしたら、「なんか見たことあるやつあるー!」ってなりました
意外とプログラム書いているとそれっぽいこと聞いたことある人もいるかもしれないと思って、「ハードルが低そうなSOLID原則についての記事を書いて自分でもついでにりかいしちゃおー!」って考えた次第です
知能指数が猫レベルの私の事なので、まだ別にSOLID原則を完全に理解しているわけではないですが、とりあえず完全に理解することよりも、何となく概要をつかむ方が実践においては大事な気がする(そんなことはない)ので備忘録程度に読んでいただければ幸いです~
もし間違えてたり、ここ猫のIQじゃ分からんぞ!!😡っていうことがあれば、コメントでお願いします!
SOLID原則とは?
なんかプログラマのすごい人が考えた、**「オブジェクト指向ではとりあえずこれやっとけばプログラムの不安定要素少なくなるよ!」**っていうプログラムのルールの群れのこと
5つの法則のそれぞれ頭文字を取ったのがSOLIDで
S:Single Responsibility Principle(単一責任の原則)
O:Open/closed principle(オープン/クロースドの原則)
L:Liskov substitution principle (リスコフの置換原則)
I:Interface segregation principle(インターフェース分離の原則)
D:Dependency inversion principle (依存性逆転の原則)
これだけ見ても猫のIQじゃわかんないですよね~
なのでIQ下げてわかる範囲で説明してみます
間違ってたらおしえてください~~~
Sのやつ(単一責任の原則)
これは比較的原則名でもわかりやすそうですね!
単一責任...と聞くと、「1つだけの責任」みたいな感じしますね~
実際その通りでして、ざっくり言うと
1つのクラスに仕事は1つだけ!
っていう事みたいです
というのも、どこかでエラーが発生したときに、どこかしらのクラスを修正する必要がありますよね?
その時に、1つのクラスに仕事がいっぱいあると、そのクラスを修正したときに関係ないけど、同じクラスに書かれている処理まで被害を被る可能性があるから、リスクを分散させようね!
ということだけど、これでもよく分からなければこう覚えよう!
処理を変更する時の責任を連帯責任にならないようにしようね! このエラーは君だけの問題だよ😁
S=責任に関するルール(責任のローマ字の頭文字Sだし)
で覚えようね!
Oのやつ(オープン/クロースドの原則)
これも名前だけ聞くと、分かりそうだけど、何を開閉させるの???って感じですね
その正体は、クラスなどの仕組みが機能の拡張ができる状態をOpen:開いている
、そして、拡張の時に修正する必要がないという状態Close:閉じている
と言うみたいです
とはいえ、「そんなんむりやん🥺」って思いますよね
私もそう思いました
結論から言えば、機能の追加には既存のコードを修正せず、新しくコードを記入するだけにする
という状態にすればいいらしいんですね~
というのも、機能の追加のたびに既存のコードを書き換えるというのは、その度どこかでそのコードと関連付けられた部分でエラーを吐く危険性を孕んでいるんですよね
「そんなの嫌だ!!😤」ってことで、このルールが存在するですね~
O=オープンとクローズドに関するルール(まんまやんけ)
で覚えようね!
Lのやつ(リスコフの置換原則)
これは、ぱっと見だとリスコフさんが考えた置換に関する原則だってことは一目でわかりますね!
リスコフさんは、アメリカで活躍している女性のプログラマーで、御年81歳だそうです
なんでも、プログラム言語の開発に携わっていたり、オブジェクト指向プログラミングにおける派生の概念を定着させた方だそうです
すごいですね!
そんな方が考えた置換に関するルールというのが、S が T の派生型であれば、プログラム内で T 型のオブジェクトが使われている箇所は全て S 型のオブジェクトで置換可能であれ
というもの
これだけ見ても、IQ🐈は分からないですよね~
簡単に言えば、Tの機能を継承したSをプログラムの上で使用したとき、そのSをそのままTで書き換えても正常に動くようにしようね!
つまるところ、「継承元のT以上の機能をSに実装するのはいいけど、Tの機能をSでなくすようなことはするなよ!!😡」ってことだね
コメントでめちゃくちゃ分かりやすい例えを出してくれた方がいたので、引用させていただきます!
たとえばUSB3.0はUSB1.0や2.0などを継承した規格なので、USB3.0のデバイスをUSB1.0のポートに繋ぐとUSB1.0のデバイスとして動作することが要求されます。
USBってオブジェクト指向的な考えをかなり取り入れた設計なんですよね。
これめっちゃ分かりやすいですよね!
意外と知識があると身近なものが自分の知ってる知識で出来ているって分かるのいいですよね!(伝われ!!)
L=リスコフさんが作ったルール(リスコフさんは派生に関する権威だから)
で覚えようね!
Iのやつ(インターフェース分離の原則)
これもぱっと見で結構分かりますね!
インターフェースを分離させるルールまたは、インターフェースを分離する時のルール
みたいな感じっぽいですね!
そもそもインターフェースってなんでしょうか?
SOLID原則にたどり着いてる人はもう知ってるかもしれないですけど、一応説明だけしますね!(自分が分かってない←)
インターフェースって言うのは、複数のオブジェクトがある時に、それらの共通部分は一括で実装してそれを継承しよう!っていう考えに至った時に共通部分を実装するものだと思ってくれれば大丈夫だと思います
PCのUSB端子なんかも、差し込み部分は共通部分で、その先がマウスであったり、キーボードであったり、固有の実装がありますよね
だからUSB端子の事はインターフェースというんですね!
それはそうと、それを分離ってどういう事なんでしょうね?
簡単に言うと、インターフェースは極力最小の実装をし、機能によってしっかり分ける
ということなんですね~
というのも、1つのインターフェースにあれもこれもって実装すると、いざそのインターフェースを使用する時に、
「あれ?この機能ってここになかったっけ???」 ってなっちゃうんですよね
USB端子がイヤホンジャックも、LAN用端子も充電用端子も共通してあったら、便利かもしれないですけど、その分その端子って壊れやすい気がしますよね
そういう事です!
だから、インターフェースはできるだけ小さいものにしましょうってことなんですね
1個の汎用性が高いインターフェースよりも、10個の小さいインターフェースの方がいいってことですね!
コード量は増えるし、それだけ実装は大変だけど、その分作ってさえしまえば便利の極みですからね~
プログラマは楽するために苦行に耐えねばならんのです!
このルールはクラスにたくさんの機能を持たせないようにする単一責任の原則(Sのやつ)とよく似てて覚えやすいですね!
I=インターフェースに関するルール(これもまんまやん)
で覚えようね!
Dのやつ(依存性逆転の原則)
これが一番分からん!!!
名前だけ見ても、そもそも依存性ってなんじゃー!!って感じですし、それをさらに逆転させるんですから余計にわかんないですよね
私も理解してるかよくわかってないんですけど、
依存というのはAがBを読み込んだ場合AはBに依存している
という事になります
AさんがBさんに告白して付き合い始めたらAさんがBさんにめちゃくちゃ依存しちゃったっていう感じですね!
そして、依存している状態では、もし、依存先(Bさん)に変更が加わると、依存元(Aさん)にも何かしら影響があるという状態ですね
ここまではまだ理解できるんですよね
問題はここからで、それを逆転ってどういうことじゃい!と
難しい言葉で上位のモジュールは下位のモジュールに依存してはならない。どちらのモジュールも「抽象」に依存すべきである。
などと説明がなされているんですが、上位とか下位とか分かるか!!ってなっちゃいますね...
なのでここからは私の友人の言葉を借りて、説明しますと
クラス図の矢印を逆向きにすることを依存性逆転という←ふむふむ
その際に生じる不具合には、インターフェースを噛んでなんとかする←!?
という事らしいです~
最後に
どうでしたか?猫のIQでも分かったでしょうか?
私もまだ理解しきれてないので、猫のIQをお持ちの方はご安心ください
とはいえ、完全には理解できなくても、知ってるだけで役には立つものばかりのものなので、とりあえずなんかそういうルールがあるって覚えとけば大丈夫だと思います!!!!(適当)