Tbpgr Blog

Employee Experience Engineer tbpgr(てぃーびー) のブログ

Ruby | 複数のor条件の判定の記述方法について

概要

複数のor条件の判定の記述方法について

詳細

複数のor条件の判定の記述方法について。

どうするのが一番シンプルで可読性・保守性が高いのか思案。
いくつか例を上げてみた。これがいい!みたいな要望があれば
tbpgr_utils gemに追加しようかな?
=>結局Object#any_of?としてtbpgr_utils gemに含めてver 0.0.3でリリースしました。

わざわざ作らなくても普通はこうするよ、このライブラリが良いよ、
みたいのがあればそちらを利用しようかな。

パターン1

オーソドックスに「||」で判定。でも比較数が増えてきたりすると
self == "xxx"をいっぱい書く必要があって冗長。

サンプルコード
# encoding: utf-8

class String
  def sample
    puts (self == 'hoge' || self == 'hige') ? 'hogehige' : 'other'
  end
end

%w{hoge hige other}.each(&:sample)
サンプル出力
hogehige
hogehige
other

パターン2

case文で書いてみる。パターン1のようにself == "xxx"を何度も書く必要な無いが
三項演算子利用時のように1行で書けなくなった。

サンプルコード
# encoding: utf-8

class String
  def sample
    case self
    when 'hoge', 'hige'
      puts 'hogehige'
    else
      puts 'other'
    end
  end
end

%w{hoge hige other}.each(&:sample)

※以降すべて出力結果はパターン1と同じため省略

パターン3

比較対象をリストにして左辺にinclude?でチェックする。
しかし、可読性の面からすると本来はselfを基準とした比較のため違和感を感じる。
左辺定数による比較を容認するか、しないかみたいな議論とも似たもので個人の好みが大きいのかもしれないが。
それが嫌なら判定部分だけメソッドとして抽出してメソッド名で可読性を高めるか。
※左辺定数による比較については後述

サンプルコード
# encoding: utf-8

class String
  def sample
    puts %w{hoge hige}.include?(self) ? 'hogehige' : 'other'
  end
end

%w{hoge hige other}.each(&:sample)

パターン4

SQLのinをObjectクラスに実装してみました。
パターン3よりも意味が伝わりやすいです。
ただ、「in」というメソッド名はいまいちだろうか?
少なくともRubyで論理値を扱うなら「xxx?」にしたい。

サンプルコード
# encoding: utf-8

class Object
  def in(*args)
    args.each {|v|return true if self == v}
    false
  end
end

class String
  def sample
    puts self.in('hoge', 'hige') ? 'hogehige' : 'other'
  end
end

%w{hoge hige other}.each(&:sample)

左辺定数による比較について

例えばJavaなどでif文の判定をする際に左辺を定数にするとNullPointerExceptionが発生しないため
その記法を愛用する開発者がいる。
元々はCやC++タイプミスなどで比較(==)ではなく代入(=)を行うことを防ぐためにこう書くようになった、
みたいな情報を読んだことが有ります。
そもそもJavaでは条件式中はbooleanになるように書く必要があるので、そういう心配がないのですが
左辺定数を利用している人に理由を聞くと、最初に挙げたぬるぽ対策のようなものを理由にしているようです。

下記はJavaのコード。
個人的には比較の意味から考えても、下記コードは自然に読めますが

if (person.equals('tanaka') {
  // 田中さん用の処理
}

下記コードは気持ち悪いです。

if ('tanaka'.equals(person) {
  // 田中さん用の処理
}

好みはあると思うし、仕事でJavaの規約を決める際にこの話が出たら大荒れだったので
その時は結局どっちで記述しても良い、ということになりました。