什么时候应该抛异常?

前言

说到异常,之前一直不是太理解它的作用,项目中有用到基本都是数据库事务上。
比如:添加一个新数据,修改一条旧数据,有异常,回滚事务,没有则提交事务。这几天在给公司的支付项目开发 SDK ,又重新查一下资料,有一番新的认识,顺便记录下来。

什么时候应该抛出异常?

按照面向对象的单一职责原则,一个类只应该关心自己的逻辑,当出现问题的时候,如果不是当前类该处理的,我们就应该抛出而不是消化。怎么理解呢?比如,请求一个根据用户 id 获取用户信息接口的时候,网络出现问题,HTTP 请求库抛出了异常,这时候应该抛出异常。可是为啥不是 catch 异常然后返回 false 呢?这就涉及到边界问题了,业务异常与运行时异常要区分开,对方接口返回你要查询的 id 不存在,返回错误,这属于业务异常,这时候是不会抛出异常的。而你请求的 API 不存在,或者对方服务器宕机,或者你的服务器网络出问题,这属于运行时异常,就应该以异常抛出来告知调用方,而不是自主处理该异常并返回 false 来结束逻辑。

可能刚开始你是不太好理解,其实说白了就是边界问题。当你有更多的应用设计与代码实践经验后你会慢慢感受到这个边界。

异常的分类和命名

由于异常情况有很多,所以我们自定义异常类时通常需要做分类,方便排查原因,这是最佳实践,可以看看开源的框架、类库的源码,基本都是把异常做了分类。至于命名,先看 PHP 内置异常类是如何命名的。

  • BadFunctionCallException
  • BadMethodCallException
  • DomainException
  • InvalidArgumentException
  • LengthException
  • LogicException
  • OutOfBoundsException
  • OutOfRangeException
  • OverflowException
  • RangeException
  • RuntimeException
  • UnderflowException
  • UnexpectedValueException

自定义异常类我们直接参考 PHP 内置异常类命名就好,按名称来命名:

  • 参数错误,当传入的参数不合法时,我们通常抛出异常;
  • HTTP 异常,在请求 API 时异常终止时抛出的异常;
  • 其它异常,模块其它部分异常。

当然还有其它的,你可以命名非常细,比如 HttpExceptionErrorResponseException 等等,只要做到命名规范、清晰易懂即可。

自定义的异常需要继承 PHP 内置的异常类 Exception,可以不包含任何方法。

打赏作者

您将是第一位评论人!

提醒
avatar