首页 > 其他分享 >是不是“异常”让我的脑子糊涂了?

是不是“异常”让我的脑子糊涂了?

时间:2023-06-25 13:35:41浏览次数:26  
标签:脑子 James 代码 try Go 异常 我们 糊涂


是不是“异常”让我的脑子糊涂了?_编程语言

两卷书的试读内容均已在微信读书上线

"

《重构:改善既有代码的设计》的作者Martin Fowler曾说过,“异常很不错,但是 Java 的检查型异常带来的麻烦要比好处多。“

这种说法恰好与异常处理的设计理念背道而驰。时至今日,我们需要以一个更谨慎的态度去平衡编程中的得失,需要学会更辩证地思考语言功能设计带给的好处与麻烦,这有助于我们写出更加高效完善的代码。

下文是Bruce Eckel写于2011年的博文,从语言设计层面对比讨论Java与Go异常处理机制的理念,希望能够带给你新的思考。

是不是“异常”让我的脑子糊涂了?_编程语言_02

是不是异常让我的脑子糊涂了?

本文节选自《On Java 中文版 基础卷》

我的朋友James Ward当时正试图编写一些简单易懂的JDBC教学示例,但是检查型异常让他屡屡受挫。他还把Howard Lewis Ship的文章“检查型异常的悲剧”(“The Tragedy of Checked Exceptions”)指给我看。本来应该是很简单的事情,却要克服重重难关,这让他感到沮丧。甚至在finally块中,他也不得不加入更多try-catch子句,因为关闭连接也可能引发异常。这样下去,何时才能到头呢?我们被迫克服重重阻碍,却只是为了做一点简单的事(请注意,try-with-resources语句大大改善了这种情况)。

我们开始讨论Go编程语言,我对这门语言很着迷,因为Rob Pike等人明确提出了关于语言设计的很多基础且深刻的问题。基本上,他们会审视我们已经开始接受的关于语言的一切,然后问一下“为什么”。学习这门语言真的会引发你的思考和好奇心。

我的印象是,Go团队决定不做任何假设,只有在明确“某个功能是必要的”的情况下,才会推动这门语言的演化。他们似乎并不担心所做的修改会破坏旧代码——他们还创建了一个重写工具,所以如果他们做了这样的修改,这个工具可以帮着重写代码。这使他们可以把语言变成一个持续的实验,以发现什么是真正必要的,而不是做大而全的预先设计(Big Upfront Design)。

他们做出的最有意思的决定之一是完全不考虑异常。你没看错,他们不是仅仅舍弃了检查型异常,而是舍弃了所有的异常。

替代方案非常简单,而且乍一看和C语言很像。因为Go从一开始就纳入了元组,所以可以轻松地从一个函数调用返回两个对象:

result, err := functionCall()

(:=操作符让Go在这里定义result和err,并推断出它们的类型。)

每次调用我们都会得到一个结果对象和一个错误对象。我们可以立即检查错误(这非常典型,因为如果某个操作失败了,我们不太可能轻松地进入下一步),或者稍后再检查,如果可行的话。

这乍一看很原始,是向远古时代的倒退。但是现在我发现Go中的这个决策是经过深思熟虑的,并值得玩味。是不是异常让我的脑子糊涂了,我才有这么简单的反应?这对James的问题又有什么影响呢?

我忽然想到,我一直把异常处理看作一种平行的执行路径。如果遇到异常,我们就从正常的路径跳出来,进入这个平行的执行路径,就像一个“奇异世界”(bizarro world),在这里我们不再处理我们所写的东西,而是跳来跳去,进入了catch和finally子句中。正是这一替代性执行路径的世界,引发了James所抱怨的问题。

James创建了一个对象。理想情况下,对象创建不会引发潜在的异常,但是如果会的话,我们就必须捕捉。我们不得不在创建操作之后跟一个try-finally块来确保清理(Python团队意识到,清理并不是一个真正的异常情形,而是一个独立的问题,所以他们创建了一个不同的语言构造——with,以避免二者混淆)。任何会引发异常的调用都会停止正常的执行路径,并(通过平行的奇异世界)跳转到catch子句。

关于异常有个基本的假设:将所有的错误处理代码收集起来放在代码块的末尾,而不是在错误发生的时候直接处理,能够带来某种好处。在这两种情况下,我们都会停止正常的执行,但是异常处理有一个自动机制,可以将我们从正常的执行路径中抛出来,让我们跳入奇异的平行异常世界之中,然后在正确的处理程序中又会把我们送出来。

