【SOLID原則】単一責任の原則

# はじめに
こんにちは！ちびまろです。
SOLID原則(後述)について、**全５回**に分けて紹介していければと思っています。

# 前提条件
この記事を読むにあたり、「クラス・メソッドの意味と基本的な使い方を知っている」レベルであればスムーズに理解することができると思います。

# SOLID原則とは
さてみなさん、<font color="red">**SOLID原則**</font>について聞いたことはありますか？
恥ずかしながら私は最近耳にしました😅
きっかけは[@baby-degu(baby degu)](https://qiita.com/baby-degu)さんのこちらの投稿。

https://qiita.com/baby-degu/items/d058a62f145235a0f007

私個人、設計周りを勉強してこなかったのもそうですが、何よりも耳にしたことがないことに驚いたので早速調べてみました。

>ソフトウェア工学の用語であり、特にオブジェクト指向で用いられる五つの原則の頭字語である。ソフトウェア設計をより平易かつ柔軟にして保守しやすくすることを目的にしている。その特徴はインターフェースを仲介にしての機能の使用と、インターフェースによる機能の注入である。
>アメリカのソフトウェア技術者ロバート・C・マーティン（英語版）が提唱していた数々の設計原則の中からチョイスされたものである。
[Wikipedia](https://ja.wikipedia.org/wiki/SOLID)


簡単に言うと、<INS>**オブジェクト指向プログラミングとソフトウェア設計のための５つの設計原則**</INS>のことです。
「オブジェクト指向に乗っ取ったシステムはこうやって作るべきだよね。こう書くべきだよね。」を決めたルールブックのようなもの。だと私なりに落とし込みました。

色々なサンプルコードを読みつつ上記のイメージがしっくりきたので**あくまで**イメージだと理解した上で読んでいただけると幸いです。

五つの原則は以下の通りです。
 1. 単一責任の原則(single-responsibility principle)
 2. 開放閉鎖の原則（open / closed principle）
 3. リスコフの置換原則（Liskov substitution principle）
 4. インターフェース分離の原則(interface segregation principle)
 5. 依存性逆転の原則（dependency inversion principle）


その中でも今回はSOLID原則の中の一つである「S」にあたる<font color="red">**単一責任の原則**</font>について説明します。

# 単一責任の原則（Single Responsibility Principle）
正直「単一責任の原則とか言われても～」って感じですよね。

私も最初はそうでした。

でも安心してください。中身は非常にシンプルです。

そこで少しでも理解が深まるよう、単一責任の原則の説明をしたのちに「<INS>原則に準拠したコード</INS>」と「<INS>原則に反したコード</INS>」について説明しますね。

単一責任の原則とは、**1つのクラスに対して１つの責任だけを持つべきである**という概念です。

実際のコードを用意したため、それぞれ比較しつつ、実際に書きながら一緒に学んでいきましょう。

## 単一責任の原則に反したコード
同じUserクラスの中で、「ユーザ情報関連」「ログイン関連」「出力関連」と役割の異なるメソッドが`User`という１つのクラスに集約されています。
これでは`Userクラス`が何の役割を担っているのか。つまり、どのような責務を担当しているのかが分かりません。

```php
class User{

  private getUserName;
  private getEmail;
  private getPassword;

  // ユーザー名を取得
  public function getUserName(){
    return $this->userName;
  }

  // Eメールを取得
  public function getEmail(){
    return $this->getEmail;
  }

  // パスワードを取得
  public function getPassword(){
    return $this->getPassword;
  }

  // ログイン
  public function login(){
    // 省略
  }

  // ログアウト
  public function logout(){
    // 省略
  }

  // Json形式の出力メソッド
  public function exportJson(){
    // 省略
  }
}
```


そこで出てくるも・の・こ・そ・が！！！
はい〜！そうです！

## 原則に準拠したコード
ちゃんと役割ごとにクラスを分けよう！という考えです。
各クラスごとに明確な役割を振り分けてあげることで、今後修正する際の影響範囲を小さくすることができます。

原則に準拠することで、全部で３つのクラスに分けられました！
```php

// ユーザ情報に関するクラスで１クラス目
class User{

  private getUserName;
  private getEmail;
  private getPassword;

  // ユーザー名を取得
  public function getUserName(){
    return $this->userName;
  }

  // Eメールを取得
  public function getEmail(){
    return $this->getEmail;
  }

  // パスワードを取得
  public function getPassword(){
    return $this->getPassword;
  }

}

// 認証（ログイン・ログアウト）に関するクラスで２クラス目
class Auth{


  public function login(){
    // 省略
  }

  public function logout(){
    // 省略
  }

}

// 出力に関するクラスで３クラス目
class Output{

  // Json形式の出力メソッド
  public function exportJson(){
    // 省略
  }

}
```


### 単一責任の原則に従うことによる主なメリット
色々メリットがありますが、厳選して３つご紹介します。

#### 再利用性の向上
一つの特定の機能に焦点を当てることで、他のコンポーネントやアプリケーションでも再利用しやすくなります。

#### テストの容易さ
単一責任を持つクラスは、テストコードを書く形式のテストが行いやすくなります。
特定の機能に特化していることで、他の機能やクラスへの影響を感じることが少ないです。
また、少ないテストケースで網羅的にテストをすることができます。


#### バグの減少
責任が明確に分離されていることで、バグが発生しにくくなります。
一つのクラスに複数の責任がある場合、１行の修正で意図しないデグレを発生させてしまう可能性が高まります。


# さいごに
最後まで読んでいただきありがとうございました！
SOLID原則のうちの一つである**単一責任の原則**は理解できましたか？

もしまだ難しいと感じた方がいる場合は、コメントいただけると嬉しいです！
時間がある時に何かより良い伝え方がないか考えてみます！