第一章已经看了好几遍,书里记录了一些临散的笔记,就是不知道从何落笔记录,就想着从第二章开始发了。书里的作者本人风格感觉是不太爱描述这种概念性的东西,我不太一样,如果连一些基本的东西都不去理解,或者说不清楚,怎么能理解透彻呢?
一、何谓重构
书中描述了两种定义,从名词到动词的形式。我大概默写一些,你们如果想深入的理解,还是看原书。
名词:
对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低修改的成本。(改命名、位置等)
动词:
使用一系列重构的手法,在不改变软件可观察行为的前提下,调整其结构。(改实现)
- 1.1 重构与性能 性能优化往往会使代码更难理解,重构是为了更好理解与修改,出发点不同。
- 1.2 使用重构时,会遇到两个问题,1、 重构。 2、 添加新技能
两种场景应该说是互不干扰的,但是在重构中,会经常替换,一会儿会添加新功能,一会会修改结构为了更好的添加。
目的
- 可以改进代码的设计: 1.消费重复代码。 2.易于理解 3.提高编码速度。4,更好定位bug并修复。
重构的时机
我个人觉得无论何时都是可以去慢慢钻研代码,然后进行重构的啦。
比较多的是作者的举例比如:
在添加功能时重构,当我们需要添加功能或者现有的设计无法帮助我们添加新功能更轻松时,就可以进行重构了。
修补错误时也可以进行重构,这时候主要是为了代码更容易理解吧。
复审代码时,一般这时候,是重构的最好时机
间接层
书中引入了一个间接层的专业词,我觉得暂时就叫这个名字吧。
大多数重构都会为程序引入很多的间接层,会把大型对象,处理类拆成很多的小型对象,大型函数拆成很多个小函数。
但是这是一把双刃剑,一个东西拆成多份就要多维护一份,不好管理。一个对象如果委托另一个对象处理,委托多了,程序也变得很难阅读跟理解。
书中也总结了一些间接层的价值:
1.允许逻辑共享,这句话其实是指可以抽象实现后,子类共用。
- 分开解释和实现,我觉得理解为多态吧。
另外两种说法,我觉得都差不多,就不列举了。
重构基本会引入更多的间接层,但是反过来想,也可以在重构时,把不必要的间接层删除掉。
重构时会遇到的难题
数据库
绝大多数商用程序都与背后的数据库结构紧密耦合在一起,这也是数据库结构如此难以修改的原因之一。另一个原因是数据迁移,就算很小心的进行系统分层,将数据库与对象模型的依赖降至最低,但数据库结构的改变(例如数据拆分业务拆分)还是让你不得不迁移所有的数据。
对于非对象数据库,解决迁移所有数据的方法就是:在对象模型和数据库模型之间插入一个分隔层,这就可以隔离两个模型各自的变化,升级某一模型不用升级另一个模型,只要升级分隔层就行,这样的分隔层会增加系统复杂度,但是可以带来很大的灵活度。最好在发现对象不稳定时在去设计生产他。
关于数据库与对象模型之间的中间层,我们在开发中可能遇到的会比较少,我文章开头说了,今天主要是记录一些概念性的东西,大家多理解理解,如果遇到我会分享一些实现的。
修改接口
这里说的修改接口的情况,就是,当你的接口是已经发布或者对外提供的,或者说你的修改又不能保证能覆盖到所有的调用者,这时候,任何修改都可能会影响使用。
这个时候,你要怎么办呢? 一般来说,都尽量推荐,使用旧接口调用新接口的方式。当你需要修改某个函数名称时,请留下旧函数,让她调用新函数。千万不要复制函数的实现,不然你会陷入重复代码,很难自拔的。
保留旧接口的方式也是可行的,但是会构造并微信一些额外的函数。也可以选择另一种处理,不要发布接口。
在书中,对于java还推荐了一种特殊的接口处理方式。在throw子句中增加一个异常。你可以为这个函数改一个新名字,让旧函数调用他,并将这个新增的受控异常转换成一个非受控异常,也可以抛出一个非受控异常,不过这样你机会失去检验能力。
处于这个原因,很多开发者都会设置一个异常抽象父类,让所有1自定义异常都继承他,对调用者来说,就都不受影响。因为他们只需要认识一个基类。
难以通过重构手法完成的设计改动
书中举了一个例子,比如很难将原本就不考虑安全性需求时构造起来的系统,重构成具备良好安全性系统。
针对这种场景,作者分享了自己的一些小经验:先想象重构的情况,考虑候选设计方案时,想想将某个设计重构为另一个设计的难度有多大?如果看上去看简单,就直接选最简单的,如果预先都看不到,那就多在设计上投入精力。
不该重构的情况???
前面作者讲了很多重构的知识,当然也会有不该重构的时候。
比如需要重新编写所有的代码逻辑的时候,这时候还不如直接重新写一个简单。
重构与设计
重构肩负一项特殊使命,跟设计互补。在编程具备一定经验的时候,会发现,事先做好设计可以节省返工的高昂成本,许多人把设计看成软件开发的关键环节。
书中举例了一种观点:重构可以取代预先设计,就是不需要做设计,然后按照最初的想法编码,让代码有效运作,再重构成型。这种方式是真的可行的。
如果你选择这种方式,问题的重点就变了,你任然做预先设计,但是不一定要找出最正确的解决方案,此时只需要得到一个足够合理的方案就行了。如果是软件设计为主,则你可能在软件设计的时候,会力求设计最灵活的解决方案,要建造一个灵活的解决方案,成本难以计算,最终得到的也可能更难以维护,可能只修改了一个地方的设计但是因为设计的非常灵活,导致维护非常麻烦,同时系统复杂度也会大大增加。
当然如果最后发现设计的这些都没必要,就会造成最大的失败。
总结:重构可以带来更简单的设计,同时不失灵活性,这也降低了设计过程的难度。