先週末に WEB+DB PRESS Vol.99の「良いコード」を本気でコードレビューしてみた という興味深いブログ記事が書かれました。
はてなブックマークでのコメントを見ると、多くの人がブログ記事の内容に賛同しているようですが、「P12: 何もしないelseは必要か?」の節には異論が散見されました。
ブログ記事全体の趣旨は、WEB+DB PRESS Vol.99の「Rubyで学ぶ!良いコードって何だろう?」という特集記事への批判です。
特集記事では、次のような例が掲載されていて、
case hour
when 9
say_hello()
when 18
say_goodbye()
end
これは意図が伝わりにくいから、次のように空の else
節を加えるべしと書かれています。
case hour
when 9
say_hello()
when 18
say_goodbye()
else
end
これに対して、ブログ記事の筆者(伊藤氏)は空の else
節は不要だと主張しています。
プログラミング初心者が else
節を書き忘れる可能性を考えると、このケースでは空の else
節を書いたほうが親切かなと私は思います。
しかし、まったく空の else
節が残ることに「座りの悪さ」を感じるのも確かです。
はてなブックマークのコメントで知ったのですが、Python には「何もしない」 pass
文というのがあるそうですね。
これが使えればいいのですが、残念ながら Ruby には存在しません。
特集記事があげている例があまりよくなかったのかもしれません。関数 say_hello
と say_goodbye
の中身まで含めたリファクタリングを検討すべき場面じゃないでしょうか。
おそらく、ソースコード全体はこんな感じです。
def say_hello
puts "Hello!"
end
def say_goodbye
puts "Good bye!"
end
hour = Time.now.hour
case hour
when 9
say_hello()
when 18
say_goodbye()
end
であるとすれば、まずこう書き換えるべきです。
def say(message)
puts "#{message}!"
end
hour = Time.now.hour
case hour
when 9
say("Hello")
when 18
say("Good bye")
end
すると、次のように自然な形で else
節を導入できます。
def say(message)
puts "#{message}!"
end
hour = Time.now.hour
message = case hour
when 9
"Hello"
when 18
"Good bye"
else
nil
end
say(message) if message
元のコードの問題点は、(1)メッセージを選択する論理と(2)メッセージを出力するかどうかを決定する論理を単独の case
式に混在させてしまった点にあります。
私のコードでは、二つの論理が明確に分離されています。(1)の論理は case
式で表現され、(2)の論理は「後置の if
」で表現されています。
いかがでしょうかね。