[Rails]そのunless、ifじゃダメですか?
お仕事で書いたコードのレビューで、先輩エンジニアさんから「ここのunless
はif
の方が良いです」という旨のコメントを頂きました。
私自身、いつからかif
とunless
で先に思いついた方を使うようになっていたので、自戒の意を込めて、また、私と同じ失敗をする人が出ないようにするために、本記事を残します。
unlessを使うようになった契機
本当にrailsに触り始めた頃、以下のようなコードを書きました。
if !hero.〜
(略)
end
すると、rubocopくんが
unless hero.〜
(略)
end
と書くように! と怒ってきたのです。
unlessを知らなかった当時の私は「unless便利やん」ぐらいに思ってしまいました。
それから私は、if
とunless
をその場のノリで使い分けるようになっていきます。。。。
結論:unlessを使う前に一呼吸置いてほしい
簡単な例から
if !hero.blank?
を日本語訳すると、「もし、ヒーローが存在していないでないとき」となる。かなり不自然な日本語である。
一方で、
unless hero.blank?
を日本語訳すると、「もし、ヒーローが存在していないことはないとき」という、これまた不自然な日本語になる。(上よりはマシなので、rubocopくんが悪いとは思わないが)
if hero.present?
を日本語訳すると、「もし、ヒーローが存在するとき」という、自然かつ理解のしやすい日本語になる。
次に、少し複雑な例で考える
unless hero.age > villain.age
日本語訳すると、「ヒーローの年齢がヴィランの年齢より上で『ない』とき」
if hero.age <= villain.age
日本語訳すると、「もしヒーローの年齢がヴィランの年齢以下のとき」
否定が入らない分、後者の方が理解しやすい日本語となっているだろう。
もっと複雑な例で
unless hero.blank? || villain.blank?
自分で書いておいてなんだが、もはや理解不能である。
「ヒーローが存在していないか、もしくは、ヴィランが存在していない、ではないとき」っていつだよ。
というわけでif文にしましょう
if hero.present? && villain.present?
「ヒーローが存在していて、かつ、ヴィランが存在しているとき」と素直にわかります。
結論をもう一度:unlessを使う前に一呼吸置いて、日本語訳してみよう
可読性の高いコードの方が良いなんてことは周知の事実のはずだ。
であれば、自身の書いたコードを即座に日本語訳できるか、その日本語は理解しやすいものかを考えれば、それが良いコードか否かはわかるはずである。
そこら辺をサボると私のように可読性の低いコードを書いてしまうので、皆さんには(特に私のような初心者には)注意していただきたい。
最後にもう一度、基本的にはif
の方が理解しやすいです。
しかし、unless
の方が良い場合もあるので、日本語訳をしましょう。
あなたが書いたコードを読むのはコンピュータと人間です。
コンピュータは少々汚いコードでも読んでくれます。
だから、人間に優しいコードを書きましょう。
というか、そういうコードを書くように心がけます(猛省)
参考文献
Discussion