跳入奇异世界会给James带来问题,而且会给所有的程序员增加更多工作:因为我们无法知道什么时候会发生什么事情(我们随时有可能滑入奇异世界),所以就必须增加一层层的try块,以确保不会有什么东西从裂缝中漏掉。我们最终不得不通过额外的工作来弥补异常机制(这看起来类似于为弥补共享内存并发问题所做的额外工作)。

Go团队做了一个大胆的举动,他们对这一切提出了质疑,并说:“让我们试试没有异常的情况,看看会发生什么。”是的,这意味着我们通常要在错误发生的地方处理它们,而不是把它们全部集中到try块的末尾。但这也意味着关于一件事情的代码都位于一个局部,也许并不是那么糟糕。这可能还意味着,我们不能将公共的错误处理代码合并到一起了(除非识别出公共的代码,并将其放到一个函数中,也不是那么糟糕)。但这肯定意味着,我们不必再担心有多个可能的执行路径,以及由此引发的各种问题了。

你怎么看待编程语言中“异常处理机制”?


标签:脑子,James,代码,try,Go,异常,我们,糊涂
From: https://blog.51cto.com/u_15767091/6545065

相关文章

  • 异常的好处有哪些?
    首先,最重要的是,当你捕获并处理异常之后,你的程序就不会在遇到异常的时候突然崩溃,突然卡住其次,异常会包含堆栈信息,通过堆栈信息可以很方便地定位到出错的代码位置处理异常的时候,可以对异常重新包装,可以返回给前端和后台日志一些更容易识别的错误信息,以便快速理解程序异常。你可......
  • 自定义异常的作用
    自定义异常的作用,就是在程序中遇到异常的时候能够吧异常转换为相对应的可识别的错误类型,把相应的响应方式记录下来并抛出,最终在最外层的函数中捕获到这个自定义异常以便于从中取出合适的响应类型,返回给前端,而不是一味地搪塞,返回给前端空的数据。核心思想还是包装,把难懂的具......
  • 全局异常处理:优化 Flask 应用程序的可靠性与用户体验
    Flask是一个流行的PythonWeb框架,它提供了简单而灵活的方式来构建Web应用程序。然而,即使是最出色的开发人员也难以完全避免错误和异常的发生。用户可能会提交无效的数据,服务器可能会发生内部错误,或者应用程序可能会遇到不可预料的问题。在这些情况下,良好的错误处理机制对于保......
  • python入门(九):异常处理
    Python异常处理指南原文|大纲|首页在Python中,异常处理是一种重要的技术,用于捕获和处理程序运行时可能出现的错误。通过合理地处理异常,我们可以增加代码的健壮性和可靠性。了解Python的异常处理对于编写高质量的代码非常重要。异常基础异常是在程序运行过程中发生的错误......
  • java 异常处理,事务管理,事务共用,事务传递
    异常处理,事务管理,事务共用,事务传递1.在每个controller添加trycatch2.定义全局异常处理器/***全局异常处理器*/@RestControllerAdvicepublicclassGlobalExceptionHandler{@ExceptionHandler(Exception.class)//捕获所有异常publicResultex(Exception......
  • Hibernate3.x版本使用时遇到的异常
    换高版本的5.x就不会遇见,然后是因为少了一个依赖(竟然没在自己的导包配置里引用?还得自己加)maven中加<dependency><groupId>javassist</groupId><artifactId>javassist</artifactId><version>3.12.0.GA</version>......
  • Python开发系列课程(13) - 文件和异常
    文件和异常在实际开发中,常常需要对程序中的数据进行持久化操作,而实现数据持久化最直接简单的方式就是将数据保存到文件中。说到“文件”这个词,可能需要先科普一下关于文件系统的知识,对于这个概念,维基百科上给出了很好的诠释,这里不再浪费笔墨。在Python中实现文件的读写操作其实非常......
  • scala异常和IO
    异常处理语法处理上和Java类似,但是又不尽相同。java的异常处理publicclassExceptionDemo{publicstaticvoidmain(String[]args){try{inta=10;intb=0;intc=a/b;}catch(ArithmeticExceptione){//catch时,需要将范围小的写到前面e.printSt......
  • Android-Kotlin-函数表达式&String与int转换$异常处理
    Kotlin的函数表达式:packagecn.kotlin.kotlin_base03/***函数第一种写法*/funaddMethod1(number1:Int,number2:Int):Int{returnnumber1+number2}/***函数第二个种写法*/funaddMethod2(number1:Int,number2:Int)=number1+number2/***......
  • 在sql中使用函数,遇到net.sf.jsqlparser.parser.ParseException异常
    异常详情如下Causedby:net.sf.jsqlparser.parser.ParseException:Encountered""->""->""atline1,column31.Wasexpectingoneof:"AS"..."DO"..."ANY"..."KEY"...……(中间省略很多符号)atnet.......