重构建议 - Ruby 101 - 使用多个嵌套的if-then

时间:2011-11-23 18:01:19

标签: ruby-on-rails ruby methods refactoring

重构以下内容的规定最佳做法是什么?

def has_thing?
  if things and things[:something] and things[:something][:else] and things[:something][:else][:matters]
    return true
  else
    return false
  end
end

如果things[:something][:else][:matters]不是nil,我基本上想要返回true,但return true if things[:something][:else][:matters]为nil或things为{0}时,things[:something]会失败undefined method '[]' for nil:NilClass

我可以将它全部包装为begin...rescue..end并在抛出异常时返回false,但这似乎也不正确!

5 个答案:

答案 0 :(得分:4)

我可能会建议两个选项:

def has_thing?
  !!(things && things[:something] && things[:something][:else] && things[:something][:else][:matters])
end

或者更具可读性

def has_thing?
  return false unless things
  return false unless things[:something]
  return false unless things[:something][:else]
  return false unless things[:something][:else][:matters]
  true
end

答案 1 :(得分:2)

请注意以下代码:

if something
  return true
else
  return false
end

完全等同于:

!!something

或直接something如果它是布尔值。另请注意,在编写方法的最后一个表达式时,显式写return并不是惯用的。

另外,尽量避免在哈希中重复检查。我建议ick可能是

另外,在你的* core_ext *模块中你可以使用这个方法:

class Object
  def to_bool
    !!self
  end
end

最后,代码看起来更简洁和声明:

def has_thing?
  things[:something].maybe[:else].maybe[:matters].to_bool
end

答案 2 :(得分:1)

您可以使用try

def has_thing?
  !! things.try(:[], :something).try(:[], :else).try(:[], :matters)
end

使用Hash#fetch的更详细的版本:

def has_thing?
  true if things &&
          things.fetch(:something){ return false }.
                 fetch(:else)     { return false }.
                 [:matters]
end

答案 3 :(得分:1)

我可能会选择:

def has_thing?
  !!(
    things &&
    things[:something] &&
    things[:something][:else] &&
    things[:something][:else][:matters]
  )
end

能够快速了解​​代码的作用对于长期代码维护非常重要。

垂直对齐使我们可以轻松快速扫描正在变化的线条并查看新内容。

答案 4 :(得分:0)

这个问题有各种解决方案。一种是使用andand。您的代码将变为:

def has_things?
  things.andand[:something].andand[:else].andand[:matters]
end

虽然不是非常漂亮,但它可以解决问题。