状況
- メソッド内に、正常ルートが不明確な入れ子の条件付き振る舞いがある
double getPayAmount() { double result; if (_isDead) result = deadAmount(); else { if (_isSeparated) result = separatedAmount(); else { if (_isRetired) result = retireAmount(); else result = normalPayAmount(); } } return result; }
「正常な」という点がポイントです。「正常」と「異常」が区別されるということは、
それらの分岐に至る頻度が等しくはない、ということです。
対処
- 特殊ケース全てに対してガード節を使う。
double getPayAmount() { if (_isDead) return deadAmount(); if (_isSeparated) return separatedAmount(); if (_isRetired) return retireAmount(); return normalPayAmount(); }
分岐の頻度が等しい場合には、条件記述の出口を一つとした入れ子の分岐が適当ですが、
そうでない場合には、入れ子ではなく、逐次returnするような条件記述が適当です。
このような分岐のチェック方法を、しばしば「ガード節」と呼びます。
メリット
分岐が読みやすくなる
ガード節のルールが共有されている場合には、条件分岐の頻度が等価でないことが読み手に伝わる
手順
else部の中で入れ子になっている場合
条件判定をガード節に置き換える
- ガード節は、returnするか例外を投げるかのいずれかになる
置き換える度にコンパイルしてテストする
if部の中で入れ子になっている場合
条件記述部の内容を逆にする(&&を||に、>を<=に、というように)
条件判定をガード節に置き換える
- ガード節は、returnするか例外を投げるかのいずれかになる
置き換える度にコンパイルしてテストする
一時変数を削除して値に置き換えられるか、検討する
楽天ブックス: リファクタリング新装版 - 既存のコードを安全に改善する - マーチン・ファウラー - 9784274050190 : 本