単一責任の原則(SRP)

SOLID原則のひとつ、単一責任の原則。
英語でいうとSingle Responsibility Principle、略してSRPと呼ばれている原則です。

単一責任の原則

関数やクラスは一つの責任だけを持つべきという原則です。
何に対しての責任かというと、そのシステムを使うユーザやステークホルダーに対して。
Clean Architectureではこの対象をまとめて「アクター」という言葉で表現しています。

この言葉を使うと先ほどの説明は「クラスは一つのアクターに対して責任を持つべき」と言い換えられます。

もう少し詳しく今度はコードで見ていきます。 以下のようなEmployeeというクラスがあったとします。

class Employee {
    /**
     * 経理部門が使うデータ
     */
    public function calculatePay()
    {
    }
  
    /**
     * 人事部門が使うデータ
     */
    public function reporyHours()
    {
    }
  
    /**
     * DB管理者が使うもの
     */
    public function save()
    {
    }
}

このクラスはSRPに違反しています。

複数のアクターに対してのメソッドが存在しており、複数の理由からこのクラスを改修する必要があり不安定なクラスになっています。
もし各メソッドが共通のメソッドを使っていたとしたら、共通メソッドに修正を入れた場合に他のメソッドにも影響が出てきてしまうでしょう。
さらに経理部門や人事部門、DB管理者に向けての開発チームが分かれていた場合、マージのコストや思いがけないコンフリクトも発生していくかもしれません。

ではどうするか?

解決策としては、それぞれのメソッドを別のクラスに切り出すことです。

// 例えばcalculatePayメソッドをクラスに切り出した場合
class PayCalculator {
    public function calculatePay()
    {
    }
}

あるいは、EmployeeクラスはFacadeとして扱い、実際の処理は別クラスに委譲するというやり方もあります。

いずれにせよ、アクターに対する責務を一つだけにしていくことでクラスや関数は凝集度の高いものになっていくでしょう。

単一責任の原則を守ることで、変更に強い設計に繋がっていきます。

コンウェイの法則

ちょっと余談。

Clean Architectureでは、「単一責任の原則はコンウェイの法則に帰結する」と書かれています。

コンウェイの法則とは、メルヴィン・コンウェイという方が生み出した法則です。

システムを設計する組織は、その構造をそっくりまねた構造の設計を生み出してしまう

これは実際に自分も経験しています。
当時いた組織はこの法則の通り、開発チームごとにシステムが独立して分かれている状態でした。
チームが機能ごとに分かれていたこともあって、わざわざチームをまたいで機能を連結してシステムを設計するメリットがなかったためです。

単一責任の原則を適用していくと、アクターごとにクラスが分かれていくことになります。
このアクターごとで組織が分かれていた場合、アーキテクチャは自然と組織に沿ったものになっていきます。
これがコンウェイの法則に帰結すると言っている理由なのかなと思います。