21. 区分业务异常和技术异常

区分业务异常和技术异常

        应用程序在运行时出错基本上是两个原因:阻止我们使用程序的技术问题和阻止我们错误地使用程序的业务逻辑。现代编程语言,例如LISP,Java,Smalltalk和C#,使用异常来标识这两种情形。然而,这两种情况有很大的区别,应该仔细地分辨。使用相同的层次的异常来表示这两种是造成混淆的潜在原因,更别提使用相同的异常类了。
        当程序出错时,一个不能解决的技术问题就会发生。比如,如果你尝试访问一个只有17个元素的数组的第83个元素,程序就明显出现偏差了,应该会导致异常。更难以察觉的版本是使用不当的参数调用某些库里的代码,导致库内部出现同样的状况。
        尝试自己解决这些你导致的异常情况是不对的,取而代之的是,我们让异常到达架构的最上层,并让一些通用的异常处理机制做它能做的来确保系统处理安全状态,例如回滚一个事务,记录日志或者告警给管理员,并(礼貌地)回报给用户。
        这种情况的一个变体就是当你使用“库情形”时,一个调用者打破了你的方法的约定,比如,传一个非常怪异的参数或者没有正确地创建一个依赖的对象。这和从17个元素中访问第83个是一样的:调用者应该先检查;不检查则是使用者程序员的错误。正确的回应则是抛出一个技术异常。
        另一种不同的但也是技术上的情况是,运行环境中的问题导致程序不能处理,例如数据库不响应。这种情形你应该假设基础架构做了它可做的来解决这种问题——修复连接并重试合理的次数——但失败了。尽管产生的原因不同,调用者代码是相似的:它几乎无能为力。所以,我们通过一个异常来标识这种情况,并让它向上到达通用的异常处理机制。
        和这些相对的是,我们因为业务逻辑的原因不能完成调用时也有这种情况。这种情况下,我们也遇到了异常,也就是非常的、不合要求的,但不是异常或者程序错误。比如,我尝试从一个金额不足的账户中提现。也就是说,这种情况是约定的一部分,抛出异常只是一个返回路径,是模型的一部分,客户端应该了解并做好了处理的准备。这样的情况中,创建一个特别的异常或者区分异常的处理层次才是恰当的,这样客户端可以用他自己的术语来处理这些情况。
        把技术异常和业务异常混合在同一个层次,模糊了二者的区别并会让调用者对方法的约定是什么、调用前应该确保什么条件、处理什么情形产生疑惑。分离二者则更明确,增加技术异常被应用框架处理、业务领域异常由客户代码考虑和处理的机会。

原文:Distinguish Business Exceptions from Technical by Dan Bergh Johnsson

你可能感兴趣的:(程序员应该知道的97件事)