(不确定它是否只是一个C ++的东西)
未来怎么样?
是否有其他已知方法可以处理大多数语言中未实现的错误,或者只是大专院校的研究?
换句话说:是否(通常)知道更好(不完美可行)的方法来处理编程语言中的错误?
答案 0 :(得分:10)
嗯,总是有返回码,errno
等。一般的问题是那些不知道特定呼叫可能失败的程序员可以忽略或忘记这些。程序员也经常忽略或错过例外情况。不同之处在于,如果您没有捕获异常,程序就会死亡。如果不检查返回代码,程序将继续对无效数据进行操作。 Java试图通过创建已检查的异常来强制程序员捕获所有异常,如果您没有准确指定它们何时可以传播并最终捕获它们,则会导致编译错误。事实证明这非常令人讨厌,因此程序员会尽可能地将catch(...){/* do nothing*/}
(在C ++ parlence中)的异常捕获到尽可能接近其源,并且结果并不比忽略返回代码更好。
除了这两种错误技术之外,一些函数语言还支持使用各种monadic返回类型,这些类型可以封装错误和返回值(例如Scala的Either
类型,Option
类型或{{ 3}})。这些优点是 only 使用成功返回值的方法是在monad中执行代码,monad确保在出现故障时不运行代码。 (对于那些不是Haskell或Scala程序员的人来说,解释起来相当复杂。)我没有那么多地使用过这个模型,但是我认为对于某些人来说这会像检查异常一样烦人。
基本上,IMO,错误检查是一种态度问题。您有三种选择:
显然,你应该尝试成为#1类型的程序员。
答案 1 :(得分:6)
假设您希望代码根据是否发生错误而执行不同的操作,您基本上有三个选项:
1)在代码中的任何地方显示它(C样式错误返回值检查)。主要的缺点是它很冗长。
2)使用非本地控制流将错误处理代码与“通常路径”(例外)分开。主要的缺点是跟踪代码可以接下来的所有位置,特别是如果记录的接口并不总是列出所有这些。 Java的实验以及“处理”后一个问题的已检查异常也未完全成功。
3)坐上错误直到“以后”(IEEE风格的粘滞错误位和安静的NaN,流上的C ++错误标志),并且仅在方便调用者时检查它们。主要的缺点是设置和清除错误需要每个人仔细使用,并且错误站点上可用的信息可能会在处理时丢失。
接受你的选择。 (1)看起来臃肿而复杂,并且新手通过不正确检查错误来搞乱它,但每行代码都很容易推理。 (2)看起来小而简单,但是每一行代码都可能导致跳到谁知道哪里,所以新手通过不正确地实现异常保证来搞乱它,并且每个人有时会在错误的地方捕获异常或根本不捕获异常。 (3)设计得很好很好,但你永远不知道每行代码实际上做的几种可能性中的哪一种,所以在像C ++这样的富含UB的环境中也容易搞乱。
我认为基本问题基本上很难:处理错误会明显增加代码中的分支。在特定的代码中,处理错误会悄悄地增加您需要推理的状态量。
例外也有“它真的特别吗?”问题。您可以通过仅在整个程序无法恢复的情况下抛出异常来防止异常导致混乱的控制流。但是你不能将它们用于可以从程序的POV中恢复但不能从子系统的POV中恢复的错误,因此对于这些情况,你可以回到(1)或(3)的缺点。
答案 2 :(得分:5)
我不能说它比异常更好,但另一种选择是Erlang开发人员实现容错的方式,称为“让它失败”。总结一下:每个任务都是作为一个单独的“过程”产生的(Erlang的术语是大多数人所说的“线程”)。如果某个进程遇到错误,它就会死掉,并且通知会返回到控制进程,该进程可以忽略它或采取某种纠正措施。
这可能导致代码更简单,更健壮,因为整个程序不会因为缺少错误处理而崩溃或退出。 (请注意,这种健壮性依赖于Erlang语言和运行时环境的一些其他功能。)
Joe Armstrong的论文,其中包括一个关于他如何设想容错Erlang系统的论文,可供下载:http://www.erlang.org/download/armstrong_thesis_2003.pdf
答案 3 :(得分:1)
Common Lisp的condition system被认为是一个强大的超集,超出了你的例外情况。
答案 4 :(得分:0)
在我看到的系统中异常处理的基本问题是,如果例程X调用例程Y,它调用例程Z,这会抛出异常,Y没有干净的方法让其调用者在许多情况下区分:
我认为,这种困难源于这样一个事实,即异常类型集中在出现问题的问题上 - 这个问题在很多情况下基本上与如何解决这个问题正交。我希望看到的是包含虚拟“isSatisfied”方法的异常,并且尝试吞下异常,其isSatisfied方法返回false以抛出包含的异常,其isSatisfied方法将链接嵌套异常。某些类型的异常(如尝试将重复键添加到未损坏的字典)将提供无参数AcknowledgeException()方法来设置isSatisfied。其他涉及数据损坏或其他问题的例外要求AcknowledgeCoruption()方法传递损坏的数据结构,或者破坏损坏的数据结构。一旦在堆栈展开过程中破坏了损坏的数据结构,宇宙就会再次开心。
我不确定最佳架构是什么,但提供一种方法,通过这种方式,异常可以传达系统状态损坏或完整的程度,这将大大有助于缓解现有架构的问题。