2

我正在努力改进我的 Ruby 代码,特别是在每个 Ruby 习惯用法的样式方面。我有以下方法:

def self.carnivore_convert
  lambda do |value, field|
    diet_type = value
    if field[:header].to_s == 'diet'
      diet_value = value.to_s.downcase
      if diet_value =~ /yes|no/
        diet_value == 'yes' ? diet_type = 'Carnivore' : diet_type = ''
      end
    end
    diet_type
  end
end

Rubocop 对此抱怨,说我应该:

“避免超过 2 层的块嵌套。”

它专门指的是这一行:

diet_value == 'yes' ? diet_type = 'Carnivore' : diet_type = ''

但是,我根本不清楚为什么这是“违反样式”,我为“修复”这件事所做的任何事情似乎都会使代码更加混乱,至少在我看来是这样。

当我说我不明白为什么这是一种风格违规时,我明白 Rubocop 显然觉得我不应该有一个if...if...if排序结构。但我不确定为什么这是错误的。

我在想我也许可以通过使用某种保护子句来摆脱这段代码中的第一个 if 条件,但我不能这样做,因为这样我的代码就不起作用了。例如,我像这样更改了我的代码:

def self.carnivore_convert
  lambda do |value, field|
    diet_type = value
    next unless field[:header].to_s == 'diet'
    diet_value = value.to_s.downcase
    if diet_value =~ /yes|no/
      diet_value == 'yes' ? diet_type = 'Carnivore' : diet_type = ''
    end
    diet_type
  end
end

但是,虽然没有出错,但这确实使代码无法按预期工作。我试过了breakreturn而不是next

所以我不确定如何将这段代码变成 Rubocop 不会抱怨的形状并且仍然可以阅读。作为一个附带问题,我觉得我在“Ruby 样式”上花费了很多时间,即使我的代码确实有效。只要我能理解为什么这种风格是违规的,我不介意,但在这里我很难看到它。话虽这么说,但我确实了解到,要建立对这些东西的直觉,我还有很长的路要走。

关于上述问题,有人有什么想法吗?

4

1 回答 1

3

如果您收到嵌套警告,这基本上意味着“这里发生了太多事情”。有时样式还有其他问题,您可以修复它们(例如保护子句)。其他时候你只需要拆分代码。您的方法和类越小,可读性越高,并且可能具有单一职责。下面的代码远非完美,但它只是旨在显示一个简单的更改,使其更具可读性并遵循约束:

def self.carnivore_convert
  lambda do |value, field|
    field[:header].to_s == 'diet' ? diet_type(value) || value : value
  end
end

def self.diet_type(diet_value)
  diet_value = diet_value.to_s.downcase
  if diet_value =~ /yes|no/
    diet_value == 'yes' ? 'Carnivore' : ''
  end
end
private_class_method :diet_type

编辑:这是与原始代码等效的另一个版本,但更容易掌握:

def self.carnivore_convert
  lambda do |value, field|
    simplified_value = value.to_s.downcase

    if diet_header?(field) && simplified_value == 'yes'
      'Carnivore'
    elsif diet_header?(field) && simplified_value =~ /yes|no/
      ''
    else
      value
    end
  end
end

def self.diet_header?(field)
  field[:header].to_s == 'diet'
end
private_class_method :diet_header?
于 2015-07-03T13:48:30.540 回答