れすぽんしびりてぃ
何らかの状態を残すと何故、SingleResponsibilityに反するのか、そこがよく理解できていません。
加えて、「ガード節による入れ子条件記述の置き換え」というリファクタリングを適用すると、
メソッドの動作仕様には変化ないのに、なぜ、SingleResponsibilityに反してしまうのか、
という点が疑問です。
ものすごく簡単に書くと↓のどちらかって事だと思うのですが、このレベルではSingleResponsibilityは関係ないです。なぜなら十分に単純なので何かかが埋まっている可能性がないからです。もし、何かが埋まっているようならその実装は2つ以上に分けられる可能性が高いのでSingleResponsibilityに違反している可能性も高いということです。
public boolean hoge() { boolean result = false; if(someState) { result = true; } return result; } public boolean hoge() { if(someState) { return true; } return false; }
A.全ての責任は私にあります。
B.部下 needChange() がやったことです。私には責任はありません。
これはたぶんプログラムの各要素が持つべき責務と、問題が発生した場合の原因と影響範囲を混同されてませんか?
一般的に責務(Responsibility)という言葉がデザインパターン周りでしか使われないので、オブジェト単位に範囲を絞って考えがちですが、プログラムの要素の全てが何かしらの責務を持っています。
責務を持っているということは責務を果たすべき相手がいるということなので、例えばメソッドのローカル変数はメソッドに対して一定の責務を持ちますし、Privateなメソッドはそれを呼ぶ側のメソッドに対して責務を果たすことになります。
action()メソッドの外側から見てバグのせいでaction()メソッドの責務が果たされていなかったのならAです。Bの表現はaction()メソッドが責務を果たすべき相手を無視しているのであってはならないことです。せめて「needChange()に問題があったせいで、自分の責務が果たせなかった」という表現になると思います。
この二つはどちらを使えばいいというのもではないです。
関係を調整するときにはインターフェースだけを考えて(Aの表現)、実装をしている場合にはインターフェースを外側の壁として意識ししつつどう実現するかを考える(Bの表現)というのを、意識的にスイッチさせながら実装するのがオブジェクト指向プログラマです。(これを無意識にしかやってないのは「えせ」です。)
SingleResponsibilityはプログラムの全ての要素に対して「単純であれ」というメッセージを送っているのだと理解しています。複雑なものを単純にするには「分割して関係を整理する」というのが基本的な手法です。
ネストの浅い箇所で途中でreturnしている場合はreturnの後で分割が可能であったり、ネストの深いところでreturnしている場合は何かしらの状態が埋まっているので、その状態を抽出すれば分割が可能になります。
ですから単純な状態さえ保っていれば"途中でreturn"は自然になくなってしまうわけです。