《重构——改善既有代码的设计》读书笔记(七)

一、简化函数调用

首先是一些优化函数的原则:

①函数名、参数名要能表达出其所代表的作用;

②函数的参数个数应尽量的少;

③对函数的参数表明是否值可变(const);

④修改值与查询值的操作应当分开;

⑤函数内的一切应对外不可见;

简化函数的方法:

1. 为函数取一个正确的名字;

函数名一定要能表达出这个函数的功能,因为之前就一直在提“一个函数应该只做一件事”,如果这一条能尽可能的执行的话,那么为函数起一个简单正确的名字就是很容易的一件事,如果遇到某一个函数不知道该如何取名,那么很可能是这个函数的功能被你设计的过于复杂了,这时应首先考虑函数内的部分是否又可以被分层或独立的代码段;还有一种情况是可能要给函数取一个与另一个函数极为相似的名字,那么这时应该对比两个函数,看功能是否一致是否可以统一为一个函数,如果两个函数功能不一致的话就不应该出现取名近乎相同的情况。而且取名时要尽可能的详细,不要怕函数名字长,我最开始时就很不喜欢起长名字的函数,现在这个坏习惯我也在改,当然函数名字还是越短越好,但是前提是你可以用足够少的词汇清晰表达其作用。

2. 合理添加/删除函数参数

首先,函数参数越少越好,那么就是在保证函数功能正常的情况下应减量少执行添加参数这种操作。遇到需要添加参数的情况时,首先考虑是否可以用别的操作代替,例如在调用这个函数的地方加一个条件语句,或是检查函数内实现的功能是否过多导致需要添加参数,还有可能因为数据结构的变化导致原来的参数可能需要与另一个参数一起才能起作用,那么这时应该为这种关联性的数据建立一个新的对象,把新建立的对象类型穿进去而不是单单的添加一个参数。还有时是调用函数成立条件不同而导致为其添加参数,这时某个参数可能只有在某些情况下会用,这时要考虑用多态来实现。

3.查询函数与修改值的函数分离

4.同类功能用参数区分

例如有这样两个函数

double GetTwoDecimal()
{}
double GetFiveDecimal()
{}

从名字来看他们的功能分别是取小数点后两位与取小数点后五位的值,里面可能但部分代码是一致的,那么它就可以化为:

double GetDecimal(int nDigit)
{}
只需要根据传进去的参数“位数”来判断返回几位就可以了

5.以具体函数取代参数

大概就是说当我们明确知道自己需要做什么或取什么的时候,直接去调用对应的函数,而不需要调用一个根据我们传入的参数来给我们对应返回值的函数。这是书中的例子:

6.保持对象完整

当一个函数的参数是你取自某个对象的某些值时,可以考虑直接将整个对象作为参数传递进去,这样做的好处是可能以后如果这个函数中再需要这个对象的别的值就可以直接从对象取到,而且相比传值参数个数很可能更少。

我觉得这种方法有些时候不太好,有时可能传递的值是某一个很大的对象的成员,例如我现在在维护的代码有一个类,光是成员变量就有2000+,那么为了给一个函数所用到的3、4个参数简化为一个而直接传递一个这种对象进去,可能对程序运行效率造成不好的影响,作者也提到了当参数只是某个对象的某几个值(个数很少)时,不需要使用这种方法,但可能我觉得如果是我上面用的那种成员变量2000+的对象,就算你的参数是多个对象的值,而同时函数内部代码也很复杂时,我还是不会传递这个对象。

7.以函数取代参数

有些时候传递进去的某些参数我们可以在函数内使用另外的函数取到,或是计算得到,这时可以去掉对应的参数。当然如果又计算得到很耗费时间和资源,那么还是传递参数好。

8.移除设值函数

某些字段可能只会在创建时被赋值,其余时候不应该被改变,那么就不要给他写一个赋值函数。而且最好为他加一个const final之类的。这个操作最好是在写代码最后阶段进行。

9.隐藏函数

保持函数的封装性,本身类外没有用到的函数设置为private。我个人的习惯是在声明函数时全部定为private,当有函数被外界用到时,再修改为public。

10.以工厂函数取代构造函数

简单来说就是将第5条的操作逆执行。

11.封装向下转型

这个还是用作者的代码表示吧:

12.异常取代错误码,以测试取代异常

“异常”应该被用于异常的、罕见的行为处理,也就是用于处理那些在我们预期之外出现了的问题。

而如果一段代码执行之前我们就能猜到可能会出现某些问题,就要添加对应的测试代码,例如数组下标越界这种。

 

 

二、处理概括关系

1.字段、函数上移

多个子类拥有相同的字段(函数),将这个字段移到父类中

2.构造函数上移

各子类中的构造函数几乎一致,让他们共同使用父类的构造函数

3.函数、字段下移

父类中的某个函数或字段只有特定的子类使用,将这些字段/函数下移到对应的子类中;

4.提炼子类

类的某些特性只有一种情况会被用到时,将这些特性单独提炼为一个子类;

5.提炼父类

两个类有相似特性,将这些特性提炼到一个新类中,并将这个新类设为原来的两个类的父类;

6.折叠继承关系

超类和子类区别不大时,删除其中一个

7.委托取代继承

某个子类只使用父类接口的一小部分,或父类的数据对该子类完全无意义,那么就将原本的父类编程原本子类的一个成员,再通过该成员实现原本的功能。

8.继承取代委托

两个类具有委托关系,并为了这种关系要编写一系列极简单的委托接口,可以考虑将委托关系改变为继承。

 

这是处理概括关系是书中第十一章的内容,讲的主要是如何处理关于继承机制的相关问题,其实这些方法就是为了提醒开发者要始终遵循继承最开始的含义:父类是对一系列相同事物的抽象,子类是继承与父类而又有自己独立的发展。在代码中具体就是将子类共同的部分放在父类中,独属于一个子类的特性只在对应子类中可见。只要在使用继承关系时始终牢记这种原则,继承关系的使用其实不会有太多问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值