重构-改善既有代码设计-重构原则(1)

版权声明:不自见故明;不自是故彰;不自伐故有功;不自矜故长; https://blog.csdn.net/LightUpHeaven/article/details/84259664

神马是重构?从两方面来说:

一个是名词:对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。

一个是动词:使用一系列重构手法,在不改变软件可观察行为的前提下,调整其结构。

对重构的扩展

1.重构的目的是使软件更容易被理解和修改。(注意和性能优化的区别,会使代码难以理解)

2.重构不会改变软件可观察行为--重构之后软件功能一如既往。

两顶帽子:

1.添加新功能。添加新功能时,不应该修改现有代码,只管添加新功能。通过测试可衡量自己的工作进度。

2.重构。重构时不要添加新功能,只管改进程序结构。此时不应添加任何新的测试,只在绝对有必要时(接口变化)才修改测试。

软件开发过程中会经常变换帽子,但无论何时,都要清楚自己戴的是哪顶帽子

为何重构:

1.重构改进软件设计。经常性的重构可以帮助代码维持自己该有的形态。

2.重构使软件更容易理解。及时填补“想要计算机做什么”和“告诉计算机做什么”之间的缝隙。编程模式的核心即“准确说出我想要的”。除了计算机,还有其他程序猿要读你写的源码。这位第二位读者才是最重要的。利用重构协助理解不熟悉的代码。不满足于看代码,真正动手修改代码,让它更好的反应出你的理解。然后重新执行,通过是否仍然运行正常,来验证自己的理解是否正确。

一开始的重构都局限于细枝末节,随着代码的简洁,可以发现一些以前看不到的设计层面的东西。如果不对这些代码做修改,永远看不到它们。这种“早期重构”被称为“擦掉窗子上的污垢,使你看的更远。”重构把你带到更高的理解层次上。

3.重构帮助找到Bug。不擅长调试的人,盯着一大段代码看不到里面的Bug,但如果对这些代码进行重构,就可以深入理解代码的作为,并恰到好处的的把新的理解反馈回去。搞清楚长须结构的同时,也清楚了自己所做的一些假设,于是想不把Bug找出来都难。Ken Beck“我不是一个伟大的程序猿,我只是一个有着一些优秀习惯的好程序猿。”重构能帮助人写出更健壮的代码。

4.重构提高编程速度。良好的设计是快速开发的根本。拥有良好设计才可能做到快速开发。重构可以帮助你更快速的开发软件,因为它阻止系统腐败变质,甚至还可以提高设计质量。

何时重构:

无须专门拨出时间重构,重构本来就不是一件应该特别拨出时间做的事情,重构应该随时随地进行。不应该为了重构而重构,之所以要重构,是因为想做别的什么事,而重构可以帮你把哪些事做好。

三次法则:第一次做某件事时只管去做,第二次做类似的事会发生反感,但无论如何还是可以去做。第三次做类似的事,你就应该重构。

添加功能时重构:帮助自己理解需要修改的代码,为了下次再看这段代码时容易理解。最主要的原因是:如果在前进的过程中把代码结构理清,可以从中理解更多东西。

另一个原动力是:代码的设计无法帮助自己轻松添加自己所需要的特性。不用为过去的错误而懊恼,用重构来弥补它。一来可以让未来添加新特性时更轻松一些,最主要的原因还是这是最快捷的途径。重构是一份的快速流畅的过程,一旦完成重构,新特性的添加就会更流畅,更快速。

修补错误时重构:调试过程中重构,多半是为了让代码更具可读性。

复审代码时重构:复审代码时考虑是否可以通过重构立即轻松实现它们。如果可以,可以立即动手。这样做了几次之后,可以把代码看的更清楚。为了让过程正常运转,复审团队必须精炼。最好是一个复审者搭配一个原作者,共同处理这些代码。复审者提出修改建议,然后两人一起判断这些修改是否能够通过重构轻松实现。果真如此,就一起着手修改。

比较大的设计复审工作,在一个较大的团队内保留多种观点通常会更好一些,此时直接展示代码往往不是最好的办法。用UML展现设计,并以CRC卡展示软件情节。换句话说,和某个团队进行设计复审,二和单个复审者进行代码复审。

极限编程中的“结对编程”把代码复审的积极性发挥到了极致。一旦采用这种形式,所有正式开发任务都由两名开发者在同一台机器上进行,这样便在开发过程中随时进行代码的复审工作,而重构也就包含在代码的开发过程中了。

第一步,要先搭建可自我检验的测试系统,保证修改前后代码的处理结果相同。

程序的两面价值

“今天可以为你做什么”和“明天可以为你做什么”。大多数时候我们只关注自己今天想要程序做什么,让它在今天更有价值,但是系统当下的行为,只是整个故事的一部分。如果为了完成今天的任务不择手段,导致不可能完成明天的任务,那么最终还是会失败。重构时一条拜摆脱困境的路,如果发现昨天的决定已经不符合今天的情况,放心改变这个决定就是,然后就可以完成今天的工作了。明天如果回头看今天的理解也觉得幼稚,那是你还可以改变你的理解。

是什么让程序如此难以相与

1.难以阅读的程序,难以修改。

2.逻辑重复的程序,难以修改。

