修复未知错误是否属于重构
2004 年 9 月 3 日
Przemyslaw Pokrywka 提出一个有趣的问题。在 这本书 中,重构之一是 引入空对象 - 一个非常有用的重构(也在 Josh 的新书 中讨论)。Przemyslaw 的观点是,这种重构会改变行为。如果你让一个方法返回 null,然后调用该 null 上的方法,你将得到一个空指针异常。如果你使用空对象,你将得到一些默认行为。
现在,许多重构确实会改变行为,实际上它们就是为了改变行为而设计的。如果你应用 形成模板方法,那么程序的行为就会不同。关键问题是这是否是我在 重构定义 中所说的可观察行为。也就是说,它是否改变了程序的本质行为?对于引入空对象,你必须查看程序中操作返回引用的地方,通常是通过检查它是否为 null。这就是为什么这是一种比较棘手的重构。
这个难题的有趣之处在于,如果你错过了存在错误的地方会发生什么。在你的程序中的某个地方,你调用了 null 引用上的方法。在重构之前,你会得到一个异常,我们假设这里是一个你不知道的异常,它一直传播到某个顶层处理程序。重构之后,你得到了默认行为 - 这实际上可能修复了错误。如果你修复了一个你不知道的错误,这仍然是重构吗?
我认为是的,因为你不知道或不在乎(足够)错误的行为,那么我认为这种行为不可观察。即使你知道了错误,我仍然认为,如果错误不是你想要保留的行为,那么称之为重构是可以的。
这是一个有趣的情况,我可以很容易地想象自己改变主意或探索更多边缘情况。
它指出的一个有趣的事情是手动重构和工具驱动重构之间的区别。在手动重构中,你可以做出这样的判断,而工具通常必须更加谨慎。然而,即使是工具也不能总是保证保留行为 - 即使是重命名方法,如果该方法通过反射调用,并且名称是从文件中读取的,那么重构也可能失败。