ruby - 引发自定义异常、返回常量或返回符号?为什么?

标签 ruby exception error-handling

假设我有一个 WebCrawler 类。它可能会遇到几个错误。我应该如何向上传播错误?

使用异常:

class WebCrawler
  class UrlBadFormatError < StandardError; end
  class PageNotFoundError < StandardError; end
  class UnauthorizedError < StandardError; end
  def crawl(url)
    if(! url =~ /some_format/)
      raise UrlBadFormatError
    response = get(url)
    if(response.code == 404)
      raise PageNotFoundError
    if(response.code == 403)
      raise UnauthorizedError
    ... 
  end
end

或常量:

class WebCrawler
  URL_BAD_FORMAT = 1
  PAGE_NOT_FOUND = 2
  UNAUTHORZIED = 3 
  def crawl(url)
    if(! url =~ /some_format/)
      return URL_BAD_FORMAT
    response = get(url)
    if(response.code == 404)
      return PAGE_NOT_FOUND
    if(response.code == 403)
      return UNAUTHORZIED
    ... 
  end
end

或符号:

class WebCrawler
  def crawl(url)
    if(! url =~ /some_format/)
      return :url_bad_format
    response = get(url)
    if(response.code == 404)
      return :page_not_found
    if(response.code == 403)
      return :unauthorized
    ... 
  end
end

哪个最好?或者它取决于(取决于什么?)

最佳答案

对于表明程序员错误的事情,例如传递给方法的参数类型错误,肯定会抛出异常。该异常会使程序崩溃,引起程序员的注意,他们没有正确使用您的类,因此他们可以解决问题。在这种情况下,返回错误代码是没有意义的,因为程序必须包含检查返回值的代码,但在调试程序后,这样的错误永远不会发生。

在您的 WebCrawler 类中,是否预期 crawl 有时会收到错误的 URL 作为参数?我想答案很可能是否定的。因此,当传递错误的 URL 时引发异常是合适的。

当出现异常时,执行流程突然“跳”到最里面的处理程序。当大多数情况下不会预期会发生异常时,这可能是一种构建代码的有用方法,因为您可以将方法的“主要流程”编写为简单的直线代码,而无需包含关于发生某些罕见错误情况时会发生什么的很多细节。这些细节可以从“主要流程”代码中分离出来,并放入异常处理程序中。但是,当预期在正常情况下会发生错误情况时,最好将错误处理代码与“主流”内联,以便更清楚地了解正在发生的事情。如果你的程序的控制流“跳来跳去”(就像异常用于正常流控制时的情况),这意味着读者在弄清楚它是如何工作时也必须在程序文本中“跳来跳去”。

对于另外两个,我认为至少在某些时候,HTTP 请求会返回一个错误代码。要确定异常或特殊返回值是否是指示此类情况的最佳方式,我会考虑这些情况在正常使用情况下发生的频率。还要考虑客户端代码将如何读取任何一种方式。如果您使用异常,他们将不得不编写如下内容:

urls.map do |url|
  begin
    crawl(url)
  rescue PageNotFoundError
    ""
  rescue UnauthorizedError
    ""
  end
end

(顺便说一句,我认为这个代码示例说明了一些事情:如果您的两个自定义异常都继承自一个公共(public)父类(super class)可能是个好主意,这样您就可以用一个 rescue 子句(如果需要的话)。)或者如果你使用错误代码,它看起来像这样:

urls.map do |url|
  response = crawl(url)
  if [:page_not_found, :unauthorized].include? response
    ""
  else
    response
  end
end

你认为哪个读起来更好?这真的取决于你。您不想做的一件事是对错误使用整型常量。为什么要使用整数?当您在调试跟踪中打印它们时,您必须查看常量列表以了解每个常量的含义。使用符号在计算上同样高效。

关于ruby - 引发自定义异常、返回常量或返回符号?为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9558582/

相关文章:

Ruby block 语句和隐式返回

ruby-on-rails - 如何在 Ruby on Rails 中添加自定义路由、 Controller 和操作?

java - java中检查异常有什么用?

java - JxBrowser 6.14.2 下载文件处理异常

python - flask 中的@app.errorhandler(Exception) 不会捕获无效路由

java - Ruby 代码到 JAR

mysql - 是否可以使用 Mysql2 gem 更改所选数据库?

c# - 如何找到 "out of range"异常的原因?

powershell - 无法在Powershell中使用try..catch捕获错误

unit-testing - Grails:使用 spock 测试约束错误消息