我正在考虑流量控制的最佳实践。我应该走哪条路?
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 表示存在一些问题。还必须处理它,向用户报告或其他内容。缺点是如果你忘记了这一点,你可能会误导用户。
我会使用第一种方法,并在之前进行额外的检查以确保它存在。但这取决于使用情况。