可能重复: 防御性编程与异常处理? if/else语句或例外
我经常看到一些热门的博客文章,其中作者使用了这样的论点:“异常与显式错误检查”来倡导他/她喜欢的语言而不是其他语言。普遍的共识似乎是,使用异常的语言天生比依赖于通过显式函数调用进行错误检查的语言更好/更干净。
是否认为使用异常比显式错误检查更好的编程实践,如果是,为什么?
发布于 2012-09-25 00:03:31
在我看来,最大的争论是程序员犯错误时会发生什么变化。忘记处理错误是一个很常见且容易犯的错误。
如果您返回错误代码,则可以默认忽略错误。例如,如果malloc失败,它将返回NULL并设置全局errno。所以正确的代码应该
void* myptr = malloc(1024);
if (myptr == NULL) {
perror("malloc");
exit(1);
}
doSomethingWith(myptr);但是,只写一篇文章是非常容易和方便的:
void* myptr = malloc(1024);
doSomethingWith(myptr);这将意外地将NULL传递到其他过程中,并可能丢弃精心设置的errno。代码没有明显的错误表明这是可能的。
在一种使用异常的语言中,您可以编写
MyCoolObject obj = new MyCoolObject();
doSomethingWith(obj);在这个(Java)示例中,new操作符要么返回一个有效的初始化对象,要么抛出OutOfMemoryError。如果程序员必须处理这个问题,他们可以抓住它。在通常(也是方便地,也是懒惰的)情况下,异常传播以相对干净和显式的方式终止程序。
这就是为什么异常,如果使用得当,可以使编写清楚和安全的代码更加容易。这种模式适用于许多可能出错的事情,而不仅仅是分配内存。
发布于 2012-09-25 01:09:42
虽然史蒂文的回答提供了一个很好的解释,但我发现还有一点是相当重要的。有时,当您检查错误代码时,您无法立即处理失败案例。您必须通过调用堆栈显式地传播错误。当您重构一个大函数时,您可能必须将所有错误检查样板代码添加到您的子函数中。
除了例外情况,您只需照顾您的主流。如果一段代码抛出一些InvalidOperationError,您仍然可以将该代码移动到一个子函数中,并且错误管理逻辑将被维护。
因此,异常允许您更快地重构和避免锅炉板。
发布于 2012-09-25 08:05:12
从不同的角度来看:错误处理都是关于安全性的。未经检查的错误破坏了以下代码所基于的所有假设和先决条件。这可能会打开许多外部攻击矢量:从简单的DoS对未经授权的数据访问到数据损坏和完全系统渗透。
当然,这取决于具体的应用程序,但是当假设和先决条件被打破时,所有的赌注就都取消了。在一个复杂的软件中,您根本无法确定从那时起什么是可能的,什么是可以和不能从外部使用的。
考虑到这一点,有一个基本的观察:当安全性被视为一个可选的附加组件,以后可以附加,那么它通常会失败。它最好的工作,当它已经考虑在第一个基本设计阶段和内置的权利从一开始。
这基本上是你得到的例外:一个已经内置的错误处理基础设施,是活跃的,即使你不关心。通过显式测试,您必须自己构建它。你必须建立它作为第一步。刚开始编写返回错误代码的函数,直到您进入应用程序开发的最后阶段,才会考虑全局,这实际上是一个附加错误处理,注定会失败。
一个内置的系统在任何方面都不起作用。大多数程序员不知道如何进行错误处理。大多数时候都太复杂了。
只要给我看一本学习者的书,在这本书中,错误处理从一开始就经过严格的设计,并最终在所有的例子中使用,而不会因为简洁和可读性而被遗漏,并作为读者的摘录。如果这适用于教育POV是另一个问题,但不足为奇的是,错误处理往往是足够的第二次或第三次思考,当它应该是第一次。
https://softwareengineering.stackexchange.com/questions/166039
复制相似问题