代码之家  ›  专栏  ›  技术社区  ›  Ryan Elkins

何时使用自定义异常vs.现有异常vs.一般异常

  •  11
  • Ryan Elkins  · 技术社区  · 14 年前

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

    • 他们的徽章失效了
    • 他们无权在这个车站工作
    • 系统中不存在扫描的徽章
    • 他们已经登录到别处的另一个站点
    • 数据库关闭
    • 内部数据库错误(如果徽章设置不正确,有时会发生)

    使用此库的应用程序必须以某种方式处理这些异常。他们可能会决定说“错误”,或者想给用户更多有用的信息。在这种情况下,最佳做法是什么?为每个可能性创建自定义异常?使用现有异常?使用异常并传入原因( throw new Exception("Badge is deactivated."); )?我认为这是前两种方法的混合,在适用的地方使用现有的异常,在需要的地方创建新的异常(在有意义的地方对异常进行分组)。

    5 回复  |  直到 14 年前
        1
  •  6
  •   S.Lott    14 年前

    你有两种例外。

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

    特定于应用程序的异常应该简化使用库的人员的用例。3个特定于应用程序的异常是用户可以做的事情。第四个(徽章不存在)显然不是程序性的,而是更加严重的。

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

    其他的是其他技术的一部分,即数据库错误。一般来说,你可以忽略这些。如果数据库不可用,api将抛出错误,您可以让这些错误在库中冒出来。

    您还可以将它们“包装”为包含较低级别异常的特定于应用程序的异常。如果有很多较低级别的技术,这有时是有帮助的。对你来说,这只是一个数据库。忽略它,让数据库错误冒泡通过。

        2
  •  10
  •   JSBÕ±Õ¸Õ£Õ¹    14 年前

    我基本上同意你现在的想法。

    • 在适当的情况下使用现有的核心异常:ArgumentException、InvalidOperationException等。不要尝试重新调整特定于某些其他模块的异常的用途。使用那些有明确、通用目的的异常,不要将它们用于业务规则。例如, InvalidOperationException 应该指出与api相关的错误操作,而不是违反业务规则。
    • 对于特定于库的异常,创建一个基本异常类, BadgeAuthException ,然后一直扔下去。具体的场景应该每个都有自己的子类( BadgeDeactivatedException , NoPermissionsAtWorkstationException ,等等)这样,应用程序可以根据需要分别处理各个子案例,但它们也可以只捕获一般的 徽章例外 如果他们不想在细节上卑躬屈膝。
    • 无论你做什么,确保 Message 字段总是包含除异常名称之外的有用信息。
        3
  •  8
  •   n535    14 年前

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

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

    一般来说,重用标准异常是很好的,因为它们可以完全描述代码实际面临的异常情况。在当前情况下很难给出建议,因为异常通常依赖于语义(例如参数异常或无效操作异常(例如,可能适合于“他们的徽章被停用”的情况)。

        4
  •  2
  •   bmargulies    14 年前

    通过使用扩展公共基类的细粒度异常类几乎永远不会出错。这样,那些需要特别捕捉一些并让其他人通过的呼叫者可以,而那些想要一起对待他们的呼叫者可以这样做。

        5
  •  1
  •   Andrew Bezzub    14 年前

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