当代码、方法和类膨胀到了的程度,难以处理。通常这些代码的臭味不会立即出现,而是随着程序的发展逐渐积累,尤其是当没有人努力消除它们时。
1 过长参数列(Long Parameter List)
使用 Replace Parameter with Method(以函数取代参数) 来向已有的对象发出一条请求取代一个参数;
使用 Preserve Whole Object(保持对象完整) 将来自同一个对象的一对数据收集起来,并以该对象替换它们;
如果某些数据缺乏合理的对象归属,可以使用Introduce Parameter Object(引入参数对象)
为它们制造出一个”参数对象“。
2 过长函数(Long Method)
每当感觉需要以注释来说明点什么的时候,我们就把需要说明的东西写进一个独立函数中,并以其用途(而非实现手段)命名。
如果函数内有大量的参数和临时变量,灰度你的函数提炼形成阻碍。这个时候可以通过Introduce Parameter Object(引入参数对象)
和Preserve Whole Object(保持对象完整)
将过长参数列表变得简洁一些。如果这么做之后还是有很多临时变量和参数,可以使用Replace Method with Method Object(以函数对象取代函数)
。
条件表达式和循环也是提炼的信号,可以使用Decompose Conditional(分解条件表达式)
处理条件表达式。可以将循环和其内部代码提炼到独立函数中。
3 基本类型偏执(Primitive Obsession)
你可以运用Replace Data Value with Object(以对象取代数据值)
将原本单独存在的数据值替换为对象,从而走出传统的洞窟,进入炙手可热的对象世界。如果是类型码,可以使用Replace Type Code with Class(以类取代类型码)
将它替换掉。进一步,如果有类型码相关的条件表达式,可以使用Replace Type Code with Subclass(以子类取代类型码)
或Replace Type Code with State/Strategy(以State/Strategy取代类型码)
加以处理。
如果你有一组总放一起的字段,可以使用Extract Class(提炼类)
。如果在参数列表看到基本数据类型,可以试试Introduce Parameter Object(引入参数对象)
。针对数据,也可以运用Replace Array with Object(以对象取代数组)
。
4 数据块(Data Clumps)
常常可以在很多地方看到相同的三四项数据:两个类中相同的字段、许多函数签名中相同的参数。可以运用Extract Class(提炼类)
将它们提炼到一个独立对象中。针对函数参数,可以运用Introduce Parameter Object(引入参数对象)
或者Preserve Whole Object(保持对象完整性)
为它们减肥。
5 过大的类(Large Class)
如果类有太多实例,可以使用Extract Class(提炼类)
将类内彼此相关的变量提炼至新类内。
有时候并非所有时刻都使用类的所有实例变量,这个时候,可以多次使用Extract Class(提炼类)
或Extract Subclass(提炼子类)
。
和拥有太多实例类似,如果一个类有太多代码,也可以使用Extract Class(提炼类)
或Extract Subclass(提炼子类)
。可以确定客户端如何使用这个类,然后使用Extract Interface(提炼接口)
为每一种使用方式提炼一个接口,或许可以看清楚如何分解这个类。
对于大的GUI类,你可能需要把数据和行为一到一个独立的领域对象去,需要两边各保留一些重复数据,并且保持同步。这个时候Duplicate Observed Data(复制"被监视数据")
会告诉你该怎么做。