【ソフトウェア開発】設計の目的とSOLID原則についてまとめる【クリーンアーキテクチャ】

おすすめ技術書
マイケル
マイケル
みなさんこんばんは!
マイケルです!!
エレキベア
エレキベア
クマ〜〜〜
マイケル
マイケル
今日はソフトウェア設計の考え方について、
下記の書籍をベースにまとめてみました!

Clean Architecture 達人に学ぶソフトウェアの構造と設計 (アスキードワンゴ)

エレキベア
エレキベア
クリーンアーキテクチャ・・・
マイケル
マイケル
この本は40年以上プログラムを書き続けてきた筆者が
様々な形態のシステムに共通するアーキテクチャのルール、原則
についてまとめた本なんだ!
エレキベア
エレキベア
それはすごそうクマね・・・
マイケル
マイケル
システムに共通する考え方だから、WEBアプリやゲーム開発にも通用するし、
これから形が変化していっても役立つ知識が得られる本だと思うよ!
エレキベア
エレキベア
ちょっと気になってきたクマ・・
マイケル
マイケル
検索で辿りついたあなたもきっとソフトウェア開発で悩んでいるはず!
この記事も参考にして、気になったら書籍も読んでみてね!
エレキベア
エレキベア
クマ〜〜〜
スポンサーリンク

ソフトウェア設計の目的

マイケル
マイケル
まず、この本ではソフトウェア設計の目的を下記のように語っています。

ソフトウェア設計の目的は

「求められるシステムを構築、保守するために必要な人材を最小限に抑えること」である。
Clean Architecture

マイケル
マイケル
ソフトウェアが優れた設計になっていると、
開発も運用もスムーズになり、必要な人材やコストも最小限に抑える
ことができます!
エレキベア
エレキベア
確かにいざ言語化してみるとそうなるクマね
マイケル
マイケル
そしてそのような設計を行うための原則として、
下記のように記述されていました!

ソフトウェアはソフトでなければならない。
Clean Architecture

マイケル
マイケル
「ソフト」ウェアだけに、変化に柔軟でなければならない、
変更が容易なプログラムは長い目で見て利点がありますし、開発途中の変化にも対応することができます!
マイケル
マイケル
つまり目指すべきは変化に強いプログラムをつくること!
これを達成するための基本的な原則について紹介します!
エレキベア
エレキベア
なるほどクマ・・・!!
変化に強いというのがキーワードなんだクマ

SOLID原則

マイケル
マイケル
このような目的を踏まえた上で、下記を達成するために生まれたのがSOLID原則だ!
SOLID原則
  • 変化に強く、理解しやすい構造を作るための原則
  • 多くのソフトウェアシステムで利用できるための原則
  • 下記の5つの原則の頭文字を取っている
    ・単一責任の原則(SRP: Single Responsibility Principle)
    ・オープン・クローズドの原則(OCP: Open-Closed Principle)
    ・リスコフの置換原則(LSP: Liskov Substitution Principle)
    ・インターフェイス分離の原則(ISP: Interface Segregation Principle)
    ・依存関係逆転の原則(DIP: Dependency Inversion Principle)
エレキベア
エレキベア
SOLID原則・・・!
かっこいいクマ・・・!!
マイケル
マイケル
それじゃ1つずつ見ていこう!

単一責任の原則(SRP: Single Responsibility Principle)

単一責任の原則
  • モジュールを変更する理由はたったひとつだけであるべきである。
マイケル
マイケル
これは「どのモジュールも1つのことを行うべき」ということではなく、
「変更する理由が1つだけであるべき」ということです。
エレキベア
エレキベア
よくわからんクマ〜〜
マイケル
マイケル
例えば下記のようなEnemyクラスを見てみよう!
UntitledImage
↑複数の責務を負っている状態
マイケル
マイケル
これだとEnemyクラスの中で
・位置、回転情報の更新
・スコアの計算処理
・描画処理
大きく3つの責務を負っている状態だ。
マイケル
マイケル
これだとクラスが肥大化してしまうし、それぞれの修正が発生した場合にはマージ作業が必要になってしまう・・・
エレキベア
エレキベア
確かにやってることが多すぎる気がするクマ・・・
マイケル
マイケル
だからこの場合は責務ごとにクラスを分けてあげる方がよさそうだ。
その場合、Facadeパターンを使用することで呼び出し元を集結させることができるよ!
UntitledImage
↑責務ごとにクラスを分割した
エレキベア
エレキベア
これならそれぞれのクラスの修正が影響を受けなくなるクマね
マイケル
マイケル
まあこの例の場合は、そもそも位置更新や描画処理は共通処理として抜き出した方が良さそうだけどね・・・。
Unityではこれらはコンポーネントとして提供しているよ!

