有一本书叫做《重构 改善既有代码的设计 》,个人感觉写的还蛮不错的,在读这本书时候做的一些读书笔记,分享给大家:
一点个人总结
重构可以理解为是一套体系,在这套体系中主要包括几个东西:
- 什么样的代码需要重构
------首先明确什么样的代码需要重构,通过代码的坏味道来分辨出有问题的代码 - 什么时候去重构
--------在工作中,在什么时间,什么场景更适合推动去重构 - 怎样避免引入新的问题
---------重构的第一步是为程序建立一组可靠的测试环境,用来保证重构不会引入新的bug重构方法 - 重构的方法
----------有一系列已经总结出来的方法和范式,可以碰到情况,直接去套
读书笔记
1. 首先什么样的代码需要重构:
1:函数过长
2:参数过多
3:类过大
4:类的功能不合理(A类中一个功能,大量依托B类中的参数,更应该把次功能移到B类)
5:平行继承关系(解决办法可以考虑在一个继承关系中引用另一个继承关系中的类,然后通过移动类的参数和方法,消灭另一个继承关系)
6:switch语句
7:如果修改一个小功能,要对多个类进行修改
8:一个类经常因为不同业务或者方向上的功能修改,而去修改这个类
。。。
2. 何时来重构:
1:Review代码
2:修改Bug
3:增加新功能
同时注意一个原则增加功能和重构进行分离,重构时候专注重构,当增加功能时专注增加功能
3. 建立可靠的测试环境:
1:这个首先是自动化测试的环境,过于不过,对不对自动来判断
2:主要加大力度测试容易出错的地方,简单的set get不用来搞
3:重点测逻辑边界的地方
4:有bug,要增加测试case
4. 重构方法:
细化方法,更小颗粒度
方法移动到别的类
抽象出新的类
内部类
随手记
1:分解长长的函数
<1>对于函数中的局部变量进行查看,对于那些会改变的局部变量可以考虑通过另一个函数的返回值获取
<2>在程序实现中,往往有些组合类,它里边的功能依托于多个类来实现,比方说其中一个比较重要的功能函数,它只使用了其中一个组合类的各种方法和变量来实现功能,那么该考虑下下这个方法应该移到这个组合类中来实现
<3>在一个类里用其它类的属性做switch判断的话,就说明不太靠谱,如果真的需要应该在原来的类里去做这个判断
2:重构的目的在于让软件更容易让人理解和修改,但不影响软件或者程序对外的表现
3:改进设计的一个重要方向就是消除重复代码
重构和添加新功能进行分开进行,重构时专心重构,添加新功能时只增加新功能
何时重构:
1:添加功能时进行重构
2:修补错误时进行重构
3:Review代码时进行重构
性能优化,首先是有性能问题,通过数据找到性能消耗的点,不能只主观臆测
代码的坏味道
一些比较好的原则,把总是一起发生变化的东西放到一起
1:重复代码
<1>同一个类中有重复代码,提一个函数出来
<2>兄弟类中有重复代码,将代码置于父类
<3>毫不相干的两个类中有重复代码,搞一个单独类出来,然后进行引用,或者其它方式进行引用
2:过长函数
有一个简单判断条件,如果觉着需要写注释了,可以考虑搞一个新的函数出来,函数命名一定要能表现出功能来,即便是导致代码量更长了,但是这样看着会更加明确
3:过大的类
如果用同一个类干太多事,往往就会有一堆变量,可以将几个相关的变量提到同一个类中处理
太多代码的话,可以考虑先内部重构,把大函数中的重复代码做成小函数
4:参数太长
考虑传入参数用类来代替
5:发散式变化
如果一个类经常因为不同原因在不同方向上发生变化,例如修改数据库在这个类需要修改三个函数,新增一个工具需要在这个类修改四个函数,那么应该分成两个类比较合适,每个类真对一种修改
6:霰弹式修改
如果遇到一个变化会对多个类进行小的修改,可以考虑把这些个修改抽象到一个类中
7:依恋情结
如果实现一个功能,调用类另一个类的一堆函数,那应该考虑把这个功能放到另一个类中,如果这个功能比较复杂,用到了多个类的多个字断,判断哪个类拥有最多彼此函数使用的数据,将这部分数据和功能放到哪个类中
8:数据泥团
在很多地方看到相同的三四项数据,两个类中相同的字断,许多函数签名中相同的参数,可以将这些参数抽象到类中
9:switch
switch语句最大的问题是重复,常会发现同样的case语句到处存在,要修改就得到处改
当看到switch语句时候,考虑多态来实现
10:平行继承体系
当在一个类继承体系中,增加一个类时,往往需要在另一个继承体系中增加一个类
解决办法是让一个继承体系的类引用另一个继承体系的类
构筑测试体系
1:确保所有测试自动化完成,让他们检查自己的测试结果
2:考虑可能出错的边界,把主要测试放在这
3:每收到一个bug时,考虑加一个测试
4:在最担心出错的地方搞单元测试
测试应该是一种风险驱动的行为,测试的目的是希望找出现在或未来可能出现的错误
重新组织函数
1:提炼函数
有一段代码可以组织在一起并独立出来,将这段代码放进一个独立函数,并让函数名称解释该函数的用途
当看见一个长长的函数或者看到一段注释才能理解功能的函数时,将这段代码放进一个独立函数中,注意的是需要把这些函数命名的比较好。当函数细粒度越小,被服用的可能就会越大
函数的命名以做什么为命名,而不是怎样做
2:以函数对象取代函数
如果一个大型函数,内部有多个临时变量,而代码间的逻辑又各种引用这些个临时变量,直接运用提炼函数的话,应该会导致每个提炼函数都有一批参数传递,就不太适合直接提炼函数,这时候可以采用一个办法是新建一个类,这个类接受本身这个实例,以及这些个临时变量,在新类里就可以有final的全局参数,有个委托参数来实现原来大型函数的功能,而在新类里对于这函数可以来提炼函数了,这些个变量已经是全局变量了
对象之间搬移特性:
搬移函数
如果类中的一个函数与其他类打交道的比与自己的类打交道还多,可以考虑将这个函数搞到那个类中
搬移字段
根搬移函数差不多意思
提炼类
如果某个类干了两个类干的事,建立一个新类,将相关的字读和函数迁移过去
大家对于文章内容,有疑问或者希望有内容补充修改的可以在评论中提,笔者会秉承互联网产品哲学,小步快跑,快速迭代,不断修改和优化文章内容。