繁体   English   中英

如何管理API中的异常?

[英]How to manage exceptions in APIs?

好的,这是我在编写任何可重用的API(也称为代码)时始终存在的疑问。

你有什么例外? 有不同的可能性:

  • 总是把它们扔给客户 异常是累积性的,因此,如果方法A使用私有方法B,并且方法B引发异常,而方法A引发另一个异常,则客户端将看到2个异常,并且仅应看到最新的异常,因为这是他正在调用的方法。 我们可以积累很多例外。

  • 仅抛出在客户端调用的方法上产生的异常。 我们如何处理内部异常? 只是打印异常( printStackTrace() )? 将此已检查的异常转换为未处理的异常,因此我们只需要抛出它们?

  • 实现一个接口,客户端可以使用该接口来设置他的首选Log 我只是拒绝这样做。

  • 扩展RuntimeException并始终抛出您的自定义未经检查的异常。 向客户发布的所有方法都得到了很好的解释,并说如果履行合同,这些方法可能会引发异常。 我喜欢这种技术。

关于您的第一点-最好为您的API创建特定于域的异常层次结构(例如spring的DataAccessExceptions ),然后将所有输出包装到客户端。

关于已检查/未检查的异常的经验法则是:

  • 当客户端无法对错误执行任何操作时,将引发未经检查的异常
  • 客户端应处理错误时引发检查异常

关于第二点-如果内部错误以任何方式影响客户端,请不要隐藏内部错误。 另外,不要将错误信息输出到客户端可能不知道的侧通道(例如e.printStackTrace() )。 如果需要向用户提供非例外信息,则有两种选择:

  1. 提供接受某种Logger的方法
    • 优点:明确,没有其他依赖项
    • 缺点:API混乱,使用麻烦
  2. 使用SLF4J记录外观并以常规方式进行记录
    • 优点:保持API清洁
    • 缺点:依赖slf4j-api

您应该将异常返回给客户端调用的方法。 私有方法在API内部生成的异常应将异常抛出回客户端或捕获它并做一些有用的事情。 如果无法在生成异常的情况下继续执行,则应将异常回退到方法堆栈中。

通常,我喜欢通过扩展Exception或它的子类来使用异常。 因此,引发的异常类型更加有意义,并且更易于客户端理解。 因此,我通常会捕获然后扔出自定义标签。

通常最好通过扩展Exception来使用检查的Exception 它们通常更容易调试。 但是当然,在某些情况下,您可能希望使用未经检查的异常。

无论做什么,都不要使用返回值来指示特殊情况,这对于Java来说是不好的做法。 只是以为我会提到它,就像我以前看到的那样。

无论您在何处引发异常,请确保向其添加一条有意义的消息,客户端可以理解。

最终归结为您希望在API中获得的东西,但是在发生异常时,应始终使其易于使用和调试。

我不确定这是否属于您的第一项内容,但是我最好还是在内部捕获一个异常,然后引发一个新的特定异常,并将原始异常作为根本原因:

class A {
  void methodA() throws AException { /*...*/ }
}

class B {
  void methodB() throws BException {
    try {
      new A().methodA();
    } catch(AException e) {
      throw new BException("A problem occured in methodA", e);
    }
  }
}

当然,这可以导致一些嵌套的异常级别,但是优点是更好的信息隐藏(因为您不必通过内部方法抛出的异常来公开内部使用的方法),并且也可以使接口杂乱得多,因为您不需要在您的throws声明中最终有20个异常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM