【SOLID】単一責任原則~変更する理由は、ただひとつだけ

single-responsibility-principle
単一責任原則

Single Responsibility Principle

クラスを変更する理由はひとつ以上存在してはならない

クラスをどう定義するか、の原則です。

SOLID原則と呼ばれる、主要5原則のひとつ。

SOLID原則
目次

どんなときに使える?

メソッド数が恐ろしく多いとき

新人くん

〇〇クラス、メソッド5個分の実装終わりましたー

イケイケくん

〇〇クラスのメソッド10個追加完了っす!

リーダーさん

なんかこのクラス、メソッド100個くらいあるんだけど…

プログラム開発のとき、なんだかやたら大きいクラスができたりします。メソッドがなん十個もあったり、1万行くらいのコードになったり…

クラスを分けておかないと、今後の開発で支障が出そうです。でもどう分ければいいんでしょう?

クラス分割の指針=変更理由はひとつだけ

単一責任原則は、クラスをどう分割するかの指針になります。

それは「そのクラスの変更理由が1つだけ」になるよう、分割することです。

どういうこと?具体的な例で考えましょう。

従業員クラスの例

従業員のデータを管理するクラスを考えます。

// 従業員クラス
public class Employee {
  // 給与計算を行う
  public Money calculatePay() {
    ...
  }
  // 作業時間報告書を出力する
  public String reportHours() {
    ...
  }
  // データベースに保管する
  public void save() {
    ...
  }
}

このクラスには3つのメソッドがあります。

従業員クラスのメソッド
  • calculatePay 従業員の給与を計算します
  • reportHours 従業員の作業報告書を出力する
  • save 従業員に関する情報をデータベースに保管します

いずれも従業員のデータを操作するメソッドなので、従業員クラスにあるのが望ましい…本当でしょうか?

変更理由が多いクラス

問題なのは、3つのメソッドが、まったく違った理由で変更される可能性があることです。

メソッドの変更理由
  • calculatePay 給与計算に関わるルールが変わったら、修正が必要
  • reportHours レポートのフォーマットが変わったら、修正が必要
  • save データベーススキーマが変わったら、修正が必要

これらの変更は、おそらく別々のタイミングで発生するでしょう。

3つも変更理由がある従業員クラスは、非常に不安定な存在となります。

従業員クラスを分割する

クラスを分割したほうがよさそうなのは分かりました。ではどう分割すればよいでしょう?

そう、変更される可能性ごとに分けるのです。

// 従業員クラス
public class Employee {
  // 給与計算を行う
  public Money calculatePay() {
    ...
  }
}
// 従業員報告書クラス
public class EmployeeReporter {
  // 作業時間報告書を出力する
  public String reportHours(Employee e) {
    ...
  }
}
// 従業員リポジトリクラス
public class EmployeeRepository {
  // データベースに保管する
  public void save(Employee e) {
    ...
  }
}

これで各々のクラスで、変更理由がひとつになりました。

神クラス(God Class)に立ち向かえ!

これが「従業員管理システム」だとすれば、従業員クラスはまさに根幹となるクラスです。

転勤する、昇格する、データバックアップする、リストプリントする。。どんな処理でも従業員に関する処理です。ほうっておくとすべて従業員クラスのメソッドになります。

このような、あまりにも多くを知り、あまりにも多くを行うクラスを、神クラス(God Class)といいます。

神クラスは、保守、拡張、使用、テストなど様々な局面で困難をもたらします。責任が単一となるよう分割しましょう。

まとめ

とはいっても、こと「責任」の考えは人によって違います。話はそれほど簡単になりません。

ひとつ考えかたがあります。責任を考えるとき、逆に「このクラスは、なにに責任を持たないのか?」と考えるのです。

従業員クラスは報告書フォーマットに責任は持たないし、DBのスキーマも決めるべきでない。であるなら、その処理は従業員クラスに実装すべきではないのです。

考え方のひとつになるのでないでしょうか。

SOLID原則
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次