为啥抛出异常比返回错误代码更好?

Posted

技术标签:

【中文标题】为啥抛出异常比返回错误代码更好?【英文标题】:Why is it better to throw an exception rather than return an error code?为什么抛出异常比返回错误代码更好? 【发布时间】:2011-06-07 22:40:42 【问题描述】:

传统错误处理倾向于遵循所有函数根据成功/失败返回代码的方法。您将检查此代码并适当地处理(如果有错误)。

然而,现代编程语言遵循异常模型,如果发生无法正确处理的异常事件,则会引发异常 - 一直冒泡直到处理完毕。

我的问题是我们为什么要转向异常模型?这背后的原因是什么?为什么更好?

解释/链接将不胜感激。

【问题讨论】:

【参考方案1】:

这里有几个原因

忽略异常需要开发人员采取措施,而忽略错误的返回值则需要完全采取 0 措施。从理论上讲,这使得开发人员更有可能处理错误而不是忽略它,甚至没有意识到它正在发生。 在错误点和处理之间提供更清晰的分离。它不会强制在两者之间的每个点手动传播错误。 与简单的错误代码相比,异常可以提供更大、更丰富的信息负载。有很多方法可以使用错误代码来做到这一点,但这更像是事后的想法,而且有点麻烦。

【讨论】:

【参考方案2】:

我已经详细地写过这个:Exceptions vs. status returns,但简短地说:

    当每次调用都返回测试状态时,异常会让您的代码无需进行所有必要的检查, 异常允许您将函数的返回值用作实际值, 异常可以携带比状态返回更多的信息, 最重要的是:异常不能通过不作为而被忽略,而状态返回则可以。

扩展最后一点:如果您忘记对状态返回执行您应该执行的操作,您将忽略错误。如果您忘记对异常执行您应该执行的操作,异常会冒泡到软件的外层,并在那里变得可见。

【讨论】:

你不是没有把使用异常允许 try / catch (MyCustomException ex) 的事实排除在外,这样你/(其他开发人员)可以添加只会捕获新类型的 try / catch您创建的异常。 这是一个很好的观点。我喜欢层可以忽略异常并让它们通过。您的观点是可以细化到单个异常类型(假设您使用的语言支持按类型捕获异常)。 第 2 点:目前很多语言都有返回多个值的能力,消除了这种不便。第 3 点:异常通常是没有附加功能的标准类型,您可以返回任何类型并根据需要传达尽可能多的信息。但是,确实有些语言会在异常内部自动添加一些信息(堆栈跟踪等)【参考方案3】:

状态代码通常比异常更好,因为它们表示函数的立即调用代码准备处理的情况。状态码的问题在于,如果直接调用代码不处理它们,很可能什么都不会。如果代码抛出异常并且直接调用的代码没有准备好处理它,则异常将传播到至少声称已准备好的代码。

【讨论】:

状态代码似乎依赖于一个自定义的状态列表(除非该列表是原生的,如http 协议)。所以这似乎带来了直接的开销,而常见的编程语言似乎具有用于异常和操作符的本地构造来处理它们。这意味着更少的开销……函数式编程的典型特征。【参考方案4】:

Throwing an exception 明确指出了程序员难以忽视的问题(如果没有 catch 块,程序将终止)。

异常将终止函数其余部分的执行并将控制权传递给下一个catch块(如果当前调用堆栈中有任何异常。如果没有,则程序将终止)


对于 Javascript

是的,它是可选的,但您应该始终使用 .catch() 处理程序(用于 Promises)。

这意味着,我们可以在一个处理程序中处理许多函数中的许多错误,如下所示;

storeData()
    .then(changeSomething)
    .then(storeData)
    .catch((e) => 
        // Handle the error.
    )

在这里,我们可以看到如何同时处理三个不同功能的错误。从本质上讲,catch 的行为是将所有函数包装在一个同步的 try/catch 中。

【讨论】:

以上是关于为啥抛出异常比返回错误代码更好?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 IE 会在这一行抛出错误?

为啥在 V8Js 中运行时,Vue 路由器 beforeEach 中的错误不会抛出异常?

为啥我的 argparse 抛出 SystemExit 2 错误?

为啥我收到错误工厂方法'halLinkDisocoverer'在springboot中抛出异常?

为啥我的云函数返回带有代码 INTERNAL 的异常,并且详细信息为 null 并带有未处理的错误 TypeError: is not a function

PHP将抛出一个错误问题,怎么解决