SOLID原則とは?Swift(iOS)で理解する設計開発思想

この記事からわかること
- SOLID原則とは?
- ソフトウェア開発における設計思想
- Swift/iOSで例える各原則の役割
- Single Responsibility Principle:単一責任の原則とは?
- Open-Closed Principle:開放・閉鎖の原則とは?
- Liskov Substitution Principle:リスコフの置換原則とは?
- Interface Segregation Principle:インターフェース分離の原則とは?
- Dependency Inversion Principle:依存性逆転の原則とは?
index
[open]
\ アプリをリリースしました /
今回はオブジェクト指向プログラミングにおける開発設計思想の1つである「SOLID原則」についてSwift(iOS)と絡めながらまとめていきたいと思います。
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
おすすめ記事:【Swift】MVVMアーキテクチャとは?ViewModelの役割
SOLID原則とは?
そもそも「SOLID原則」とはオブジェクト指向型の言語を用いたソフトウェア開発において、拡張性や保守性を高めるために利用されるガイドラインみたいなものです。SOLID原則は以下の5つの原則で構成されています。
- Single Responsibility Principle:単一責任の原則
- Open-Closed Principle:開放・閉鎖の原則
- Liskov Substitution Principle:リスコフの置換原則
- Interface Segregation Principle:インターフェース分離の原則
- Dependency Inversion Principle:依存性逆転の原則
アメリカのロバート・C・マーティン (Robert C. Martin) によって2000年代初頭に書かれた著書「Agile Software Development: Principles, Patterns, and Practices」の中でSOLID原則を提唱されました。
ここからはそれぞれの役割をSwift(iOS)での例に例えながら見ていきたいと思います。またここではクラスを例に見ていきますが、原則に当てはめるべきはクラスだけでなく、メソッドやプロパティなども含みます。
Single Responsibility Principle:単一責任の原則
1つのクラスは単一の責務を持つべき
これはクラスに持たせるべき責務を考えるための原則です。ここで言う責務とはクラスが持つ役割や機能(API)のことであり、クラスに対して責務は1つであるべきだと提唱しています。
例えばユーザー情報を表すクラス(Userクラス)にユーザー情報を管理させる(ユーザーの追加など)のはこの原則に反しています。なのでユーザーを管理するためのUserManager
クラスなどを定義することでそれぞれの責務を明確に切り分けることが大切なようです。
意識するべきは定義したクラス名以上の役割をクラスに持たせないようにすることだと思います。
Open-Closed Principle:開放・閉鎖の原則
拡張しやすく、変更しにくい設計にするべき
この原則はクラスの機能に対する原則です。クラスに対して新しい機能を追加することには開放的であり、機能自体を変更することには閉鎖的であるべきと提唱しています。
クラスの機能(メソッドなど)の動作自体を変更するとアプリ全体に影響を及ぼす可能性があり、改修する部分が膨大になってしまう可能性があります。機能を追加するだけであれば影響を与える範囲は少なくすみます。
Liskov Substitution Principle:リスコフの置換原則
サブクラスはスーパークラスを置き換えても問題無いようにするべき
この原則はクラスのスーパークラスとサブクラスの継承に関する原則です。サブクラスを利用している部分はスーパークラスでも正常に動作できるようにすることで、正しい継承(仕様)であることを保証させることごできると提唱しています。
ちなみにリスコフとはこの原則の提唱者であるアメリカのコンピュータ科学者、Barbara Liskov(バーバラ・リスコフ)の名前に由来しているようです。
スーパークラスとしてUser
を定義しておき、継承したサブクラスを2つ用意します。そしてそれらを扱うUserManager
クラスはUser
型を操作するクラスとします。
これによりUserManager
クラスはRegularUser
型もPremiumUser
型も意識することなくUser
型として操作することが可能になります。
Interface Segregation Principle:インターフェース分離の原則
使用しないインターフェース(メソッドやプロパティなど)を持つクラスは設計上の問題があるとされ分離するべき
この原則はクラスに持たせるべき役割を精査するための原則です。1つの大きなクラスが持つインタフェースを小さなクラスに分割することで必要となるインターフェースだけを保持したクラスになるようにするべきと提唱しています。
細かく切り分けることで再利用性が向上するだけでなく、クラス間の依存性の減少や、テストやメンテナンスの容易性が上がりやすくなります。
Dependency Inversion Principle:依存性逆転の原則
上位クラスは下位クラスに依存してはならず、抽象に依存するべき
この原則はクラスが依存するべき先を示すための原則です。クラスAとクラスBがあるとき、この両者に依存関係を持たせるべきではなく、抽象(Swiftでいうプロトコルなど)として定義された型に対して依存させるべきと提唱しています。
これまでのコードにも既に登場してますが、クラスA変更した際に、クラスBまで変更するのは良くないので、両者が扱うべき抽象を用意しようねって感じですかね。
UserProtocol
プロトコルを定義したことでUserManagerクラスは、UserProtocol型(抽象)に依存させることができ、UserProtocol
を採用しているすべてのオブジェクトを追加/削除できるようになります。
ご覧いただきありがとうございました。