用 try…except…提高代码的稳定性,是否是好习惯?
把每个可能出错的东西都套上 try…except,这样有什么坏处吗?
比如,是否会影响代码的执行效率?
把每个可能出错的东西都套上 try…except,这样有什么坏处吗?
比如,是否会影响代码的执行效率?
从程序执行流本身来看,异常的意义在于回滚调用栈
回滚调用栈。
如果你不确定是不是该上异常处理,那就判断一下此时是不是想把调用栈回滚到某个状态前。一个用异常处理的绝佳例子是 visitor 设计模式,当递归 visit 到某一个节点发生错误时,显然把 error code 穿过层层递归跟等于 nil 的 result 一起传回来是个非常蠢的做法(你甚至得给每一种节点类型的 visit 函数都写一遍 if err return ! shit !)
从业务逻辑上来看,异常处理机制是用来统一处理某封闭模块在各个阶段产生的同类错误用的
比如游戏读图,在每个关卡我要读不同的地图文件,文件读上来以后要解析数据结构,有可能读图失败,有可能结构不对,出错了以后我想让游戏回退到选图界面,那我肯定没理由在写游戏逻辑的地方还判断 loadNextStage()成功了没有,抛出异常可以让更上层的逻辑来处理同时打断游戏逻辑,其实还是对应回调用栈回滚的本质
再回头看为什么指南不建议你写 try except print 是不是理解一些了
出错了?出错了就出错了呗,崩了就崩了呗,崩了的时候你至少知道系统出错了。总好过你用 try exception 乱包一气,然后系统出错了还不明不白继续执行下去,等你注意到的时候可能已经过了好久,数据都因此乱七八糟了要好。
当然这里不是说你不该用 try,只是什么 try exception 的话对系统来说是个灾难
Java 里面似乎会用异常来负责一些错误码的功能,Python 听说甚至会用异常来代替部分控制流。但总体的思路就是这样。
如果你需要进程从头到尾按你的需求执行,不写 catch 块让他自然抛出才是建议的做法,但是比如你要执行一个循环查询,有异常只需记录你又不能枚举所有异常类型,那可以直接 catch 并存储。
但任何事情都有 trade off,抛异常直接跳出来确实比插一根管子层层返回错误要优雅,但也太过狂野。
当进行一个可能失败的操作时,使用异常就得包到一层 try 里面,错误跳到 catch 里处理,如果我想失败重试,整个控制流就会非常混乱。
这种情况直接返回一个包含了成功时的结果或失败时的原因的结构则要清晰很多,无论是直接裸返回再手写 iferr 还是包到 Result 里面用 pattern match,错误处理包含在常规控制流中。
日常使用时这种情况占绝大多数,所以较新的语言开始用直接返回替代异常控制流作为绝大多数情况下的错误处理方式,当然少部分时候有时也确实需要回滚,所以也有提供类似异常的 panic recover 机制,我觉得这是正确的发展方向。
公司项目里面都是这样的代码。。
❌ DO NOT use exceptions for the normal flow of control, if possible.
For example, you can provide a way to check preconditions before calling a member so users can write code that does not throw exceptions.
The member used to check preconditions of another member is often referred to as a [tester] , and the member that actually does the work is called a [doer] .
Tester-Doer Pattern https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/exceptions-and-performance
具体是你可能需要根据不同错误进行不同处理
否则建议全部都加上…
任何现代化的语言都不至于 catch 一下就不知道出错在哪,打个 ERROR Log,监控 ERROR Log 量,不要放任 ERROR 就行了
当然取决于你什么行业,什么方向,不同方向对于服务要求不同….
比如你直接把异常直接弄成 Exception 完全没有细化,又不去有针对性处理,还不如直接报错还能知道为什么错了。
但是凡事都有代价,写得 try 越多无效率代码就会浪费越多。