3.添加新行为时需要修改已有代码的程序,难以修改。

4.带复杂条件逻辑的程序,难以修改。

因此我们希望程序(1)易于阅读;(2)所有逻辑都只在唯一地点执行;(3)新的改动不会危及现有行为;(4)尽可能简单表达条件逻辑;

重构是这样一个过程:它在一个目前可以运行的程序上运行,在不改变程序行为的前提下使其具备上述美好性质,使我们能够继续保持告诉开发,从而增加程序价值。

间接层和重构

计算机科学是这样一门科学:它相信所有问题都可以通过增加一个中间层来解决。

间接层的价值

1.允许逻辑共享。如一个子函数在两个不同的地点被调用,或超类中的某个函数被所有子类共享。

2.分开解释意图和实现。选择每个类和函数的名字,给了一个解释自己意图的机会。类或函数内部则解释实现这个意图的做法。如果类和函数内部又以更小单元的意图来编写,你所写的代码就可以描述其结构中的大部分重要信息。

3.隔离变化。在两个不同地点使用同一对象,其中一个地点想改变对象行为,但如果改动了它,就要冒同时影响两处的风险。为此做出一个子类,并在需要修改处引用这个子类。现在可以修改子类而不必承担无意中影响另一处的风险。

4.封装条件逻辑。对象有一种奇妙的机制:多态消息,可以灵活而清晰的表达条件逻辑。将条件逻辑转化为消息形式,往往能降低代码的重复,增加清晰度并提高弹性。

这就是重构游戏:在保持系统现有行为的前提下,如何才能提高系统的质量或降低其成本,从而使它更有价值?

这个游戏中最常见的变量就是:你如何看待自己的程序。找出一个缺乏“间接层利益”之处,在不修改现有行为的前提下,为它加入一个间接层。现在你获得一个更有价值程序,因为它有较高的质量,让我们在明天(未来)受益。

这种与推测性的区别是,推测性设计试图在任何一行代码诞生之前就先让系统拥有所有优秀质量,然后程序猿将代码塞进这个强健的骨架中就行了。这个工程的问题在于:太容易猜错。如果运用重构,你就永远不会面临全盘错误的危险。程序自始至终都能保持一致的行为,而你又有机会我程序添加更多价值不菲的质量。

数据库:在非对象数据库中,解决这个问题的办法之一是,在对象模型和数据库模型之间插入一个分割层,可以隔离两个模型各自的变化。升级某一模型时,无须同时升级另一个模型。无需一开始就插入分割层,可以在发现对象模型变得不稳定时再产生它。这样你就可以为你的改变找到最好的平衡点。

修改接口:允许修改软件模块的实现和接口。可以安全的修改对象内部实现而不影响他人,但对于接口则需特别谨慎。如果接口被修改了,任何事情都有可能发生。

如何修改已发布接口。当要修改某个函数名称时,请留下旧函数,让它调用新函数。千万不要复制函数实现。保留旧接口,通常可行,但很烦人。在一段时间内必须构造并维护一些额外函数。

另外一个选择,不发布接口。不是说完全禁止,除非真的有必要,不要发布接口。 

难以通过重构手法完成的设计改动:是否存在某些核心设计决策,无法以重构修改。比如在一个项目中,我们很难(但还是有可能)将不考虑安全性需求时构造起来的系统重构为具备良好安全性系统。

此时的方法是:先想象重构的情况。考虑候选设计方案时,我会问自己:将某个设计重构为另一个设计的难度有多大?如果看上去简单,则无需太担心选择是否得当。测试就会选最简单的设计,哪怕不能覆盖所有潜在的需求。如果预先看不到简单的重构方法,就会在设计上投入更多力气,不过我发现,后一种情况很少出现。

何时不该重构:有时候根本不应该重构,例如你应该重新编写所有代码的时候。有时候既有代码实在太混乱,重构它还不如重新写一个来的简单。做这种决定很困难,我承认我也没有什么好准则可以判断何时应该放弃重构。

重写的一个清晰信号就是:现有代码根本无法正常工作。记住,重构之前,代码必须起码在大部分情况下正常工作。

一个折中的办法就是:将“大块头软件”重构为封装良好的小型组件。然后你就可以注意对组件做出“重构或重建”的决定。这是一个颇有希望的办法。但我还没有足够数据,所以无法写出好的指导原则。对于一个重要的遗留系统,这肯定会使一个很好的方向。

另外,如果项目已近最后期限,也应该避免重构。在此时机,从重构过程中赢得的生产力只有在最后期限过后才能体现出来,而那个时候已经为时晚矣。

未完成的重构工作形容为“债务”,很多公司都需要借债l来使自己更有效的运转。但是借债就需要得付利息,过于复杂的代码所造成的维护和扩招的额外成本就是利息。你可以承受一定程度的利息,但如果利息太高你就会被压垮。把债务管理好是很重要的,应该随时通过重构来偿还一部分债务。

如果项目已经非常接近最后期限,你不应该再分心于重构,因为已经没有时间了。不过多个项目经验显示:重构的确能提高生产力。如果最后产没有足够时间,通常就表示你其实早该进行重构。

重构的起源:与技术无关,暂不表述。

猜你喜欢

转载自blog.csdn.net/LightUpHeaven/article/details/84259664