是否有任何好的资源可以从架构的角度规划如何使用异常?(或者直接在这里提供你的建议。)在我工作过的项目中,我发现一些常见的异常被一遍又一遍地使用,并且往往失去了它们的意义。来自:http: //jamesjava.blogspot.com/2007/10/exception-plan.html
4 回答
我通常发现沉迷于检查的异常是矫枉过正的。应为程序无法合理恢复的意外错误情况保留异常。对于这些,我倾向于同意您观察到的内容,即特殊错误类型往往会失去意义。
作为一般规则,当满足以下所有条件时抛出异常:
- 无法从这里恢复状态。
- 不能合理地期望调用者从这种情况中恢复。
- 有人会想调试这种情况,所以他们可能想查看堆栈跟踪。
你会发现,如果这些都是真的,那么异常的类型并不重要,你还不如抛出 java.lang.Error。如果其中任何一个是错误的,那么异常可能是矫枉过正(你真的需要类型、消息和堆栈跟踪吗?)
相反,请考虑增加方法的返回类型以指示预期的失败类型。例如,对于在某些情况下不返回值可能有意义的方法,使用Option<A>类型。对于可能需要返回其类型取决于失败或成功的值的方法,请使用Either<A,B>类型。在您之前可能有专门的 Exception 子类型的地方,您可以改为使用 Either<Fail,A> ,其中 Fail 只是对预期失败类型的枚举。
我一半同意 Apocalisp 的评论。应为发生数据或处理错误但可以通过用户或系统干预恢复的情况保留异常实例。RuntimeException 的实例应该保留给那些在您的应用程序范围内没有干预可以解决问题的情况。因此,这两种类型被称为 Checked 和 Unchecked 异常。
未检查异常的一个示例是物理资源(例如数据库或消息总线)不可用。在这种情况下,RuntimeException 很好,因为您不打算让资源不可用,因此您的业务逻辑不必经常检查 DatabaseUnavailableException 或类似的东西。您可以以不同的方式处理 RuntimeExceptions(可能是 AOP 发送电子邮件)以报告中断并让员工或支持人员解决物理问题。
Checked 异常的示例包括数据输入不佳、数据访问不完整或业务逻辑实际上失败但可以检查和恢复的情况。例如,您搜索的用户不可用。这是您的业务逻辑中的一个单独条件,可以检查和处理(例如由应用程序的 View 部分,然后将异常消息作为错误消息报告给用户)。
许多框架都使用这个模型,而且它似乎比我以前看到的效果更好。
话虽如此,许多确实将检查的异常替换为返回的空值、-1、空字符串或 Number.MIN_VALUE。虽然这没关系,但如果您通常不期望数据源或方法中的这些值,它可能应该表示为异常。
“有效的 Java”,第 2 期。编。Bloch在第 9 章中有一些很好的建议。
“Hardcore Java”,Simmons在第 5 章中有一些很好的建议。
我还要无耻地提到我写了一个小工具来管理Java异常源代码。异常代码通常非常多余,您通常关心的只是类型。我的工具接受一个命名异常类型的配置文件,然后为这些异常生成代码。
我尝试确保使用 try/finally 的位置数量大大超过使用 try/catch 的位置数量。catch 通常被保留用于在顶层捕获异常——它们可以被合理地处理,或者处理来自平台 API 的异常。
在这种情况下,只要您给异常提供有意义的消息,并在必要时链接异常,无法通过其类来识别异常并不是什么大损失。我经常抛出 RuntimeException 而不是尝试为每个可能的错误情况开发一个异常类 - 但您对此的看法将取决于您在已检查与未检查异常辩论中所处的位置。