Ruby 流控制:抛出异常,返回 nil 或让它失败



我正在考虑流量控制的最佳实践。我应该走哪条路?

1)不要检查任何东西,让程序失败(更干净的代码,自然错误消息):

  def self.fetch(feed_id)
    feed = Feed.find(feed_id)
    feed.fetch
  end

2)通过返回nil以静默方式失败(但是,"干净代码"说,你永远不应该返回null):

  def self.fetch(feed_id)
    return unless feed_id
    feed = Feed.find(feed_id)
    return unless feed
    feed.fetch
  end

3)抛出异常(因为不按id找到提要是例外):

  def self.fetch(feed_id)
    raise ArgumentError.new unless feed_id
    feed = Feed.find(feed_id)
    raise ArgumentError.new unless feed
    feed.fetch
  end

换句话说:我应该主动使用保护条件,还是依靠Ruby/Rails方法并在发生错误时让它们抛出异常更好?

1)不要检查任何东西,让程序失败(更干净的代码, 自然错误消息):

使用

已知的、记录的异常"让程序失败"是可以的,但是因为您尝试使用nil对象而获得令人不快的NoMethodError只是粗心大意。在您的特定示例中,ActiveRecord#find会引发记录在案的ActiveRecord::RecordNotFound异常,因此 IMO 这是要走的路:

def self.fetch(feed_id)
  Feed.find(feed_id).fetch
end

2)通过返回nil来静默失败(但是,"干净代码"说,那 你不应该返回空值):

作为一般建议,这很好,但是Ruby充满了返回nil的方法;这没关系(同样,只要它被记录下来),它只是意味着"什么都没有"(并允许非常紧凑的模式something_that_can_be_nil || another_value)。在这种情况下,我会使用 Ick 的maybe简洁地编写它:

def self.fetch(feed_id)
  Feed.find_by_id(feed_id).maybe.fetch
end

3)抛出异常(因为找不到源是例外的 同上):

是的,但是让该方法引发众所周知的RecordNotFound异常,而不是自定义异常(除非您想抽象出正在使用AR的事实,这可能非常麻烦)。

我会选择干净的版本。

如果你不为fetch方法提供feed_id,Ruby 本身会提高ArgumentError: wrong number of arguments(0 for 1),所以 #3 的第一部分毫无意义。

如果您没有提供有效的feed_id,则Feed.find(feed_id)调用将引发不同的异常,很可能ActiveRecord::RecordNotFound显示一条消息,指出它找不到具有所提供 ID 的源,或者如果未提供 ID(feed_id参数为 nil),则它找不到没有 ID 的源。

对我来说,用 feed_id = nil 调用该方法似乎有点愚蠢,所以我可能会争辩说"如果您发送无效输入,它可能会中断",在这种情况下,我认为ActiveRecord::RecordNotFound会为您提供更多信息关于出了什么问题比您提出ArgumentError

返回 null 值很少是一件好事,因为这不会告诉您实际出了什么问题。因此,我也会排除#2。

我认为

正确的答案是:这取决于。从理论上讲,用户永远不会遇到来自框架的任何错误消息。您必须始终准备好处理这些异常。选择权在您手中(如果它不是外部使用的接口或其他东西)。

如果您采用第一条路线,我认为您应该首先查询是否存在具有该 id 的任何提要,然后尝试获取它。如果两者之间的源消失,这可能是一个真正的报告问题。第三个基本相同。您需要确保处理了每种情况,并且在抛出异常中可以帮助防止用户看到错误。

第二种解决方案基本上是这样的,但需要内部处理。用 nil 表示存在一些问题。还必须处理它,向用户报告或其他内容。缺点是如果你忘记了这一点,你可能会误导用户。

我会使用第一种方法,并在之前进行额外的检查以确保它存在。但这取决于使用情况。

相关内容

  • 没有找到相关文章

最新更新