if-elseとガード節の(個人的な?)使い分け
2021.6.19
ケースバイケースなので、あくまで一つの考え方として。
はじめに結論
対称性のある正常パターンの条件分岐 → if else
不正パターンを弾くための条件分岐 → ガード節
例
if-elseを使うパターン
- 男性 or 女性
- 成人 or 未成年
- 小学生 or 中学生 or 高校生
のような条件が対象的で、正常パターン同士の分岐にはif else
が適している
→逆に考えれば、if else
を使う事によって、正常パターンについて分岐をしているという意思表示になる
例えば年齢ごとに飲めるドリンクを決めるような処理を考えると、
if age.over_20?
# 成人はビールとジュース
man.drink('beer', 'juice')
else
# 未成年はジュース
man.drink('juice')
end
ここでmanは成人でもOKだし、未成年でもOK。
if else
を使うことで、条件に対称性があることと、どれも正常パターンであることを表現できる。
ガード節を使うパターン
- 入力が特殊・不正値
- 不正なパターンの分岐
のような不正なケースを除外するための分岐にはガード節が適している。
先程のコードに、age
がnilの場合を追加してみる。
return if age.nil?
if age.over_20?
# 成人はビールとジュース
man.drink('beer', 'juice')
else
# 未成年はジュース
man.drink('juice')
end
ガード節を使うことで、不正なパターンであることを表現できる。
あえて読みづらく書くと。。。
メソッド全体をif分で括ってしまうパターン
if age.present?
if age.over_20?
# 成人はビールとジュース
man.drink('beer', 'juice')
else
# 未成年はジュース
man.drink('juice')
end
end
ガード節の説明にありがちなやつ。
デメリット
- if条件が増えるたびにネストが深くなる
- ネスト最深部のコードを読む頃には、最初のif条件を忘れていることも
age
がnilの場合は、ネストの条件を判定する必要がないので、パフォーマンス的も悪い(言語による)
全部ガード節にするパターン
return if age.nil?
return man.drink('beer', 'juice') if age.over_20?
man.drink('juice')
end
コード量自体は一番短くてスッキリ見える。
デメリット
- 不正ケース1つと、正常ケース2つの条件だが、ぱっと見は不正ケース2つ、正常ケース1つに見える
- それか、正常ケース3パターンにも見える
最後に
ガード節はリファクタリングの第一歩としては使いやすいし、何に対しての条件分岐かを意識するとさらに良いコードを書いていけそう。
このあたりにちゃんとした解説があるので、気になる人は読んでみるといいかも。
- リーダブルコード 第7章
- リファクタリング―既存のコードを安全に改善する― 第9章