我正在考虑流量控制的最佳实践。我应该走哪条路?
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找到Feed):
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方法并让它们抛出异常,如果出现错误?
答案 0 :(得分:6)
1)不要检查任何东西,让程序失败(更干净的代码, 自然错误消息):
使用已知的,记录的异常“让程序失败”是可以的,但是因为你试图使用NoMethodError
对象而得到一个令人不快的nil
只是粗心大意。在您的特定示例中,ActiveRecord#find
会引发记录的ActiveRecord::RecordNotFound
异常,因此IMO就是这样的:
def self.fetch(feed_id)
Feed.find(feed_id).fetch
end
2)通过返回nil默默地失败(但是,“清洁代码”说,那 你永远不应该返回null):
这很好,作为一般建议,但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)抛出异常(因为特殊情况下不能找到饲料 ID):
是的,但是让方法引发众所周知的RecordNotFound
异常,而不是自定义异常(除非您想要抽象使用AR的事实,这可能非常麻烦)。
答案 1 :(得分:2)
我认为正确的答案是:它取决于。用户理论上应该永远不会遇到来自框架的任何错误消息。您必须始终准备好处理这些异常。选择是你的全部(如果它不是外部使用的界面或其他东西)。
如果您采取第一条路线,我认为您应该首先查询存在该ID的任何Feed,然后尝试获取它。如果Feed在两者之间消失,那么报告可能是一个真正的问题。第三个基本相同。您需要确保,您处理了所有情况,并且抛出异常可以帮助防止用户看到错误。
第二个解决方案基本上是这个,但内部处理。没有,你发出信号表明有问题。它也必须处理,报告给用户或其他什么。缺点是如果你忘记了这一点,你可能会误导用户。
我会使用第一种方法,之前需要额外检查以确保它存在。但这取决于使用情况。
答案 2 :(得分:2)
我会选择干净的版本。
如果您没有向feed_id
方法提供fetch
,则ruby本身会引发ArgumentError: wrong number of arguments(0 for 1)
,因此#3的第一部分毫无意义。
如果您没有提供有效的feed_id
,那么Feed.find(feed_id)
来电会引发另一个异常,很可能是ActiveRecord::RecordNotFound
,并显示一条消息,说它无法找到Feed使用提供的ID,或者如果未提供ID(feed_id
参数为nil
),则无法找到没有ID的Feed。
对我而言,使用feed_id = nil
调用方法似乎有点愚蠢,所以我可能会争辩说“如果发送无效输入,它可能会中断”,在这种情况下,我认为{{ 1}}会提供有关出错的更多信息,而不是提出ActiveRecord::RecordNotFound
。
返回空值很少是好事,因为这不会告诉你实际出了什么问题。因此,我也排除了#2。