返回错误码还是抛出异常?
首先,要明确一点的是,错误码和异常,这两者在程序的表达能力上是等价的。
它们都可以向调用者传达“与常规情况不一样的状态”。
考虑使用哪一种,更多地是从API的设计、系统的性能指标、新旧代码的一致性这3个角度来考虑的(本文主要从API设计的角度着手)。
我们返回异常, 比如return ResultUtil.fail( errorCode) , 如果直接把异常返回到用户使用层面 , 会有下面两点问题
- 总不能指望用户看懂java 的Exception
- 直接返回异常信息, 可能会造成安全问题
多使用异常机制的优点
- 不需要校验各种状态
- 而且异常信息方便排查错误
- 状态码字段
- 描述信息
- 异常调用栈
- 可以多自定义业务异常 , 然后使用异常机制,而不是使用状态码,然后各种校验。
举个例子, 注意下面的代码
1 | if(StringUtils.isAnyBlank(userAccount, userPassword,checkPassword)){ |
对于上面的每一种出现错误, 我们都需要手动去返回fail
, 这种方式与
throw new BusinessException(ErrorCode.PARAMS_ERROR,"账户或密码不能为空!");
看起来似乎一致, 返回的信息也大差不差
但是前提是当前我们实现的功能尚且简单, 逻辑比较简单, 并且出现异常的情况也比较少
那么如果我们以后业务复杂, 代码繁多, 如果还像上面这样一个一个的去手动返回异常,
效率将会十分低下, 而且代码也会看起来是否的臃肿
在这里的解决方法是定义异常类, 然后设置全局异常处理器 , 统一捕获异常,
然后以Result
的形式返回
比如上面的代码就改为
1 | if(StringUtils.isAnyBlank(userAccount, userPassword,checkPassword)){ |
规则1:本次发生的异常现象是不是真的非常罕见?非常罕见意味着发生该现象的机率非常低,调用方每次都处理将浪费大量的精力,但如果出现,系统应该明确终止,而不是继续往下执行,所以使用异常;其它情况,参考规则2。
规则2:本次发生的异常现象是不是出乎意料之外?出乎意料之外意味着系统已经出问题了(状态和预期不一致),被调用方没办法再往下执行了,而调用方如果不明确处理的话,系统也应该终止(因为系统状态出问题了),所以使用异常;其它情况,参考规则3。
规则3:遇到模凌两可的情况,则根据系统的性能需求(异常使用不当可能会造成系统抖动)、现有代码的情况(要保持一致的程序风格)以及开发人员的口味(怎么舒服怎么来)。
阿里规范
3.在代码中使用“抛异常”还是“返回错误码”?
- 对于公司外的 http/api 开放接口必须 使用“错误码”;而应用内部推荐异常抛出;跨应用间 RPC 调用优先考虑使用 Result 方式,封 装 isSuccess(通信状态)、“错误码”(业务状态)、“错误简短信息”。