2.1 何谓重构
1,定义
- 名词形式:对软件内部结构的一种调整,目的是在不改变软件可观察的行为前提下,提高其可理解性,降低其修改的成本
- 动词形式:使用一系列重构的手法,在不改变软件可观察行为的前提下,调整其结构
2,目的
使软件更容易被理解和修改。你可以在软件内部做很多修改,但必须对软件的可观察的外部行为只造成很小的变化,或者没有变化,与之相对比的是性能优化,性能优化通常不会改变组件的行为(除了执行速度)只会改变内部结构,性能优化往往使代码较难理解
3,Kent Beck的两个帽子的比喻
时间分配的两种行为: 添加新功能,以及重构
2.2为何重构
1,重构改进软件设计
改进一个重要的方向就是消除重复代码
2,重构使软件更容易理解
可理解性的一方面尽量把该记住的东西写到程序里,另一方面 理解不熟悉的代码,最重要的是重构可以把自己带到更高的理解层次
3,重构帮助找到bug
4,重构提高编程速度
良好的设计是维持软件开发速度的根本
2.3何时重构
三次法则
1,添加功能时重构
2,修补错误时重构
3,复审代码时重构
代码复审对于编写清晰代码很重要,开始重构钱可以先阅读代码,得到一定程度的理解,并提出一些建议,一旦想到一些点子,就可以考虑是否可以通过重构立即轻松的实现他们,重构让自己不必想象代码应该是什么样,可以自己看见它是什么样。
极限编程中结对编程形式,把代码复审的积极性发挥到极致,一旦采用这种方式,所有正式开发任务都是由两名开发者在同一台机器上进行,这样便在开发过程中形成随时进行代码复审的工作,而重构也就包含在开发过程中了
程序有两面价值“今天可以为你做什么”和“明天可以为你做什么”
程序难以相与原因:
- 难以阅读的程序,难以修改
- 逻辑重复的程序,难以修改
- 添加新行为需要修改已有代码的程序,难以修改
- 带复杂条件逻辑的程序,难以修改
因此我们希望程序(1)容易阅读(2)所有的逻辑都只在唯一地点指定(3)新的改动不会危及现有行为(4)尽可能简单表达条件逻辑
重构是这样一个过程:他在一个目前可运行的程序进行,在不改变程序行为前提下使其具备上述美好性质,使我们能够保持高速开发,从而增加程序的价值
2.4怎么对经理说
1,技术复审是减少错误,提高开发速度的一条重要途径
经理 质量驱动 VS 进度驱动,
2,间接层与重构
间接层:重构会把大型对象分为多个小型对象,把大型函数分为多个小型函数
缺点:程序难以阅读,因为程序中会把某个对象委托另一个对象,后来又委托另一个对象
价值:
1),允许逻辑分享
比如一个子函数在两个不同的地点被调用,或者超类中某个函数被所有字类共享
2),分开解释意图和实现
类和函数的名字,给一个解释自己意图的机会
3),隔离变化
4),封装条件逻辑
对象有一个奇妙的机制,多态消息,可以灵活而清晰表达条件逻辑,将条件逻辑转化为消息形式,往往能降低代码重复,增加清晰度并提高弹性
2.5重构难题
1,数据库
绝多大数商用程序都与它们背后的数据结构紧密耦合一起,这也是数据结构如此难以修改的原因之一。另一个原因是数据迁移,就算你非常小心的将系统分层,将数据结构和对象模型间的依赖将至最低,但是数据库结构的改变还是让你不得不迁移所有的数据。
在非对象数据库中,解决这个问题的方法之一是:在对象模型和数据库模型插入一个分割层,这就可以隔离两个模型的变化,升级某一模型的时候无需升级另一模型,只需升级上述分隔层即可。这样分隔层会增加系统的复杂度,但是可以给你带来很大的灵活性
2,修改接口
关于对象,允许你分开修改软件模块的实现和接口,你可以安全修改对象的内部而不影响他人。但是对于接口要特别谨慎
1),让旧接口调用新接口, 使用java提供的deprecation(不建议使用)设置
2),不要过早的发布接口,请修改你的代码所有权政策,使重构更流畅
3),在throw子句中增加一个异常
3,难以通过重构手法完成设计改动
将某个设计重构为另一个设计的难度有多大?
4,何时不该重构
2.6重构与设计
1,事先做好设计可以节省返工的高额成本
2,实际度量程序性能,不要臆测
2.7重构与性能
首先写出可调的软件,然后调整它以求获得足够的速度
编写快速软件方法
1,时间预算法:通常用于性能要求极高的实时系统,如果使用这种算法,分解你的设计时就要做好预算,给每一个组件预先分配一定的资源----包括时间和执行轨迹,每个组件绝对不能超过自己的预算,计算拥有组件之间调配预配时间机制也不行,这种方法高度重视性能,对于心率调节器一类的系统是必须的,
2,持续关注法
关于性能。大多数程序中大半的时间都会浪费在一小半的代码中
3,性能提升法,利用上述90%统计数据,在性能优化阶段,使用一个度量工具监控程序的运行,告诉程序那些地方消耗大量空间和时间
巨大字符串问题?
创建量最大的对象是字符串
缓存—》直接写入文件流—》程序放在多处理器的计算机上,以多线程的方式运行