异常处理机制
在这篇文章中,我将分享错误处理的方式以及我们有哪些选择。错误处理是一个复杂的主题:-)
在深入探讨异常处理之前,我将从维基百科添加一些有关异常处理的上下文
异常处理是在计算过程中对异常 (例如异常或需要特殊处理的异常条件)的发生做出响应的过程,通常会打乱程序的正常执行流程 。 它由专门的编程语言构造, 计算机硬件机制(如中断或
操作系统 IPC设施,如信号 。
通常,异常会中断正常的执行流程,并执行预注册的异常处理程序 。 如何完成此操作的详细信息取决于它是硬件还是软件异常以及如何实现软件异常。 某些异常,尤其是硬件异常,可以如此优雅地处理,以使执行可以在被中断的地方恢复。
来源– https://en.wikipedia.org/wiki/Exception_handling
很少强调的是“ 破坏程序 执行的正常流程”,“预注册的异常处理程序”,硬件或软件异常。
因此它说明了什么是错误处理,所以我不会在上面花费时间。
有趣的一件事是2种类型的异常(硬件和软件)存在,硬件朋友很好地处理了它,并由软件工程师来完成。
一种软件是很难的,太多的编程语言使其变得更加困难。
我想让您参考最简单的测试可以预防的文章,在该文章中我试图解释错误处理错误的副作用,并且它纯粹是异常处理模式的结果。
C路
我确定您是否看到了这一点,并认为“这是正确的方法吗?” 。
C错误处理的代码片段
int main ()
{
FILE * fp;
fp = fopen ("somejunkfile.txt", "rb");
if (fp == NULL)
{
printf("errno: %d76485//", errno);
printf("Error opening the file: %s76485//", strerror//(errno));
exit(EXIT_FAILURE)
}
else
{
fclose (fp);
}
return 0;
}
这种方法有几个问题
–调用每个可能失败的函数后,您必须检查错误。
–此时,编译器无法强制/指示可能引发错误。
–错误处理是完全可选的
Java方式
然后出现了Java,并带着思维定式让我修复了所有错误处理,他们发明了选中/未选中的异常。
查看代码段
public void close() {
try {
this.writer.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
这种方法还有其他问题
–代码充满错误处理代码的冗长性
–编译器会强制您以错误的方式处理已检查的异常(即,将其记录或忽略)
–除了记录一些东西并将其包装在RuntimeExcetion中以获取传递的编译器之外,没有任何有意义的事情。
–包装会使情况变得更糟,因为您开始丢失导致错误的原因的上下文
功能编程方式
这个世界必须比“命令式”世界做得更好,他们做了什么? 发明单子。
def main(args: Array[String]): Unit = {
val res = divide(10, 0)
res match {
case Left(value) => println(s"Result is ${value}")
case Right(e) => println(s"Calculation failed reason ${e}")
}
val result = trydivide(10, 0)
result match {
case Success(r) => println(s"Result ${r}")
case Failure(error) => println(s"Failed to calculate reason : ${error.getMessage}")
}
}
使用这种方法时要考虑的事项
–您必须学习类别理论或单子论的技术术语
–现在给出2值,您必须编写较少的冗长代码来处理这两个路径
–由于价值的额外包装而导致的性能问题,当您拥有数百万个价值问题时,这会给您带来沉重打击
–没有编译时间安全性,调用者可以选择通过直接获取值来解决此问题
–我认为这是试图解决Optional / MayBe值的问题,其中您不知道为什么值不可用。
– Stacktrace消失了,在某些情况下它很有用,特别是在构建调用第三方库的系统时
去朗威
GoLang想做得比C / Java更好,并从Elm语言中汲取了一些灵感,并提出了委托或Killer(即Panic)方法
listener, listenError := net.ListenTCP("tcp", addr)
if listenError != nil {
return nil, fmt.Errorf("Listen: %s", listenError)
}
这是有趣的方法,但是
–在非常函数调用中使用err return时,调用者必须添加错误处理代码
–跟踪丢失,因此您必须非常小心地将所有上下文添加到消息中,以便可以进行恢复。
– Panic对库或框架不利,因为您无法终止该过程,必须由客户负责决定要做什么。
JavaScript / Python方式
我现在就离开。
没有明显的赢家,哪个选项是最佳选择,每种语言都在做一些折衷。 我们也不例外,例如Java ans和Go Lang,它是钟摆的2个末端。
可能有一个好的选择,即调用方可以决定使用哪种方法是Java Style或Go Lang。
分离控制流和错误的更好方法,因为在某些情况下错误的默认值可能是个不错的选择,或者只是清除/恢复或发送到上层以进行更好的处理。
因此catch块中的代码充分说明了客户端的需求,并决定了应该使用哪种错误处理模式。
我认为更多的是关于在上下文中正确使用模式的教育。
很高兴知道您对错误处理的看法以及应如何做。
翻译自: https://www.javacodegeeks.com/2019/08/exception-handling.html
异常处理机制