为了账号安全,请及时绑定邮箱和手机立即绑定

为什么在Ruby中“拯救异常=>e”是不好的风格?

为什么在Ruby中“拯救异常=>e”是不好的风格?

哈士奇WWW 2019-06-10 16:54:13
为什么在Ruby中“拯救异常=>e”是不好的风格?赖安·戴维斯Ruby QuickRef说(没有解释):不要拯救例外。永远不会。不然我就捅你。为什么不行?该怎么做才是对的?
查看完整描述

3 回答

?
萧十郎

TA贡献1815条经验 获得超13个赞

使用StandardError而不是一般的异常捕获。当重新引发原始异常时(例如,当救援只记录异常时),Exception可能没问题。


ExceptionRuby异常层次结构所以当你rescue Exception你从一切,包括子类,如SyntaxErrorLoadError,和Interrupt.

援救Interrupt防止用户使用克特C退出程序。

援救SignalException阻止程序正确响应信号。它将是无法杀死的,除非.kill -9.

援救SyntaxError意味着eval失败的人会默默地这样做。

所有这些都可以通过运行这个程序来显示,并试图克特Ckill它:

loop do
  begin
    sleep 1
    eval "djsakru3924r9eiuorwju3498 += 5u84fior8u8t4ruyf8ihiure"
  rescue Exception
    puts "I refuse to fail or be stopped!"
  endend

救出Exception甚至不是默认的。做

begin
  # iceberg!rescue
  # lifeboatsend

救不出Exception,它拯救了StandardError..您通常应该指定一些比默认值更具体的内容。StandardError,但是从Exception 变宽范围而不是缩小它,可能会有灾难性的结果,并使找虫极其困难.


如果你遇到了什么情况,你真的想从StandardError如果您需要一个变量(除了这个例外),您可以使用以下形式:

begin
  # iceberg!rescue => e  # lifeboatsend

相当于:

begin
  # iceberg!rescue StandardError => e  # lifeboatsend

这是少数几个正常的案例之一Exception用于日志记录/报告,在这种情况下,您应该立即重新引发异常:

begin
  # iceberg?rescue Exception => e  # do some logging
  raise e  # not enough lifeboats ;)end


查看完整回答
反对 回复 2019-06-10
?
小唯快跑啊

TA贡献1863条经验 获得超2个赞

假设你在一辆车里(运行Ruby)。您最近安装了一个带有空中升级系统的新方向盘(该系统使用eval),但是您不知道有一个程序员在语法上搞砸了。

你在一座桥上,意识到你正向栏杆走一点,所以你向左拐。

def turn_left  self.turn left:end

哎呀!那可能是不好™,幸运的是,Ruby引发了一个SyntaxError.

车应该马上停下来-对吗?

没有。

begin
  #...
  eval self.steering_wheel  #...rescue Exception => e  self.beep  self.log "Caught #{e}.", :
  warn  self.log "Logged Error - Continuing Process.", :infoend

哔声

警告:已捕获SyntaxError异常。

信息:记录错误-继续处理。

你注意到有什么地方不对劲,你就在紧急情况下摔了一跤(^CInterrupt)

哔声

警告:捕获中断异常。

信息:记录错误-继续处理。

是啊-没什么用。你离铁轨很近,所以把车停在公园里kill英灵:SignalException).

哔声

警告:捕获SignalException异常。

信息:记录错误-继续处理。

最后一秒钟,你拿出钥匙(kill -9),汽车停了下来,你猛地冲进方向盘(安全气囊无法充气,因为你没有优雅地停止程序-你终止了程序),而你车后部的电脑猛地撞到了它前面的座位上。一罐半罐可乐洒在报纸上。后面的杂货都被压碎了,而且大部分都是蛋黄和牛奶。这辆车需要认真的修理和清洗。(数据损失)

希望你有保险(备份)。哦,是的-因为气囊没有充气,你可能受伤了(被解雇,等等)。


但是等等!有更多您可能想要使用的原因rescue Exception => e!

假设你是那辆车,你想确保安全气囊膨胀,如果汽车超过了它的安全停车动量。

 begin 
    # do driving stuff
 rescue Exception => e    self.airbags.inflate if self.exceeding_safe_stopping_momentum?
    raise end

这里是规则的例外:你可以抓住Exception 只有当你重新引发异常的时候..所以,一个更好的规则就是不要吞下Exception,并且总是重提错误。

但是,在Ruby这样的语言中,添加援救是很容易忘记的,而且在重新提出问题之前,将援救声明放在这里感觉有点不枯燥。而你不要想忘记raise声明。如果你这么做了,祝你好运,努力找出那个错误。

谢天谢地,Ruby很棒,您可以使用ensure关键字,确保代码运行。这个ensure关键字将运行代码,无论发生什么-如果抛出异常,如果没有异常,唯一的例外是如果世界结束(或其他不可能发生的事件)。

 begin 
    # do driving stuff
 ensure
    self.airbags.inflate if self.exceeding_safe_stopping_momentum?
 end

砰!这段代码无论如何都应该运行。你应该用的唯一理由rescue Exception => e是否需要访问异常,或者只希望在异常上运行代码。记得重提错误。每次。

注:正如@Niall所指出的,请确保跑啊。这是好的,因为有时您的程序可以欺骗您,而不是抛出异常,即使发生问题。对于关键的任务,如充气安全气囊,你需要确保它发生在任何情况下。因此,每次停车时检查是否抛出异常都是个好主意。尽管充气气囊在大多数编程环境中是一项不常见的任务,但在大多数清理任务中,这实际上是相当常见的。

rescue Exception => e(而不是重新提出例外)-或者你强权开车离开桥。


查看完整回答
反对 回复 2019-06-10
  • 3 回答
  • 0 关注
  • 876 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信