オープン・クローズドの原則(OCP: Open-Closed Principle)

オープン・クローズドの原則
  • 既存のコードの変更よりも新しいコードの追加によってシステムの振る舞いを変更できるように設計すべきである。
マイケル
マイケル
これは「既存のコードを変更せずに、拡張できるようにするべき」ということです。
エレキベア
エレキベア
なんとなく分かるような分からないようなクマ・・・
マイケル
マイケル
この原則はよく、

・拡張に対しては開いていて
・修正に対しては閉じている

と表現されているよ。


・拡張に対して開いている

→インターフェース等を用いて、機能が拡張できるように開いているべきである。


・修正に対して閉じている

→単一責任の原則でもあった通り各モジュールは一つの責務を保障しており、
機能追加のために責務を修正すべきではない。
→ただし、バグによる修正は発生する。

マイケル
マイケル
大体こんな感じのイメージだ!
これには先ほど出た単一責任の原則で責務ごとにクラス分割してコンポーネントにまとめ
後に出てくる依存性逆転の原則に沿って外部から隠蔽する必要があるよ。
エレキベア
エレキベア
機能拡張する際には修正じゃなく
追加や差し替えができるようになっているべきなのクマね

リスコフの置換原則(LSP: Liskov Substitution Principle)

リスコフの置換原則
  • 個々のパーツが交換可能となるようにすべきである。
マイケル
マイケル
これはオープンクローズドの原則とも似ているけど、例えば「基本クラスをサブクラスと入れ替えても正しく動かなくてはならない」とも言えます。
マイケル
マイケル
この例で有名なのが「四角形、長方形問題」です。
例えば下記のような四角形(RectAngle)クラスがあったとします。
UntitledImage
↑四角形クラス
マイケル
マイケル
このクラスの派生として長方形クラス(Square)を作成するのは適切でしょうか?
エレキベア
エレキベア
どちらも四角形だからいいんじゃないクマ?
マイケル
マイケル
よさそうに見えるけど、いざクラスを作った場合は
下記のようにメソッドが異なってしまうことになるんだ。
すなわち呼び出し元の処理を変えないといけず置換できないことから
この原則に違反していると言えるよ。
UntitledImage
↑長方形クラスは処理が異なってしまう
エレキベア
エレキベア
なるほどクマ・・・!!
マイケル
マイケル
この例を思い出して、置換できるように設計する必要があるね

インターフェイス分離の原則(ISP: Interface Segregation Principle)

インターフェイス分離の原則
  • 使っていないものへの依存を回避すべきである。
マイケル
マイケル
「各操作をインタフェースに分離する」ことで、再コンパイルや再デプロイが発生しないようにしましょう、ということです。
エレキベア
エレキベア
インタフェースを使うクマね
マイケル
マイケル
例えば、下記のように書くオペレーションから使用されるクラスがあったとしましょう。
UntitledImage
↑Crudクラスと各オペレーション
マイケル
マイケル
この場合は全てのオペレーションがCrudクラスに依存してしまっていて、
どれか一つの処理を修正したら全て再コンパイルしなければなりません。
マイケル
マイケル
そのため、下記のように各オペレーションでのみ使う処理になるようインターフェースを分離することで、それぞれの処理にのみ依存させることができます。
UntitledImage
↑各処理をインターフェースに分離
エレキベア
エレキベア
これならどれか一つの処理を修正しても
全て再コンパイルする必要もないクマね
マイケル
マイケル
これは極端な例だけど、設計する際には
不要な処理に依存していないかを常に意識する必要があります。

依存関係逆転の原則(DIP: Dependency Inversion Principle)

依存関係逆転の原則
  • 具象に依存せず、抽象を参照し依存するべきである。
マイケル
マイケル
最後は依存関係逆転の原則!
これは依存性を操作できるというオブジェクト指向のパワーを利用した原則だ!
エレキベア
エレキベア
依存性が逆転・・・?
一体どういうことクマ??
マイケル
マイケル
さっき出てきたインタフェース分離の原則を見ても分かる通り、
抽象クラスを使用すると依存の方向が逆になるんだ!
UntitledImage
↑依存性の矢印が抽象クラスに向いている
エレキベア
エレキベア
確かに矢印が逆になっているクマね
マイケル
マイケル
これを下記のように抽象クラスを参照するようにすることで、
下位レベル(詳細)のが、上位レベル(方針)に依存すべきというのがこの原則の意図なんだ。
UntitledImage
↑まとまりで考えると本来の依存とは逆になっている
エレキベア
エレキベア
なるほどクマ・・・
これが依存性を操作できるということなのクマね
マイケル
マイケル
ただ全てにこの原則を適用させることは難しいため、
満たしていない具象コンポーネントをなるべく少数に絞り込むことが重要になるよ。
マイケル
マイケル
また、デザインパターンとしてAbstract Factoryパターン
この原則を適用している例と言えるね!
UntitledImage
↑Abstract Factoryパターン
エレキベア
エレキベア
デザインパターンからも学べることがいろいろあるクマね

