3

什么时候应该抛出自定义异常?

例如,我有一些连接到服务器的代码。连接到服务器的代码在连接失败时会抛出 IOException。在它被调用的方法的上下文中,这很好。在网络代码中也很好。

但是由于这表示没有连接(因此无法正常工作),所以异常一直到 ui。在这个阶段,一个 IOException 是非常模棱两可的。像 NoConnectionException 这样的东西会更好。

所以,我的问题是:你应该在什么阶段捕获一个异常,而不是抛出另一个更适合抽象的(自定义)异常?

4

5 回答 5

4

我希望异常会根据我要求原始方法执行的操作来讨论。例如

read -> ReadException
connect -> ConnectException
buildPortfolio -> FailedToBuildPortfolioException

等等。这抽象出了幕后发生的事情(即您是否通过套接字等进行连接)。作为一般规则,当我为组件创建接口时,我通常会创建相应的异常或一组异常。我的接口将被调用Component,我的例外通常是ComponentException(例如RateSourceRateSourceException)。作为一个完整的组件集导出到不同的项目是一致且容易的。

缺点是您创建了很多异常,并且您可能需要执行很多翻译。好处是(正如您已经确定的)您几乎没有抽象泄漏。

在方法调用(以及异常)的层次结构中的某个时刻,您可能会决定无法进行恢复(或者它位于不适当的位置)并转换为未经检查的异常以供以后处理。

于 2009-07-05T13:13:56.970 回答
1

我知道这被标记为“与语言无关”,但我不认为它真的如此。从 C++ 的角度来看,我预计很少有基本操作会引发异常 - C++ 标准库仅在极少数地方使用异常。所以我自己的代码往往是最先产生异常的地方。在该代码中,我喜欢一个非常扁平的层次结构——我不想在后面的代码中弄乱数百个 catch() 子句,并且从未理解 Java 和 C# 明显痴迷于创建类和命名空间的巴洛克层次结构。

因此,对于我的 C++ 代码 - 每个库包含一种有意义的错误消息的异常类型。一个用于最终的可执行文件。

于 2009-07-05T13:21:45.440 回答
1

我认为这里隐藏了两个问题:a)什么时候应该将一个异常隐藏在另一个异常后面。b)什么时候应该为此使用自定义异常。

a) 我会说:当异常跨越应用程序中的两层边界时,它应该隐藏在更适合新层的异常后面。示例:因为您正在执行一些远程操作,所以您会收到 ConnectionWhatEverException。

但是调用者不应该知道连接问题。因为他只是想执行一些服务,所以他得到了一个 ServiceOutOfOrderException。这样做的原因是:在层内部,进行远程处理时,您可能会使用 ConnectionException 做一些有用的事情(重试,写入回退队列......)。一旦你离开了那个层,没有人知道如何处理 ConnectionException。但是他们应该能够决定,当服务不工作时做什么。

b) 当没有匹配的现有异常时。例如,Java 中有几个有用的异常。我经常使用 IllegalState 和 IllegalArgument。一个新的异常类的一个强有力的论据是,如果你有一些有用的上下文要提供。例如,失败的服务的名称可能是 ServiceFailedException 的参数。只是不要为每个方法调用或任何类似的方法创建一个类。100 个异常类不是问题,只要它们具有不同的行为(即至少不同的字段)。如果它们仅在名称上有所不同并且位于相同的抽象级别,则将它们设为一个异常,并将不同的名称放在消息或该异常类的单个字段中。

c)至少在java中有关于检查异常的讨论。我将它们直接包装在未检查的中,因为我讨厌检查的那种。但这更多的是一种意见,而不是建议。

于 2009-07-05T14:58:51.440 回答
0

是否有任何情况下您会得到不是由 IO 问题引起的 NoConnectionException?相反,知道原因是否基于 IO 是否有助于客户明智地恢复?

于 2009-07-05T13:18:09.223 回答
0

什么时候应该抛出自定义异常?

I. 您何时可以提供更多(诊断)信息。

注意:在引发原始异常 (IOException) 的地方可能无法获得此附加信息。渐进式抽象层可能需要添加更多信息,例如您试图做什么导致此异常?

二、当您不能公开实现细节时:即您希望(幻觉?)抽象继续进行。

当底层实现机制可以改变时,这可能很重要。将底层异常包装在自定义异常中是将客户与实现细节隔离开来的好方法(通过提升抽象级别)

三、I 和 II

注意:此外,您的客户应该能够调整到他们感兴趣的确切信息级别,或者他们应该能够调整他们不感兴趣的任何内容。因此,从 IOException 派生您的自定义异常是一个好主意。

于 2009-07-05T14:21:08.583 回答