ロバート・C・マーティンによると、SRPは次のように述べています:
classを変更する理由は複数あるべきではありません。
ただし、彼の著書Clean Codeの第3章:関数では、次のコードブロックを示しています。
public Money calculatePay(Employee e) throws InvalidEmployeeType {
switch (e.type) {
case COMMISSIONED:
return calculateCommissionedPay(e);
case HOURLY:
return calculateHourlyPay(e);
case SALARIED:
return calculateSalariedPay(e);
default:
throw new InvalidEmployeeType(e.type);
}
}
そしてこう述べる:
この機能にはいくつかの問題があります。まず、規模が大きく、新しい従業員タイプが追加されると、規模が大きくなります。第二に、それは明らかに複数のことを行います。第3に、変更する理由が複数あるため、単一責任原則(SRP)に違反します。 【重点鉱山】
まず、SRPはクラスに対して定義されていると思いましたが、関数にも適用できることがわかりました。次に、この関数に変更する理由が複数あるのはどうしてですか?私はそれが従業員の変更のために変化しているのを見ることができるだけです。
単一責任原則の詳細を見逃したことがあるのは、「変更の理由」はユースケースアクターによってグループ化されていることです(完全な説明 here を参照してください)。
したがって、あなたの例では、新しいタイプのEmployeesが必要な場合はいつでも、calculatePay
メソッドを変更する必要があります。あるタイプの従業員は別のタイプの従業員とは何の関係もない可能性があるため、変更をシステム内の異なるユーザーグループ(またはユースケースアクター)に影響するため、それらをまとめると原則に違反します。
ここで、原則が関数に適用されるかどうかについて説明します。1つのメソッドのみに違反がある場合でも、複数の理由でクラスを変更しているため、それでもSRPの違反です。
マーティン氏がSRPを関数に適用すると、暗黙的にSRPの定義が拡張されます。 SRPはOO固有の一般的な原則の言葉遣いであり、関数に適用することは良い考えであるため、問題はありません(ただし、明示的にそれを定義)。
変更する理由は1つもないと思います。また、SRPを「責任」または「変更する理由」の観点から考えることが役立つとは思いません。基本的にSRPが達成しているのは、ソフトウェアエンティティ(関数、クラスなど)が1つのことを実行し、それを適切に実行することです。
私の定義を見ると、SRPの通常の文言よりも曖昧ではありません。 SRPの通常の定義に伴う問題は、SRPが曖昧すぎるということではなく、本質的に曖昧なものについて具体的に表現しようとすることです。
calculatePay
の機能を見ると、明らかに1つのこと、つまり型に基づくディスパッチを行っています。 Javaには型ベースのディスパッチを行う組み込みの方法があるため、calculatePay
は洗練されておらず、慣用的ではないので、書き直す必要がありますが、上記の理由ではありません。
ページ176、第12章:出現、というタイトルのセクション最小限のクラスとメソッドこの本は、次のように述べることにより、多少の修正を提供します。
クラスとメソッドを小さくするために、非常に多くの小さなクラスとメソッドを作成する可能性があります。したがって、このルールは、関数とクラスの数も少なくすることを示唆しています。
そして
クラス数とメソッド数が多いのは、無意味な独断の結果である場合があります。
明らかに、彼はSRPをフォローして上記のcalculatePay()
のような無害な小さなメソッドを完全に分解する際の独断性について話している。