💭
SOLID原則のS:単一責任の原則を噛み砕いて理解する
はじめに
Clean Architectureを読み進める中で、抽象的でピンと来なかったので自分なりに噛み砕いてみる。
単一責任の原則(Single Responsibility Principle)の定義
Clean Architectureでは、単一責任の原則を以下のように言い換えて説明している。
- モジュールを変更する理由はたった一つだけであるべきである
- →モジュールはたったひとりのユーザーやステークホルダーに対して責務を負うべきである
- →モジュールはたったひとつのアクターに対して責務を負うべきである(アクターとは、変更を望む人たちをひとまとめにしたグループ)
ここでいうモジュールはソースファイルとのこと。
違反している例
症例
給与システムにおけるEmployeeクラス。このクラスは単一責任の原則に違反している。
- calculatePayメソッドは、経理部門が規定する。報告先はCFO
- reportHoursメソッドは、人事部門が規定して使用する。報告先はCOO
- saveメソッドは、データベース管理者が規定する。報告先はCTO
これら3つのメソッドがひとつのクラスにまとめられていると、全てのアクターを結合することになって、ある変更が他のアクターに影響を及ぼす可能性がある。
よって、アクターごとにコード(クラス)は分割すべき。
解決策
解決の仕方はいくつかあるが、一番わかりやすいのはデータを関数から切り離すという方法。
例えば、3つのクラスからEmployeeDataクラスを使うようにする。
がその場合、「開発者が3つのクラスをインスタンス化して、追跡しなければいけない点が弱点」とのこと。
それを解決するために一般的に使われるのが、Facadeパターン。
EmployeeFacadeに含まれるコードはごくわずかで、その責務は実行したいメソッドを持つクラスのインスタンスを生成して、処理を委譲するだけ。
重要なビジネスルールはデータの近くにおいておきたいと考える場合、元のEmployeeクラスに重要なメソッドだけを残し、重要ではないメソッドを呼び出すFacadeとして使えばいい。
疑問
Q: 「開発者が3つのクラスをインスタンス化して、追跡しなければいけない点が弱点」ってどういうこと?
- その後の文脈的に、どのクラスを触るにしても3つ全てのクラスの詳細(実装)を知っていなきゃいけないのが弱点という意味っぽい
- そのために、実装の詳細を知らなくて良いように、「窓口」を用意するといいとのこと。(=いわゆるUseCaseかな)
- 窓口は単一責任なのか...?? 窓口にいくつか役割がありそう?
- この辺は読み進めて考える
Q: クラス名は変更する理由とその抽象度を表してる?
- クラス名を適切な抽象度にしないと「変更する理由」がぶれそう
- 今わける必要がある抽象度にしておいて、何かメンバーを増やしたくなった時に、より具体で関心ごとが分かれそうなら分ける?
- 追加したい関数はどんな関数? → 「〇〇を××する関数」と答えたとする
- 〇〇がクラス名であるべきで、××が関数名であるべきな気がする
- 「〇〇の△△を××する関数」であった場合、〇〇の△△というクラス名で切り出すべきかもしれない
Discussion