コンポーネントの原則

マイケル
マイケル
そしてここではあまり詳しく解説しませんが、
SOLID原則の他にコンポーネント設計に焦点を当てた原則も存在します。

コンポーネントの凝集性


・再利用・リリース等価の原則(REP)

→再利用の単位とリリースの単位は等価になる。


・閉鎖性共通の原則(CCP)

→コンポーネントを変更する理由が複数あるべきではない。


・全再利用の原則(CRP)

→使っていないクラスを持つコンポーネントに依存しないようにする。

REPとCCPは包含関係にあり、CRPとは相反する。
これら3つの原則のバランスをとるのが重要である。

コンポーネントの結合


・非循環依存関係の原則(ADP)

→コンポーネントの依存グラフに循環依存があってはいけない。


・安全依存の原則(SDP)

→安定度の高い方向に依存すること。


・安定度・抽象度等価の原則(SAP)

→コンポーネントの抽象度は、その安定度と同程度でなければならない。

エレキベア
エレキベア
ここもかなり重要な原則クマね

クリーンアーキテクチャ

マイケル
マイケル
これらの原則を踏まえた上で著者が提唱しているのが、
かの有名なクリーンアーキテクチャです!
CleanArchitecture↑かの有名な図
エレキベア
エレキベア
この図は見たことがあるクマ〜〜〜
マイケル
マイケル
円の外側が仕組み、内側が方針で
下位レベル(仕組み)が上位レベル(詳細)に依存するように設計する、というのが根本の考え方です。
マイケル
マイケル
このアーキテクチャの詳細が気になった方は書籍を読んだり
ネットで調べてみて下さい!

設計上の注意点

マイケル
マイケル
その他、特に書籍の中で響いた設計上の注意点について
いくつか紹介します!

依存性は下位(詳細)→上位(方針)に向かっていなければならない。
Clearn Architecture

マイケル
マイケル
これはこれまでにも何度も出てきたワードで、
下位から上位に依存するよう意識して設計を行う必要がある、ということですね。
エレキベア
エレキベア
心得たクマ・・・

データベース、ウェブ、フレームワークは詳細である。
Clearn Architecture

マイケル
マイケル
こちらはあまり考えてなかった方も多いのではないでしょうか?
設計をする際にまずDBやフレームワークから決めてしまうことが多いと思いますが、
これらは本来詳細で差し替え可能となっていることが望ましいです。
マイケル
マイケル
そしてこれらになるべく依存しない設計というのがよいでしょう・・・
エレキベア
エレキベア
確かに依存してしまうとずっと変えられなくなってしまうクマ・・・

フレームワークを使用することは結婚である。
Clearn Architecture

マイケル
マイケル
先ほどの話と被りますが、フレームワークは詳細です。
そしてフレームワークの機能に依存してしまうと一生使い続けなくてはならなくなるため、ある意味 結婚する とも例えられます。
マイケル
マイケル
著者はこのことについて、「フレームワークに出会ったらすぐに結婚しようとしてはいけない。」と述べています。
何も考えずに使用するのでなく、一旦結婚してもいいのか?を考えるようにしましょう・・・。
エレキベア
エレキベア
結婚・・・・!!恐ろしいほどの依存クマ・・・・
マイケル
マイケル
ちなみにUnity等のゲームエンジンを使用することも依存していると言えるんだぜ・・・
エレキベア
エレキベア
気付かぬ内に家族になっていたクマか・・・

おわりに

マイケル
マイケル
というわけで今回は設計に関するお話でした!
どうだったかな?
エレキベア
エレキベア
中々難しいクマがまずは「変化への適応」「上位へ依存する」とか
出てきたキーワードを意識して開発してみようと思ったクマ
マイケル
マイケル
そうだね、理論だけ知っていても中々できないだろうし
実際にたくさん書いていくしかなさそうだね
マイケル
マイケル
とりあえず今後は下記書籍を読んで
実際にSOLIDコードを書く練習をしてみることにするよ・・・

Adaptive Code ~ C実践開発手法 第2版

エレキベア
エレキベア
この本も面白そうクマね
でも高いクマ・・・・
マイケル
マイケル
高いね・・・!!
エレキベア
エレキベア
それほどの覚悟があるのか試されるクマ
マイケル
マイケル
それでは今日はこの辺で!
アデュー!!
エレキベア
エレキベア
クマ〜〜〜〜〜

【ソフトウェア開発】設計の目的とSOLID原則についてまとめる【クリーンアーキテクチャ】 〜完〜

コメント