代码的改善与重构之道
-
关于重构
* 对软件内部结构的一种调整,目的是再不改变软件可观察行为的前提下,提高其可理解性,降低修改、维护的成本。
-
重构本质
* 整理代码
* 重构是一种高效,且可控的代码整理技术,使我们能够保持高效开发,从而增强程序的价值。
* 一种可以学习的技术
* 发现代码中的问题,朝着解决问题的目标前进的道路,是学习成长的历程。
-
重构目的
* 代码易理解(表现自己的目的)、易维护(两个Easy,即easy to read, easy to maintain)
-
重构原则
* 新功能 - 不应该修改既有代码,只管添加新功能
* 重构 - 不能添加/修改新功能、测试用例,只管程序结构的重构
* 以微小的步伐修改程序 - 如果你犯下错误,很容易就可以发现并做及时的修改
* 测试 - 测试,小修改,测试
-
腐化问题
* 在尚未理解整体设计之前,贸然开始修改代码、增加新功能
* 未经设计或者设计不好的程序需要更多的代码,重复性的代码随之增多
-
重构收益
* 发现潜藏的Bug - 重构的过程可以更好的理解实现和业务
* 提高编程的速度 - 良好的设计是提高开发效率的根本
* 提高质量、改善设计、提升可读性、减少错误
-
重构时机
* 指导原则
* 事不过三,三则重构 - 第一次做某件事情的时候只管去做,第二次做类似事情的时候会产生方案,但是无论如何还可以去做,第三次再去做类似的事情,就应该重构了
* 典型时机
* 添加新功能时 - 已有代码的设计无法轻松的添加新特性,而使用某种方式来设计可以更简单的添加新特性
* 修复Bug时 - 代码不够清晰,无法快速定位问题
* 代码Review时 - 根据Review的建议进行“结对编程”
-
前提条件
* 完善的测试体系
* 确保所有的测试都完全自动化,并让它们检查自己的测试结果
* 一套测试就是一个强大的bug侦测器,能够大大缩减查找bug的时间
* 频繁的运行测试,每次编译都需要测试保障
* 收到一个bug报告,至少需要一个测试用例覆盖这个问题
* 编写未臻完善的测试用例,并运行他们,好过对完美测试的无尽等待 - 从最担心的的部分开始编写测试用例
* 考虑可能出错的边界条件,把测试火力集中在那儿
* 当事情被认定应该出错时,别忘了检查是否抛出了预期的异常
* 不要因为测试无法不抓所有的bug就不写测试,测试的确可以不抓到大多数的bug
* 代码Review机制
* 重构工具机制(Bad Smell)
-
开始重构
* 设定目标
* 选定一个重构的目标,比如,“去掉不必要的子类”
* 重构列表
* 概要 - 解决的问题、应该做的事
* 动机 - 为什么重构
* 做法 - 重构的方案
* 从哪里开始入手
* 自动化工具识别到的程序中的缺陷(Bad Smell)
* 重复代码
* 函数参数过多
* 函数过长
* 过大的类
* 霰弹式修改
* 冗余类
* 令人迷惑的字段
* 过度耦合的消息链
* Bug单频繁(>=3)出现的问题根源所在
-
重构内容
* 重新组织函数
* 在对象间搬移属性
* 重新组织数据
* 简化条件表达式
* 简化函数调用
* 处理概括关系
-
何时停止
* 完成了设定的目标
* 代码比之前的好,是“好的代码”
* 代码逻辑直截了当,叫缺陷难以隐藏
* 尽量减少依赖关系,使之便于维护
* 依据某种分层战略完善错误处理
* 性能调至最优,省得引诱别人做没规矩的优化,搞出一堆乱
* 整洁的代码只做一件事
* 通过了代码Review