在一个糟糕的编程习惯条件下实例化一个数组?

时间:2017-06-09 15:38:10

标签: ruby if-statement conditional-statements

我经常看到这种情况:

if ([CONSTANT_1, CONSTANT_2, CONSTANT_3].contains? var && a_boolean) #...

而不是:

if ((var == CONSTANT_1 || var == CONSTANT_2 || var == CONSTANT_3) var && a_boolean) #...

我明白第一个条件更优雅,但创建一个数组只是为了检查一个条件是坏的还是使用的资源是否可以忽略不计?

3 个答案:

答案 0 :(得分:0)

前一种模式确实会产生更大的内存压力和CPU开销,因为每次运行此代码时都必须分配该数组。

尽管如此,除非它是一个特别热门的代码路径,否则这不一定是个问题。如果这是一个在某个地方经常深入调用的方法,我可能选择第二个版本来避免额外的分配,但对于具有相对较低的通话率的业务代码,我认为第一个的可读性是可以接受的

答案 1 :(得分:0)

第二个版本(像最复杂的条件一样)容易出错。很容易忘记你是否需要括号或布尔逻辑是如何工作的。 "的模式是这些值中的变量之一,如果是这样,那么另一个是真的吗?"可能特别棘手,所以简化是有道理的。

但是,我不认为Array类包含contains?,是吗?在我的测试中,我使用了include?

CONSTANT_1 = 1
CONSTANT_2 = 2
CONSTANT_3 = 3.14
a_boolean = true
var = 3.14

puts "true" if [CONSTANT_1, CONSTANT_2, CONSTANT_3].include?(var) && a_boolean

请注意var周围的括号是必要的,以便include?不会搜索var && a_boolean而不只是var

我用这个习语看到的唯一真正的问题是让var先到后会更好一些。在SQL中,您可以编写类似的内容:

var in (CONSTANT_1, CONSTANT_2, CONSTANT_3) and a_boolean

这看起来更自然一点。

如果您真的担心效率并且多次进行此测试,那么设置哈希可能会更好:

constant_test = {}
[CONSTANT_1, CONSTANT_2, CONSTANT_3].each do |k|
  constant_test[k] = true
end

puts "true" if constant_test[var] && a_boolean

这样做的好处是每次测试时都是哈希查找而不是循环。 (另见:this answer。)

答案 2 :(得分:0)

理想情况下,你不会看到其中任何一个。相反,你可以使用类似这样的东西,通过将条件分解成小块功能来更加惯用和更可测试。

我意识到这个例子与你使用的if不完全相同,但它足够接近我的意思。

class Thing
  def initialize(var)
    @var = var
  end

  def a_method
    return 'yes' if has_constaints? && boolean?
    'no'
  end

  private

  def has_constaints?
    @var == CONSTANT_1 || @var == CONSTANT_2 || @var == CONSTANT_3
  end

  def boolean?
    @var && a_boolean
  end
end