最近はレビューしていることが多いなぁと思っている須藤です。レビューをしていると「真偽値を返すif
/else
」をちょいちょい見かけるなぁと思い出したので18回目のノータブルコードとして紹介します。17回目のノータブルコードが2021年6月28日なので、3年強ぶりのノータブルコードです。久しぶり!
「真偽値を返すif
/else
」というのはこういうif
/else
のことです。私は知らないのですが、なにか名前がついていたりします?
static bool
is_odd(int x)
{
if (x % 2 == 1) {
return true;
} else {
return false;
}
}
こういうif
/else
を見たときはif
/else
なしでこれでいいんじゃない?というコメントをしています。
static bool
is_odd(int x)
{
return x % 2 == 1;
}
それではこんなif
/else
について考えてみましょう。
if
/else
なしのほうがよいのか
私はない方が読みやすいなぁと思います。
static bool
is_odd(int x)
{
if (x % 2 == 1) {
return true;
} else {
return false;
}
}
というようにif
/else
があると、x % 2 == 1
がtrue
ならtrue
を返して、そうじゃないならfalse
を返すのね、と読んでいる気がします。
一方、if
/else
がないとどうでしょう。
static bool
is_odd(int x)
{
return x % 2 == 1;
}
この場合は、x % 2 == 1
かどうかを返すのね、と読んでいる気がします。
考えることが1つ減っているので読みやすく感じている気がします。
このケースではtrue
のときにtrue
を返していますが、次のようにtrue
のときにfalse
を返している場合はどうでしょうか。
static bool
is_odd(int x)
{
if (x % 2 == 0) {
return false;
} else {
return true;
}
}
読むときにもうひと手間かかっていそうな感じがしますね。
ということで、私はif
/else
がない方が読みやすいと感じます。
いつもif
/else
がない方がよいのか
それでは、いつもif
/else
を使わない方が読みやすいのでしょうか。私の経験ではそういうわけでもなさそうです。
たとえば次のケースはどうでしょうか。if
/else
ではないですがif
は使っています。
bool
grn_obj_is_bulk(grn_ctx *ctx, grn_obj *obj)
{
if (!obj) {
return false;
}
return obj->header.type == GRN_BULK;
}
これは次のようにも書けます。
bool
grn_obj_is_bulk(grn_ctx *ctx, grn_obj *obj)
{
return obj && obj->header.type == GRN_BULK;
}
このくらいのコードならどちらでもいい気はしますが、私がコードを読む人なら、コードを書いた人の意図を違うように読みそうです。
もとのコードではif
を使ってNULL
のケースを除外しています。(early returnでfalse
を返しています。)そのため、NULL
のケースはこの関数では本質ではないのだろうと読みます。return
のところにあるobj->header.type == GRN_BULK
の部分が本質なんだろうと読みます。
return
だけにしたコードではそのまま「obj
がNULL
じゃなくてobj->header.type == GRN_BULK
なときだけtrue
なんだな」と読みます。それぞれの条件の重要度の違いはあまり感じません。
ちょっとすぐに具体例を見つけられなかったのですが、&&
と||
が入り乱れるような複雑な条件の場合やはif
を使ってearly returnした方が読みやすいことが多いです。
まとめ
「真偽値を返すif
/else
」をちょいちょい見るなぁと思ったのでまとめてみました。