异常处理的设计原则

正常优先

以 Go 语言的函数ReadFile为例。定义如下:

func ReadFile(filename string) ([]byte, error)

这个函数会将error返回。事实上,大部分 Go 语言 API 都有将error返回的特征。(推荐的)调用方式如下:

//...
data, err = ReadFile("example.dat");
if (! err) {
    //...
}
//...

一些编程语言的 API,会提醒使用者“异常可能会出现”,暗示使用者“马上去做异常处理”。然而异常处理的设计过程会中断正常逻辑思路。如果异常处理链过长,回归到正常逻辑的时候可能一脸懵逼。

因此,异常处理的首要原则是“正常优先”。也就是说,如果代码写到这里才发现“可能需要设计异常处理”(即异常处理不在原有的设计预期之中),那就无视之(最多留个注释),优先完成正常逻辑。

这里的“异常设计”是广义的,并不限定在try {...} catch (exception) {...}的形式上。准确来说,“异常设计”它还包含了“容错设计”。以下列 JavaSript 代码为例:

// add.js
export default function add (a, b) {
  return a + b;
}

这个函数的作用是计算两个数的和。请注意:JavaScript 不会验证参数和返回值的类型。所以,如果这个函数是个 API,调用者可能会传入类型不正确的参数,得到不正确的结果。例如:

// index.js
import add from './add.js';

console.log(add('3' + 4)); // 34

具备“异常设计”的代码是:

// add.js
export default function add (a, b) {
  if (typeof(a) !== 'number' || typeof(b) !== 'number') {
    throw 'Error: parameters must be number.'
  }
  return a + b;
}

例子中的if (condition) {...}严格来说属于“容错设计”,本文中将其归类为“异常设计”(调用参数异常),也应当遵守上文提及的“正常优先”原则。

自用忽略

异常设计的第2个原则是“自用忽略”。也就是说,如果开发者设计 API 只会被自己调用,则不要设计异常处理。

为自用 API 设计异常处理有两大弊端:

  • 浪费时间。开发者调用自己设计的 API,通常思路明确,不会产生错误。即使设计了异常处理,也几乎不可能被执行。设计过程本身就是在浪费时间。
  • 可能会屏蔽 IDE 的异常提示,增加调试难度。现在的 IDE 都具有强大的错误追踪功能,有的甚至能精确定位到源文件的行。设计不当的异常处理,会影响 IDE 的异常捕获,反而降低了开发效率。

如果自用 API 将要被发布,可能会被其他开发者使用,这时就需要考虑异常处理的问题了。

量力而行

异常设计的第3个原则是“量力而行”。也就是说,对因信息缺失或环境限制而无法处理的异常,或抛出(throw)或终止(terminate)或无视(ignore)。

例如:

  • 抛出:上文的add
  • 终止:程序执行时,首先从指定位置读取配置文件,则读取失败(文件不存在、IO设备异常等),则直接终止程序。
  • 无视:这个在Web前端中十分常见,若 fetch API 失败(本地网络切换、服务器访问量过大等),则可以无视之。因为用户可以自行刷新网页解决这类问题。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值