Single Responsibility Principle
クラスを変更する理由はひとつ以上存在してはならない
クラスをどう定義するか、の原則です。
SOLID原則と呼ばれる、主要5原則のひとつ。
- Single Responsibility Principle 単一責任原則
- Open Closed Principle 開放閉鎖原則
- Liskov Substitution Principle リスコフ置換原則
- Interface Segregation Principle インターフェース分離原則
- Dependency Inversion Principle 依存性逆転原則
どんなときに使える?
メソッド数が恐ろしく多いとき
〇〇クラス、メソッド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のスキーマも決めるべきでない。であるなら、その処理は従業員クラスに実装すべきではないのです。
考え方のひとつになるのでないでしょうか。
- Single Responsibility Principle 単一責任原則
- Open Closed Principle 開放閉鎖原則
- Liskov Substitution Principle リスコフ置換原則
- Interface Segregation Principle インターフェース分離原則
- Dependency Inversion Principle 依存性逆転原則