【问题标题】:Are there alternatives to rescue LoadError for Ruby?是否有其他方法可以挽救 Ruby 的 LoadError?
【发布时间】:2011-09-18 08:28:48
【问题描述】:

我阅读了 JRuby Performance: Exceptions are not flow control 的博文,该博文主张在特殊情况下避免使用异常。

我意识到我经常使用救援来处理 LoadErrors 是有罪的。

是否有替代require 的方法,如果文件存在则尝试加载文件,但如果不存在则不抛出异常?

背景:如果你想知道“为什么你有你并不绝对需要的要求?”,这是我的故事:

  1. 在为 Ruby 1.8 编程时,我使用了require "rdoc/usage",以便在我没有在命令行应用程序中输入正确数量的参数时提供使用信息。这会在开箱即用的 1.9 上引发异常。
  2. 我的应用程序的一部分涉及在我的 Windows 桌面上运行时操作 win32ole 的代码。如果涉及的文件在执行繁重计算工作的 Linux 服务器下运行,则会导致 LoadError。使用 win32ole 的文件还有在我的测试套件中测试的其他代码,因此在 Linux 下运行我的测试套件时,我必须要求这些文件。我应该拆分这些文件,但这似乎有点像牦牛剃须。

【问题讨论】:

  • 我有一个非常相似的用例(即:工具中的可选扩展)。我很想知道 LoadError 是否是唯一的方法。
  • 请注意,本文讨论的情况是,每个 Rails 请求都会引发数百 个异常,而您是在讨论引发两个异常一次在程序的整个生命周期中。

标签: ruby exception require


【解决方案1】:

计算机程序几乎将所有时间都花在循环中。如果您在程序执行期间执行数百万次的内部循环中反复引发和挽救异常,您可能真的会遇到性能问题。但是加载文件通常只在程序初始化期间完成。如果您在程序启动期间引发并挽救一些异常,那么对性能的影响将非常接近于零,以至于任何人都不会注意到。

顺便说一句,如果您有一个真正对性能敏感的方法(即执行多次),但您确实想要一个“goto”,它允许您跳出多个块甚至向上调用堆栈(像一个例外),使用throwcatch。它们类似于raiserescue,但要快得多。引发异常的大部分性能成本来自于填充堆栈跟踪,而throw 不会这样做。

恕我直言,begin; require "..."; rescue LoadError 是惯用的 Ruby,无论人们怎么说“使用异常进行流控制”,无论如何都不应被视为不好的做法。如果您的脚本通常在 Windows 上执行,那么在 Linux 上运行可以正确地被视为“异常情况”,并且值得使用异常。一般来说,如果您要加载的文件不存在,那就是“异常情况”——这就是 require 首先引发异常的原因!

抬起头来,伙计!不要让仇恨者让你因为使用简单的常识代码而感到内疚!

【讨论】:

    【解决方案2】:

    对您的第一个案例使用异常可能很好,并且比尝试在调用它之前弄清楚require 是否会失败要少得多。如果你所做的只是尝试加载一些可选的东西(或者,类似地,你需要支持几个不同的库来做同样的事情),那么尝试加载它并处理异常是好的、好的和道德上的行为。

    在第二种情况下,在尝试执行特定于平台的操作(如 OLE)之前检查 RUBY_PLATFORMsys-uname 可能更有意义。有时牦牛确实需要剃毛。在这种情况下,如果您使用的是 Windows,那么您确实希望 require 失败,而如果您使用的是 Linux,则根本不想 require;您正在使用异常的副作用而不是异常本身。

    有时人们会尝试将异常用作某种可捕获的 goto。异常适用于不可恢复的错误情况,而不是作为一般事件通知系统。使用异常作为 goto(即流控制)是对异常处理系统的滥用,并且构建使用异常进行流控制的系统的人通常最终在医院(对于“跌倒”,进入一盒锤子,十次一行)。

    【讨论】:

    • 您实际上不会使用 RUBY_PLATFORM,但我明白您的意思。
    • @Andrew:我不必处理跨平台的 Ruby 问题,所以 RUBY_PLATFORM 有点猜测,AFAIK 它在 JRuby 上有问题,所以更明确(例如 sys -uname) 会是一个更好的主意。
    猜你喜欢
    • 2016-07-21
    • 1970-01-01
    • 2013-01-18
    • 1970-01-01
    • 2020-07-27
    • 2018-06-17
    • 1970-01-01
    • 2012-11-18
    • 1970-01-01
    相关资源
    最近更新 更多