异常的粒度


9

我和几个朋友之间进行了辩论。他们更喜欢一般性例外,例如作为例外的字段ClientErrorExceptionServerErrorException有详细信息,而我更喜欢使事情更具体。例如,我可能有一些例外,例如:

  • BadRequestException
  • AuthenticationFailureException
  • ProductNotFoundException

这些都是基于API返回的错误代码构建的。

遵循异常的优点,这对于Java来说似乎是惯用的。但是,我朋友的意见并不少见。

就代码可读性和API可用性而言,是否存在首选方法,或者它真的只是偏爱首选项?


您链接的页面可能是我们可以获得的最佳最终答案。您实际上是在征求意见。我可以用我的经验和看法来回答,但这不是客观的答案。
marstato

@marstato这很公平。我想我在寻找适合自己职位的理由。我宁愿遵守人们对我编写的库的期望,而不是遵循指南,如果它意味着它使我的东西更易于使用,你知道吗?

我绝对同意 我也有我的异常类粒度。另外,您可以abstract使用getter方法定义和泛化异常类,然后使细粒度类扩展通用类。例如AuthenticationFaliureException extends ClientErrorException。这样,每个用户都可以选择他们希望如何处理异常。显然,它还需要更多工作。但是,在编写应用程序(而不是库)时,恕我直言是另一种情况。在这种情况下,为简单起见,我不会使异常超出您的需要。
marstato

@marstato实际上就是我现在实现它的方式。很高兴您同意。我要把问题整夜打开,但是请把它合并成一个帖子,这样我至少可以绿色检查您了

Answers:


15

具有许多不同的异常类和只有少数几个异常类以及在错误文本中(例如)有更详细的信息之间的主要区别是,许多不同的异常类允许调用代码对不同类型的错误做出不同的反应,同时只有少数几个类可以更轻松地以统一的方式处理各种异常。

这通常是一个权衡。可以通过使用继承在某种程度上减轻这种负担(对于那些希望捕获和记录所有内容的调用者来说,这是一个通用的基本异常类,对于那些需要不同反应的调用者来说,它们是从这些基类派生的异常),但是即使这样,也会产生一个如果您不小心并遵循YAGNI原则,则会产生很多不必要的复杂性。因此指导性问题应该在这里:

  • 您真的希望代码的调用者对这些不同类型的错误以不同的控制流做出不同的反应吗?

没有一个千篇一律的解决方案,没有脑筋急转弯的“最佳实践”可以应用到任何地方。这个问题的答案在很大程度上取决于您要设计哪种软件或组件:

  • 在某个应用程序中,您或团队在哪里可以控制整个代码库?

  • 或某些可重用的第三方组件,您不知道所有潜在的呼叫者?

  • 一个长期运行的服务器应用程序,其中不同类型的错误不应该立即破坏整个系统,并且可能需要不同类型的错误缓解?

  • 一个短命的应用程序进程,如果发生错误,足以向用户显示错误消息,然后重新启动该进程?

因此,您对组件的潜在调用者了解得越多,就可以更好地决定样本的正确细节水平。


3
“您真的希望代码的调用者对这些不同类型的错误以不同的控制流做出不同的反应吗?” 这是一个很好的问题。谢谢,我要记住这一点。

我认为这是一个很好的答案,我只会进一步强调让客户端应用程序驱动异常抛出设计的必要性。即使是您可能认为明智的内置到异常层次结构中的通用化,也可能与客户端应用程序(如果不是您自己编写的)选择通用化处理程序的方式不匹配。如果您有多个具有不同需求的客户端应用程序,那么当然要平衡它们。
magicduncan

1

答案取决于我们所讨论的错误报告级别。

总的来说,我同意您的朋友们的意见,您不应该使他们变得比传达问题的原因更具体。

如果存在一个常见的众所周知的引用null的异常(NullReferenceException),则不应创建自己的MyObjectIsNullException。这只会给人类解释者增加一层混乱,这是需要学习的又不能澄清任何东西的东西。

仅当您的例外情况如此特殊,即没有预定义的例外情况可以涵盖根本原因时,才应创建自己的例外情况。

但是,您不必在那里停下来。常见错误可能发生在您的组件之一中,并且您可能想传达的是组件中存在问题。因此,不仅出了什么问题,还出了哪里。然后将第一个异常包装在MyComponentException中是合适的。这将使您两全其美。

首先,很明显,您的组件遇到了麻烦。在较低的杠杆上,具体原因可能是内部异常。


这还算公平。因此,您建议在已经存在一个好的例外时不要发明新的例外?

@rec是的,因为每个人都已经知道预定义的内容。那就是他们的目的。
马丁·马特
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.