如何处理Ruby的异常

88 阅读5分钟

编程世界中的异常处理

每一个应用程序都是为了实现用户互动,并有一个特定的目的来增加价值。然而,应用程序,像其他服务一样,有时会在执行时遇到错误。这就更有可能了,因为用户通过创建输入和请求与界面互动。典型的错误情况是以错误的格式输入输入,或者从对外部API的请求中得到错误的回报。

虽然几乎不可能防止所有的错误,也不可能预见每一个原因,但开发人员可以识别可能的错误,并处理它们,使应用程序不会中断。这就是我们所说的异常处理

Exception handling

异常处理

错误和异常

在进入这个话题的技术层面之前,我们应该清楚以下几个概念。

a)错误是指应用程序执行过程中的问题,它导致应用程序崩溃。用户通常会收到一条错误信息,程序也就此结束。在这种情况下,用户可以重新加载应用程序并开始新的执行,尝试不同的行为以避免错误;或者由开发人员通过日志跟踪问题,并尝试实施修复。

b)异常是指在生产代码中被识别为可能的错误的情况,它触发了一个特定的代码执行,以防止应用程序崩溃。我们可以将其区分开来。

  • 已处理的异常,即被成功处理的异常,使用户保持正常运行。
  • 未处理的异常,由于在异常块中定义的解决方法没有正确地支持这个问题,所以变成了错误。

在Ruby中处理异常

处理异常被认为是面向对象编程(OOP)的最佳实践,因为它是一种最大化效率的方式。Ruby是一种编程语言,它提供了一个很好的异常处理系统,具有清晰的语法和结构,有利于重复使用。

Ruby中的异常类型

为了构造我们的异常处理系统,在Ruby中我们可以根据异常的性质进行分组。

一方面,当用户的输入不被应用程序所支持时,就会出现验证异常。基本上,我们可以识别。

  • 由于缺少输入、文件等导致的必填字段错误。
  • 由于类型和格式不匹配导致的唯一字段错误,如空值

另一方面,响应异常是由于通过请求调用API时出现的问题,例如。

  • Badrequest
  • 未经授权的

如何在Ruby中实现异常

Ruby中的异常处理是非常直接的。该结构是在关键字begin,rescueensure 的帮助下执行的。第一个关键字是用来确定可能发生异常的块的范围,rescue 提供了异常情况下的变通代码,ensure 则是无论是否有异常都要执行。

语法如下。

begin
  ...
rescue
  ...
else
  ...
ensure
  ...
end

让我们举一个实际的例子。

current_year = 2022
birth_year = [USER INPUT]
begin
  age = current_year - birth_year
rescue InputError
  p "The input should be an Integer, '#{birth_year}' is not valid."
  age = 0
else
  p "Age: #{age}."
ensure
  p "Age calculation done."
end

在这种情况下,如果用户输入一个整数1990 ,异常将不会运行,返回的结果是。

#=> Age: 32.
#=> Age calculation done.

但是如果用户输入一个字符串,比如 "nineteen ninety",异常就会被执行。

#=> The input should be an Integer, 'nineteen ninety' is not valid.
#=> Age calculation done.

多次救援

rescue关键字可以在一个异常块中多次使用,创建一个多重救援来处理不同的异常。

虽然识别不同的错误类型以防止应用程序崩溃是很重要的,但作为良好的实践,有两个方面需要牢记。

  1. 永远不要强迫Ruby用标准救援来捕获所有的异常
  2. 不要试图为每一个可能的错误创建救援,并使你的应用程序过载。

在下面的例子中,我们可以看到在调用一个外部API时,针对不同的错误类型有不同的救援措施。另外,请注意,ensure 方法没有被实现,因为它是可选的东西。

begin
  ... API FETCH Request ...
rescue ErrorBadrequest
  p "400 BadRequest response"
  raise_support_alert
rescue ErrorTimeout
  p "Timeout error, retrying in 10 seconds"
  retry_api_call
else
  return data
end

循环救援

在Ruby中处理异常的另一个有用的功能是在循环中添加rescues 。比如说。

current_year = 2022
birth_year = [1990, 1999, 2001, "number", 2018]
ages = []
for i in 0..(birth_year.length - 1)
  ages[i] = current_year - birth_year
end rescue age[i] = 0
p ages
#=> [32, 23, 21, 0]

在这个例子中,由于 "number "不是一个有效的参数,异常被执行。请注意,这个循环并没有导致应用程序崩溃,但循环在第四次迭代时被中断。为了修正这一点,我们可以使用关键字retrynextRetry执行一个新的迭代,给出一个救援块,而Next则跳到下一个迭代。

上面的例子如果使用retry ,就会变成这样。

current_year = 2022
birth_year = [1990, 1999, 2001, "number", 2018]
ages = []
for i in 0..(birth_year.length - 1)
  begin
    ages[i] = current_year - birth_year
  rescue TypeError
    birth_year = 1995
    retry
  end
end  
p ages
#=> [32, 23, 21, 27, 4]

而使用next:

current_year = 2022
birth_year = [1990, 1999, 2001, "number", 2018]
ages = []
for i in 0..(birth_year.length - 1)
  begin
    ages[i] = current_year - birth_year
  rescue TypeError
    ages[i] = "invalid"
    next
  end
end  
p ages
#=> [32, 23, 21, "invalid", 4]

结论

  1. 异常使你的代码保持干净,并使其更具可读性,使其更容易理解。
  2. 代码的可维护性变得更简单,因为它更容易调试
  3. 它使你的应用程序更加灵活和可扩展。