“interface”。容易被理解、使用的接口,是开发良好面向对象软件的关键
良好的接口,只向用户展现必须展现的东西。如果一个接口暴露了过多的细节,需要将不必要暴露的东西隐藏起来,从而改进接口的质量
所有数据都应该隐藏起来。
所有可以隐藏的函数都应该被隐藏起来。hide method、remove setting method
修改函数名称。最简单、最重要。名称是程序写作者、阅读者交流的关键工具
只要能理解一段程序的功能,就应该大胆使用rename method,将自己所知道的东西传达给他人
在适当时机,修改变量名称、类名称
函数参数:add parameter、remove parameter
对象技术,可以保持参数列的简短
preserve whole object:来自同一个对象的多个值被当作参数传递
introduce parameter object:对象不存在,创建一个参数对象
replace parameter with method:函数参数来自该函数可获取的一个对象=》避免传递参数
replace parameter with explicit method:参数被用来在条件表达式中做选择依据
parameter method:为数个相似函数添加参数,将它们合并到一起
警告:
并发编程往往需要使用较长的参数列,可以保证传递给函数的参数都是不可修改的。
例如:内置对象、值对象一定是不可变的
可以使用不可变对象取代这样的长参数列。但必须对此类重构保持谨慎
separate query from modifier:明确地将“修改对象状态”的函数和“查询对象状态”的函数分开设计
replace constructor with factory method:不需要知道搞糟函数要创建的对象属于哪个类
encapsulate downcast:将向下转型封装隐藏起来,避免让用户做那种动作
replace error code with exception:以错误代码表示程序异常
replace exception with test:测试
1.rename method:修改函数名
问题:函数的名称未能揭示函数的用途
解决:修改函数名称
动机:
提倡的编程风格:将复杂的处理过程分解成小函数
做不好=》费尽周折,却弄不清楚这些小函数各自的用途
解决关键:给函数起个好名字。准确表达它的用途(将函数上的注释变成函数名称)
一个函数名称不能很好表达其用途,应该立即修改。
代码首先是为人写的,其次才是为计算机而写。而人需要良好命名的函数
起个好名称并不容易,需要经验。要想成为一个真正的编程高手,起名的水平至关重要,函数签名中的其他部分也同样重要
如果重新安排参数顺序,能够提高代码的清晰度,大胆去做。可运用add parameter、remove parameter
做法:
检查函数签名:是否被超类、子类实现过。
是:针对每份实现分别进行下列步骤
声明一个新函数,将其命名为新名称。将旧函数的代码复制到新函数中,进行适当调整
修改旧函数,让其调用新函数
找出旧函数的所有引用点,改而调用新函数
删除旧函数
如果旧函数是该类public接口的一部分,可能无法安全地删除它。这种情况下,将其保留在原处,并标记为deprecated(不建议使用)
注意:添加、去除某个参数,过程大致相同
2.add parameter:添加参数
问题:某个函数需要从调用端得到更多信息
解决:为此函数添加一个对象参数,让该对象带进函数所需信息
动机:
必须修改一个函数,修改后的函数需要一些过去没有的信息=》需要给该函数添加一个参数
不使用本重构的时机:除了添加参数外,还有其他的选择
只要可能,其他选择都比添加参数要好:不会增加参数列的长度
过长的参数列是bad smell:程序员很难记住这么多参数=》data clumps
提问:
1.能从已有参数中得到需要的信息?
2.能通过某个函数提供所需信息?
3.需要将这些信息用于何处?此函数是否应该属于用改该信息的哪个对象所有
4.针对现有参数,加入新参数是否合适?是否可以使用intruduce parameter object
并非绝对不要添加参数。但是,在添加参数之前必须要了解其他选项
做法:类似add parameter、remove parameter
检查函数签名是否被超类、子类实现过?是:针对每份分别实现下列步骤
声明一个新函数。名称与原函数同,只是添加新参数;将旧函数的代码复制到新函数中
如果需要添加的参数不止一个,将其一次性添加进去比较容易
修改旧函数,令其调用新函数
可以给参数提供任意值。一般会给对象参数提供null;给内置型参数提供一个明显非正常值;数值型参数,建议使用0以外的值,这样比较容易将其认出来
找出旧函数的所有引用点,将其修改为对新函数的引用,删除旧函数
如果旧函数是该类public接口的一部分,可能无法安全地删除它。这种情况下,将其保留在原处,并标记为deprecated(不建议使用)
3.remove parameter:移除参数
问题:函数本体不再需要某个参数
解决:将该参数去除
动机:
可能经常添加参数,却往往不愿意去掉它们:无论如何,多余的参数不会引起任何问题,而且以后可能用得上
恶魔的诱惑
参数代表着函数所需的信息,不同的参数值有不同的意义。
函数调用者必须为每一个参数操心该传什么东西进去。如果不去掉多余参数,就是让每一位用户多费一份心。很不划算,且“去除参数”是非常简单的一项重构
多态函数,情况有所不同,不能去除原有函数:可能多态函数的另一份(或多份)实现会使用这个参数,此时就不能去除它。