代码的坏味道之五 ——译自《重构》
夸夸其谈未来性Speculative Generality
Brian Foote 为一个我们都很敏感的味道建议的名字。你会遇到它当有人说“哦,我认为我们某一天会需要能力去做那一类的事”然后这样一来希望得到各种钓钩和特别的例子去处理并不需要的事情。结果往往是更难懂也难维护。如果所有的这些机制被用上,那这样做还是值得的。如果不是这样,也就不值得。这个机制就是这样产生的,所以处理掉它。
如果你有抽象类并没有做很多事,用Collapse Hierarchy.不必要的委托可以用Inline Class去掉。如果函数的某些参数未被用上,实施Remove Parameter。如果函数名称带有多余的意味,使用Rename Method。当函数和类的唯一用户是测试用例,夸夸其谈未来性可以被当成斑点。如果找到这样的函数或方法,删除它和调用它的测试用例。如果你有一个方法或类是调用遗产功能的测试用例的辅助,你当然不得不把他留在那里。
临时字段Temporary Field
有时你看到一个对象中的实例变量只在特定的情况下被设置。这种代码很难理解,因为你期待一个对象需要它所有的变量。试图理解为什么有一个变量但它并不被使用可以让你疯掉。
用Extract Class来为这些可怜的孤儿变量创建一个家。把所有关系到这个变量的代码放到这个组件里。你可能也能够当变量无效的时候依靠Introduce Null Object来创建可替换组件消灭条件代码。
一个普通情况出现临时字段是当一个复杂算法需要若干变量。因为实现代码的人不希望传入巨大的参数列表,于是他把他们放到字段里面。但字段只在算法中有效;在其他情况下他们只是普通的干扰项。在这种情况下你可以用对这些变量和需要他们的方法使用Extract Class。新的对象是一个方法对象。
消息链Message Chains
当一个客户向一个对象要求另一个对象,这个客户又向那个对象要求另一个对象,又要求另一个对象,这样,你看到消息链。你可能看到这些以一个长串getThis方法或者一列临时变量。这种方式的导航意味着客户与导航结构耦合了。任何中间关系的改变导致客户不得不改变。
在这里采取的行动是Hide Delegate。你可以在链中的多点这样做。原则上你可以对链中的每一个对象这样做,但这样做经常把每一个中间对象变成中间人。通常较好的替代是看结果对象被用来做什么。看能否使用Extract Method来取一部分代码然后Move Method来下压这个链。如果链中对象中其一的若干客户希望用这种方式导航剩下的,添加一个方法来这样做。
有的人把任何消息链当作糟糕的事。我们知道因为我们的冷静,有理有据节制。至少在这种情况我们是。