Ruby 实例化处于状态的数组是否是一种坏的编程习惯?

Ruby 实例化处于状态的数组是否是一种坏的编程习惯?,ruby,if-statement,conditional-statements,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) #... 据我所知,第一个条件更优雅,但创建数组只是为了检查条件是否不好,还是使用的资源可以忽略不计?前一种模式确实

我经常看到这种情况:

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

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

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

前一种模式确实施加了更大的内存压力和CPU开销,因为它必须在每次运行此代码时分配该数组


也就是说,这不一定是一个问题,除非它是一个特别热门的代码路径。如果这是一个经常在某个库深处调用的方法,我可能会选择第二个版本以避免额外的分配,但对于调用率相对较低的业务代码,我认为第一种模式的可读性是可以接受的。

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

也就是说,这不一定是一个问题,除非它是一个特别热门的代码路径。如果这是一个经常在某个库的深处调用的方法,我可能会选择第二个版本以避免额外的分配,但是对于调用率相对较低的业务代码,我认为第一个版本的可读性是可以接受的。

第二个版本(像最复杂的情况一样)容易出错。很容易忘记是否需要括号或布尔逻辑是如何工作的。“变量是这些值中的一个吗?如果是的话,另一件事是真的吗?”的模式可能特别棘手,因此简化显然是有意义的

但是,我认为数组类不包括
包含?
,是吗?在我的测试中,我使用了
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\u 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
它的优点是每次测试时都是散列查找,而不是循环。(另请参见:)

第二个版本(与大多数复杂情况一样)容易出错。很容易忘记是否需要括号或布尔逻辑是如何工作的。“变量是这些值中的一个吗?如果是的话,另一件事是真的吗?”的模式可能特别棘手,因此简化显然是有意义的

但是,我认为数组类不包括
包含?
,是吗?在我的测试中,我使用了
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\u 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

它的优点是每次测试时都是散列查找,而不是循环。(另请参见:)

理想情况下,您不会看到其中任何一个。相反,您应该使用这样的东西,通过将条件分解为小块功能,这样会更惯用,更易于测试

我意识到,如果您使用的是
,那么这个例子就不太一样了,但它足够近,足以说明我的意思

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

理想情况下,你不会看到其中任何一个。相反,您应该使用这样的东西,通过将条件分解为小块功能,这样会更惯用,更易于测试

我意识到,如果您使用的是
,那么这个例子就不太一样了,但它足够近,足以说明我的意思

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

一个好的编译器应该能够识别数组是静态的,并将其初始化为静态变量(或者Ruby中的任何等价物)。我不希望每次运行条件时都实际创建数组。@Carcigenicate我不知道这是否会改变您的注释,但Ruby是解释的,而不是编译的。除非您的应用程序开始感觉缓慢,否则我根本不会担心性能。如果是这样的话,您可能会找到更重要的优化方法。我想说,这取决于您优化的目的:性能(存储在常量中的
Set
可能更好)、内存消耗(您的版本可能更好)、可读性或可维护性(数组版本是一个常见的简短Ruby习惯用法)…@Piccolo哇哦。我不认识Ruby,所以我做了一个概括的评论。如果它被解释,它实际上每次都会创建列表。虽然只有几个元素,但创建起来应该很快。它是否可以忽略取决于条件运行的频率。一个好的编译器应该能够识别数组是静态的,并将其初始化为静态变量(或Ruby中的任何等效变量)。我不希望每次运行条件时都实际创建数组。@Carcigenicate我不知道这是否会改变您的注释,但Ruby是解释的,而不是编译的。除非您的应用程序开始感觉缓慢,否则我根本不会担心性能。如果是这样的话,您可能会找到更重要的优化方法。我想说,这取决于您优化的目的:性能(存储在常量中的
Set
可能更好)、内存消耗(您的版本可能更好)、可读性或可维护性(数组版本是一个常见的简短Ruby习惯用法)…@Piccolo哇哦。我不认识Ruby,所以我做了一个概括的评论。如果它被解释,它实际上每次都会创建列表。只有