为什么在Ruby中不鼓励使用else语句?

nic*_*tme 7 ruby coding-style conditional-statements

前几天我正在寻找一个Ruby代码质量工具,我遇到了pelusa gem,它看起来很有趣.它检查的一件事是给定Ruby文件中使用的else语句的数量.

我的问题是,为什么这些不好?我理解这些if/else语句经常会增加很多复杂性(而且我的目标是降低代码复杂性)但是如何在不使用else?的情况下编写检查两种情况的方法?

总结一下,我有两个问题:

1)除了降低代码复杂性之外还有其他原因可以避免其他语句吗?

2)这是我正在使用的应用程序使用else语句的示例方法.如果没有一个,你会怎么写?我能想到的唯一选择是三元语句,但这里有足够的逻辑,我认为三元语句实际上会更复杂,更难读.

def deliver_email_verification_instructions
  if Rails.env.test? || Rails.env.development?
    deliver_email_verification_instructions!
  else
    delay.deliver_email_verification_instructions!
  end
end
Run Code Online (Sandbox Code Playgroud)

如果你用三元运算符写这个,那就是:

def deliver_email_verification_instructions
  (Rails.env.test? || Rails.env.development?) ? deliver_email_verification_instructions! : delay.deliver_email_verification_instructions!
end
Run Code Online (Sandbox Code Playgroud)

是对的吗?如果是这样,是不是更难以阅读?一份else声明是否有助于打破这种局面?有没有另外一种更好的else方式来写这个我没有想到的东西?

我想我在这里寻找风格的考虑因素.

fre*_*oma 6

首先让我说你的代码没有任何问题,通常你应该知道,无论代码质量工具告诉你什么,都可能完全是胡说八道,因为它缺乏评估你实际做什么的上下文.

但回到代码.如果有一个类只有一个方法所在的片段

if Rails.env.test? || Rails.env.development?
    # Do stuff
else
    # Do other stuff
end
Run Code Online (Sandbox Code Playgroud)

发生了,这将是完全正常的(对于给定的事物总是有不同的方法,但你不必担心,即使程序员会讨厌你不与他们争论它:D).

现在是棘手的部分.人们很懒惰,因此像上面那样的代码片段是复制/粘贴编码的简单目标(这就是为什么人们会争辩说首先应该避免使用它们,因为如果你以后扩展课程你更有可能只是复制和粘贴东西,而不是实际重构它).

我们来看一下你的代码片段.我基本上提出与@Mik_Die相同的东西,但是他的例子同样容易被复制/粘贴为你的.因此,应该做(IMO)是这样的:

class Foo
  def initialize
    @target = (Rails.env.test? || Rails.env.development?) ? self : delay
  end

  def deliver_email_verification_instructions
    @target.deliver_email_verification_instructions!
  end
end
Run Code Online (Sandbox Code Playgroud)

这可能不适用于您的应用,但我希望您明白这一点,即:不要重复自己.永远.每次重复自己时,不仅会使代码的可维护性降低,而且将来也更容易出错,因为您复制和粘贴的任何内容都可能会发生一次甚至99/100次更改,但是剩下的一个事件是什么导致@disasterOfEpicProportions最终:)


我忘记的另一点是@RayToal(感谢:),这是因为if/else构造经常与布尔输入参数结合使用,导致这样的构造(我有一个项目的实际代码)维持):

class String
  def uc(only_first=false)
    if only_first
      capitalize
    else
      upcase
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

让我们在这里忽略明显的方法命名和猴子修补问题,并专注于if/else构造,它用于uc根据参数为方法提供两种不同的行为only_first.这样的代码违反了单一责任原则,因为你的方法不止一件事,这就是你应该首先编写两种方法的原因.

  • 这是OP代码的最佳重构恕我直言.带有`else`部分的`if`语句通常是不受欢迎的,因为当你看到它们时,你的封闭方法是**不止一件事**,违反了SRP(尽管我永远不会争论跟随这个100%的时间).基于环境初始化目标并不是一件事情; 它正在计算正确的目标.然后交付方法很棒.+1 (2认同)