例外和抽象

时间:2009-07-05 13:02:42

标签: language-agnostic exception abstraction

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

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

但是因为这表示没有连接(因此不起作用),所以异常一直到ui。在这个阶段,IOException非常暧昧。像NoConnectionException这样的东西会更好。

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

5 个答案:

答案 0 :(得分:4)

我希望能够根据我所要求的原始方法进行讨论。 e.g。

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

等。这抽象出了封面下发生的事情(即你是通过套接字连接等)。作为一般规则,当我为组件创建接口时,我经常创建相应的异常或异常集。我的界面将被称为Component,我的例外通常是ComponentException(例如RateSourceRateSourceException)。它作为一个完整的组件集一致且易于导出到不同的项目。

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

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

答案 1 :(得分:1)

我知道这被标记为“与语言无关”,但我认为不是。从C ++的角度来看,我希望很少有基本操作可以抛出异常--C ++标准库只在极少数地方使用异常。所以我自己的代码通常是可以生成异常的第一个地方。在那段代码中,我喜欢一个非常扁平的层次结构 - 我不想在代码中稍后弄乱数百个catch()子句,并且从未理解Java和C#对创建类和命名空间的巴洛克式层次结构的明显痴迷。 / p>

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

答案 2 :(得分:1)

我认为这里隐藏着两个问题: a)何时应该隐藏异常背后的异常。 b)何时应该为此使用自定义例外。

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

但调用者不应该知道Connection问题。由于他只是想要执行某些服务,因此他获得了ServiceOutOfOrderException。原因是:在图层内部进行远程处理,您可能会使用ConnectionException做一些有用的事情(重试,写入回退队列......)。离开该层后,没有人知道如何处理ConnectionException。但是,当服务不起作用时,他们应该能够决定做什么。

b)当没有匹配的现有异常时。例如,Java中有一些有用的Exception。我经常使用IllegalState和IllegalArgument。如果要提供一些有用的上下文,那么新的异常类的强大参数就是。例如,失败的服务的名称可能是ServiceFailedException的参数。只是不要为每个方法调用创建一个类,或者为此产生任何东西。 100异常类不是问题,只要它们具有不同的行为(即至少不同的字段)。如果它们仅按名称不同并驻留在相同的抽象级别上,则将它们设为一个Exception,并将不同的名称放在消息中或该异常类的单个字段中。

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

答案 3 :(得分:0)

是否有任何情况会导致NoConnectionException不是由IO问题引起的?相反,是知道原因是基于IO还是不能帮助客户明智地恢复?

答案 4 :(得分:0)

  

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

予。何时可以提供更多(诊断)信息。

注意:在抛出原始异常(IOException)的位置可能无法提供此附加信息。渐进的抽象层可能有更多的信息要添加,就像你想要做的那样导致了这个例外?

II。当你不能暴露实现细节时:即你希望(幻觉?)抽象继续。

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

III。 I和II都是

注意:此外,您的客户应该能够调整他们感兴趣的确切信息级别,或者他们应该能够调出他们不感兴趣的任何内容。因此,最好从中获取自定义异常。 IOException异常。