明确提出例外的申请

时间:2016-04-11 15:37:46

标签: exception ada

在程序中明确提出异常有哪些应用和优势。例如,如果我们在这里特别考虑Ada语言提供了一个在程序中引发异常的接口。例如:

List

但是我们需要明确提出异常的优势和应用领域是什么?

例如,在接受其中一个参数为string:

的过程中
raise <Exception>;

如果我在上面的函数中引发异常并且在传递的字符串长度限制超过容许限制时处理它,是否有任何优势或良好实践?或者一个简单的If-else处理程序逻辑应该做生意吗?

4 个答案:

答案 0 :(得分:2)

显式引发异常以控制向子程序的用户报告哪个异常。 - 或者在某些情况下只是为了控制与引发的异常相关联的消息。

在非常特殊的情况下,您也可以将异常作为程序流控制引发。

答案 1 :(得分:2)

为了捆绑各个方面,我会给出2美分的答案。让我们从一般性问题开始

  

但是我们需要明确提出异常的优势和应用领域是什么?

提出异常有几个典型的原因。其中大多数都不是Ada特定的。

首先,可能存在使用或不使用例外的一般设计决策。一些一般标准:

  • 即使实际上从未抛出异常,异常处理程序也可能产生运行时成本(参见例如https://gcc.gnu.org/onlinedocs/gnat_ugn/Exception-Handling-Control.html)。这可能是不可接受的。
  • 与其他语言互操作性的问题可能会妨碍使用例外情况,或者至少要求没有人在Ada中编写部分程序。
  • 在某种程度上,决定也是品味问题。一个没有例外的语言的程序员可能会对依赖于检查返回值的设计感到更自信。
  • 有些程序会比其他程序更受益于异常。如果传统的错误处理模糊了实际的程序结构,那么可能是异常的时候了。另一方面,如果潜在错误很少,很容易被检测到并且可以在本地处理,那么异常可能会掩盖潜在的执行路径,而不是传统上处理错误。

一旦做出了使用异常的一般决定,就会出现问题,在不适合的情况下,在代码中提出它们是合适的。我在评论中提到了一个通用标准。我想到了什么:

  • 异常不应该是正常的,预期的程序流程的一部分(它们被称为例外,而不是期望 ;-))。这部分是因为控制流程更难以看到,部分原因是潜在的运行时成本。
  • 可以在本地处理的错误不需要例外。 (虽然为了进行统一的错误处理而提高一个仍然很有用。当我到你的代码片段时,我将在下面讨论。)
  • 另一方面,如果函数不知道如何处理错误,异常就很好。对于可以从各种上下文(GUI,控制台程序,嵌入式,服务器......)调用的实用程序和库函数尤其如此。异常允许错误在调用链中向上传播,直到某人可以处理它,而在中间层中没有任何错误处理代码。
  • 有人说图书馆应only expose custom exceptions,至少对任何预期的错误。例如。发生I / O异常时,将其包装在自定义异常中并显式raise该自定义异常。

现在来看你的具体代码问题:

  

如果我在上面的函数中引发异常并且在传递的字符串长度限制超过容许限制时处理它,是否有任何优势或良好实践?或者一个简单的If-else处理程序逻辑应该做生意吗?

我并不特别喜欢(虽然我觉得不太可怕),因为我上面的一般论点(“如果你能在本地处理它,不要提高”)会表明一个简单的if / else更清晰。 1 例如,如果函数很长,异常处理程序将远离错误位置,因此可能想知道异常可能发生在哪里(找到一个raise位置是不能保证一个人找到了所有这些,所以审稿人必须仔细检查整个功能!)。

但这取决于具体情况。如果在多个地方发生错误,则引发异常可能会很优雅。例如,如果几个字符串可能太短,通过异常处理程序进行集中式错误处理可能会很好,而不是在函数体中散布if / then / elses(嵌套??)。情况非常普遍,a legitimate case can be made for using goto constructs语言没有例外。一个例外显然是优越的。

1 但在所有现实中,你如何处理那个错误?你有一个有保障的伐木设施吗?你有什么回报?调用者是否知道结果可能无效?也许你应该扔掉 not catch。

答案 2 :(得分:2)

给定示例有两个问题:

  1. 控制流程不需要例外,这很简单。然而,情况并非总是如此,我马上回过头来。
  2. Constraint_Error是一个非常糟糕的例外,用于检测字符串长度错误。标准异常Program_ErrorConstraint_ErrorStorage_Error应该保留用于编程错误条件,并且在大多数情况下应该在可执行文件损坏之前将其删除,并提供足够的调试信息(至少是一个堆栈追溯)让你找到错误并保证它永远不会再发生。
  3. 非常令人满意的是让Constraint_Error尴尬地指向你的错误,而不是后来发生的任何未定义的行为......(学习如何开启它是有用的堆栈回溯,默认情况下通常不会启用。)

    相反,您可能希望定义自己的String_Size_Error异常,提出并处理它。然后,未正确的代码中提升Constraint_Error的任何其他内容都将被正确调试,而不是静默生成错误的Chars_Ptr

    对于提高异常的有效用例,请考虑使用SPICE(或用于气体流动的CFD模拟器等)的电路仿真器。由于矩阵计算中出现的数值问题,这些工具即使在正常工作时也容易出现故障。 (两个项取消,产生零+/-舍入误差,这导致不可靠的大数或稍后被零除)。它通常是迭代近似,其中误差应该在每个步骤中减小,直到它具有可接受的低值。但如果发生故障,错误术语将开始增长......

    通常,模拟逐步进行,其中每个步骤都是足够小的时间步长,可能是1 us或1 ns。主循环请求一个步骤,并且该请求被传递给模拟中代表电路中的组件或CFD网格中的三角形的数千个代理。

    这些代理中的任何一个都可能无法计算解决方案,处理失败的最简单方法是引发异常,可能是Convergence_Error。可能存在数千个可能引发异常的点。

    测试成千上万的返回代码会很快变得难看。但是除了例外,主循环只需要一个处理程序,它需要采取一些纠正措施,例如减少模拟步长并再次运行步骤。

    在浏览器中清理用户文本输入可能是另一个很好的用例,更接近示例代码。

    关于异常的运行时成本的一个词:Gnat编译器及其RTS支持&#34;零成本异常&#34; (ZCX)模型 - 至少对某些目标而言。在提出异常时会有更大的惩罚,作为在正常情况下消除罚款的权衡。如果惩罚对您很重要,请参阅文档以了解您的情况是否值得。或者

答案 3 :(得分:1)

例外情况应该与他们的名字保持一致,即代表特殊情况。