10.2 太多的异常
程序员通过定义不必要的异常,加剧了与异常处理有关的问题。大多数程序员都被告知,检测和报告错误是很重要的;他们常常把这句话理解为“检测到的错误越多越好”。这就导致了一种过度防御的风格,任何看起来甚至只是有点可疑的东西都会被异常拒绝,这会导致不必要的异常激增,增加了系统的复杂性。
我自己在设计Tcl脚本语言的时候就犯了这个错误。Tcl包含一个unset
命令,可以用来删除一个变量。我定义了unset
使其在变量不存在时抛出一个错误。当时我想,如果有人试图删除一个不存在的变量,这一定是个错误,所以Tcl应该报告它。然而,unset
最常见的用途之一是清理由先前操作创建的临时状态。通常很难预测到底创建了什么状态,尤其是在操作中途中止的情况下。因此,最简单的做法是删除所有可能已创建的变量。unset
的定义使得这种情况变得很尴尬:开发者最终会把对unset
的调用包裹在catch
语句中,以捕捉和忽略unset
抛出的错误。现在回想起来,unset
命令的定义是我在设计Tcl时犯的最大错误之一。
使用异常来避免处理困难的情况是很诱人的:与其想出一个干净的方法来处理它,不如直接抛出一个异常,把问题推给调用者。有些人可能会说,这种方法赋予了调用者权力,因为它允许每个调用者以不同的方式来处理异常。然而,如果你在特定的情况下很难搞清楚该怎么做,那么很可能调用者也不知道该怎么做。在这种情况下产生一个异常,只是把问题转嫁给别人,增加了系统的复杂性。
一个类所抛出的异常是其接口的一部分;有大量异常的类有复杂的接口,它们比有较少异常的类要更浅。异常是接口中一个特别复杂的元素。在被捕获之前,它可以通过几个堆栈层向上传播,所以它不仅影响到方法的调用者,还可能影响到更高层次的调用者(以及他们的接口)。
抛出异常很容易,处理异常却很难。因此,异常的复杂性来自于异常处理代码。减少由异常处理造成的复杂性损害的最好方法是减少必须处理异常的地方。本章的其余部分将讨论四种减少异常处理程序数量的技术。
Last updated