使用保护子句而不是将代码包装在条件表达式中

时间:2018-06-19 15:18:41

标签: ruby rubocop

重新编写下面的代码的最佳方法是什么,而rubocop不会将其视为“样式/警卫队”罪行

    def abc(a1, a2, a3, a4)
      return some_method_call unless a1.is_a? Numeric
      unless a2.eql? 'name'
        some_method_call_1
      end
      unless a3.downcase.eql? 'age'
        some_method_call_2
      end
      unless a4 < 200
        some_method_call_3
      end
    end

3 个答案:

答案 0 :(得分:3)

def foo
  return some_method_call unless a1.is_a? Numeric
  some_method_call_1 unless a2.eql? 'name'
  some_method_call_2 unless a3.casecmp?('age')
  some_method_call_3 unless a4 < 200
end

您也可以将downcase.eql?替换为String#casecmp?

注意String#casecmp?从Ruby 2.4开始也可用。

答案 1 :(得分:0)

我假设保护条件将始终适用于被调用的特定方法。

在这种情况下,您可以将保护条件提取到要调用的特定方法中,并显式传递要检查的变量。

当然,这比较冗长,但是我认为这会使所有方法更加可用,可子类化,可重写等。您可以更好地控制方法的功能。而且更容易阅读。

def abc(a1, a2, a3, a4)
  if a1.is_a?(Numeric)
    do_something_with_values(a2, a3, a4)
  else
    some_method_call
  end
end

def do_something_with_values(a1, a2, a3)
  some_method_call_1(a1)
  some_method_call_2(a2)
  some_method_call_3(a3)
end

def some_method_call_1(a)
  return if a.eql?('name')
  # some functionality
end

def some_method_call_2(a)
  return if a.downcase.eql?('age')
  # some functionality
end

def some_method_call_3(a)
  return if a < 200
  # some functionality
end

编辑:

将我的代码与RuboCop GuardClause docs中的 good 示例进行比较,它们的样式似乎匹配。 我不确定abc的重写是否与RuboCop风格匹配,但是我无法想到为什么它会被认为是不好的。

答案 2 :(得分:0)

我认为Rubocop在这里想要的是这样的东西:

def abc(a1, a2, a3, a4)
  return some_method_call unless a1.is_a? Numeric
  unless a2.eql? 'name'
    some_method_call_1
  end
  unless a3.downcase.eql? 'age'
    some_method_call_2
  end
  return unless a4 < 200
  some_method_call_3
end

这是因为仅在满足a4 < 200条件时才调用最后一个方法。因此,它认为您也可以提早退出。

Rubocop没有对此抱怨:

def abc(a1, a2, a3, a4)
  return some_method_call unless a1.is_a? Numeric
  some_method_call_1 unless a2.eql? 'name'
  some_method_call_2 unless a3.casecmp('age').zero?
  some_method_call_3 unless a4 < 200
end