Rubyにおけるunlessとコードの読みやすさについて

こんにちは、hachi8833です。 状況や好みによって異なりますが、条件分岐が二重否定の形になると、一般にコードが読みにくくなる傾向があります。 unlessはうまく使えば読みやすいコードを書くときに役立ちますが、unlessが二重否定を形成するとかえって読みにくくなることもあります。三重四重は言わずもがなですね。 unless と ||の組み合わせは避けよう unlessの是非は好みが分かれることが多く、よく議論のネタになりますが、少なくともunlessと||の組み合わせは苦情が出やすいので避けましょう。 unless obj1.blank? || obj2.blank? 言葉で書けば「obj1とobj2のどちらもblankでないなら」となります。コーディング前にこのような表現で考えるのはよくあることですが、それをそのままロジックに落としこむと上のようなコードになってしまいます。 .blank?と逆の.present?が使えるなら、ド・モルガンの法則(後述)を活用して次のように書き換えると、ぐっと目に優しいコードになります。 if obj1.present? && obj2.present? 言葉で書けば「obj1とobj2が両方とも存在すれば」となり、こちらも素直な表現になります。 not演算子「!」の混用は避けよう unless条件の中でnot演算子!が使われると、二重否定が発生して読みにくくなるので、避けましょう。 unless !obj1.blank? #=> 読みにくい if obj1.blank? #=> 読みやすい unlessに限らず、複数条件の一部でnot演算子!が使われると読みにくくなります(部分否定)。 .blank?→.present?のような対義語メソッドに置き換えるなどして、not演算子!を含まない表現にすることで、読みやすくなります。 if obj1.blank? && !obj2.blank? #=> 読みにくい unless obj1.blank? && !obj2.blank? #=> さらに読みにくい if obj1.blank? && obj2.present? #=> 比較的読みやすい 参考: ド・モルガンの法則 C言語などプログラミング言語の記号を使って書けば、P, Q がどんな式であろうと !(P || Q) == !P && !Q !(P && Q) == !P || !Q が成立するということである。 Wikipedia: ド・モルガンの法則 「命題の対偶は常に真である」と並んで、安心して使えるロジックですね。 unless はシンプルに 条件が1つで、かつelse文を使わない、シンプルな条件判断であれば、unlessを使うことで視認性が向上します。 unless obj1.member? 何かする end 実行するコードが1行だけなら、後置のunlessにすることをおすすめします。 Club.alert unless obj1.member? unless A && B はどうか 「unless A && Bはまだ許せるけどunless A || Bは混乱するから嫌だ」という意見がいくつか出ました。 unless A || Bの場合、A || Bが成立するパターンが3つもあり(Aだけがtrueの場合、Bだけがtrueの場合、AとBが両方ともtrueの場合)、さらにそれぞれが否定されるので、脳への負担が大きくなります。 unless A && Bの場合、A && Bが成立するパターンが1つしかない(=AとBがtrueの場合に限る)ので、その分ましなのでしょう。 それでもunlessの複数条件は読みにくい一面がありますので、可能であればド・モルガンしてifに書き換えることを検討してみましょう。 「場合による」という意見 対義語メソッドについては別途記事にする予定です。 おまけ 関連記事 Railsでnil? blank? empty? present?を使いこなそう(人気記事) Haml で閉じタグに悪戦苦闘してRails を学んだお話 Railsでbefore_filter/before_actionがアクションを中止する仕組みを読んでみる