有两种情况应该捕获异常。
1. 尽可能低的水平
这是您与第三方代码集成的级别,例如 ORM 工具或任何执行 IO 操作的库(通过 HTTP 访问资源、读取文件、保存到数据库等等)。也就是说,您让应用程序的本机代码与其他组件交互的级别。
在此级别上,可能会出现您无法控制的意外问题,例如连接失败和锁定文件。
您可能希望通过捕获 a 来处理数据库连接失败,TimeoutException
以便您可以在几秒钟后重试。访问文件时的异常也是如此,该文件可能此时被进程锁定,但在下一个瞬间可用。
这种情况下的指导方针是:
- 仅处理特定的异常,例如
SqlTimeoutException
or IOException
。永远不要处理通用异常(类型Exception
)
- 仅当您有一些有意义的事情要做时才处理它,例如重试、触发补偿动作或向异常添加更多数据(例如上下文变量),然后重新抛出它
- 不要在此处执行日志记录
- 让所有其他异常冒泡,因为它们将由第二种情况处理
2. 尽可能高的水平
这将是您可以在将异常直接抛出给用户之前处理异常的最后一个地方。
您的目标是记录错误并将详细信息转发给程序员,以便他们识别和纠正错误。添加尽可能多的信息,记录下来,然后向用户显示道歉信息,因为他们可能对此无能为力,特别是如果它是软件中的错误。
第二种情况的指导方针是:
- 处理通用异常类
- 从当前执行上下文中添加更多信息
- 记录错误并通知程序员
- 向用户道歉
- 尽快解决
这些指南背后的原因
首先,异常是否代表不可逆的错误。它们代表系统中的错误、程序员犯的错误或应用程序无法控制的情况。
在这些情况下,用户通常无能为力。因此,您唯一能做的就是记录错误,采取必要的补偿措施,并向用户道歉。如果这是程序员犯的错误,最好让他们知道并修复它,朝着更稳定的版本努力。
其次,try catch
块可以根据使用方式屏蔽应用程序执行流程。try catch
块具有与 a 及其伙伴类似的功能,label
这goto
会导致应用程序执行流从一个点跳转到另一个点。
何时抛出异常
在开发图书馆的背景下更容易解释。当你遇到错误时你应该抛出,除了让你的 API 的使用者知道它并让他们决定之外,你无能为力。
假设您是某个数据访问库的开发人员。当您遇到网络错误时,除了抛出异常之外,您无能为力。从数据访问库的角度来看,这是一个不可逆转的错误。
这在您开发网站时有所不同。您可能会捕获此类异常以重试,但如果您从外层收到无效参数,则希望抛出异常,因为它们应该已在那里验证。
这在表示层中又是不同的,您希望用户提供无效参数。在这种情况下,您只需显示一条友好的消息,而不是抛出异常。
如https://roaddd.com/the-only-two-cases-when-you-should-handle-exceptions/中所述