Exception 何时使用自定义异常、现有异常和一般异常

Exception 何时使用自定义异常、现有异常和一般异常,exception,Exception,我试图找出对于我正在编写的库来说,抛出异常的正确形式是什么。我需要处理的一个例子是将用户登录到站点。他们通过扫描徽章来实现这一点。可能出错的事情包括: 他们的徽章失效了 他们没有在这个车站工作的许可 系统中不存在扫描的徽章 他们已经登录到其他站点 数据库已关闭 内部数据库错误(有时如果没有正确设置徽章,则会发生) 使用此库的应用程序必须以某种方式处理这些异常。他们可能决定只说“错误”,或者想给用户提供更多有用的信息。在这种情况下,最好的做法是什么?是否为每个可能性创建自定义异常?使用现有的异

我试图找出对于我正在编写的库来说,抛出异常的正确形式是什么。我需要处理的一个例子是将用户登录到站点。他们通过扫描徽章来实现这一点。可能出错的事情包括:

  • 他们的徽章失效了
  • 他们没有在这个车站工作的许可
  • 系统中不存在扫描的徽章
  • 他们已经登录到其他站点
  • 数据库已关闭
  • 内部数据库错误(有时如果没有正确设置徽章,则会发生)
使用此库的应用程序必须以某种方式处理这些异常。他们可能决定只说“错误”,或者想给用户提供更多有用的信息。在这种情况下,最好的做法是什么?是否为每个可能性创建自定义异常?使用现有的异常?使用异常并传入原因(
抛出新异常(“徽章已停用”);
)?我认为这是前两种的某种混合,在适用的地方使用现有的异常,在需要的地方创建新的异常(并在有意义的地方对异常进行分组)

使用异常并传入原因(抛出新异常(“徽章已停用”);)

这当然是一种不好的做法,因为它违反了异常的目的——不仅仅是为了表示异常情况,还提供了在类型级别区分异常的能力,因此模块的用户可以根据异常的类型做出决定


通常,只要标准异常能够完全描述代码实际面临的异常情况,就最好重用它们。在当前情况下很难给出建议,因为异常通常取决于语义(参数异常或无效操作异常(例如,可能适用于“他们的徽章已停用”的情况)。

我基本上同意您当前的想法

  • 在适当的情况下使用现有的核心异常:ArgumentException、InvalidOperationException等。不要尝试重新调整特定于其他模块的异常的用途。使用那些具有明确、通用目的的异常,不要将其用于业务规则。例如,
    InvalidOperationException
    应指示错误操作与API相关的操作,而不是违反业务规则
  • 对于特定于库的异常,请创建一个基本异常类,
    BadgeAuthException
    ,并始终抛出该类。特定场景应各自获得自己的子类(
    BadgeDeactivatedException
    NoPermissionsAtWorkstationException
    ,等等)这样,如果应用程序愿意,它们可以单独处理各个子案例,但如果它们不想屈从于细节,它们也可以捕获通用的
    BadgeAuthException
  • 无论您做什么,请确保
    消息
    字段始终包含除异常名称之外的有用信息

我认为,对于您描述的每种情况,您都需要有一个基本异常和一个子类型异常(实际上,您可以使db down和internal db error具有相同的基本异常)。关键点是,为您的库设置自己的异常是一种很好的做法。

您有两种异常

那些特定于您的应用程序的,最好避免任何现有的异常

您的应用程序特定异常应该简化使用您的库的人员的用例。您的应用程序特定异常中有3个是用户可以做的事情。第四个(徽章不存在)显然不是程序性的,但要严重得多

看起来您有两个特定于应用程序的错误:面向用户的错误和管理错误

其他的是其他一些技术的一部分,例如数据库错误。通常,您可以忽略这些错误。如果数据库不可用,API将抛出错误,您可以让这些错误在库中冒泡出来


你也可以“包装”这些异常是一个特定于应用程序的异常,其中包含一个较低级别的异常。如果有很多较低级别的技术,这有时会很有用。在您的情况下,它只是一个数据库。忽略它,让数据库错误冒泡过去。

通过使用扩展公共基本类的细粒度异常类,您几乎永远不会出错s、 这样,需要专门抓住一些人并让其他人通过的来电者可以,而想要一起对待他们的来电者可以这样做