重构原则

何谓重构

第一个定义是名词形式:

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

常用的重构有: Extract Method(110)、 Pull Up Field(320) 等。
重构之中可以包含另一个重构,例如 Extract Class(149) 通常包含 Move Method 和 Move Fields(146).

重构的另一个用法是动词形式

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

第一点,重构的目的是使软件更容易被理解和修改。 第二点是,重构不会改变软件的可观察行为。任何用户,不论是最终用户 或 其他程序员,都不知道已经有东西发生了变化。

为何重构

  • 重构改进软件设计

  • 重构使软件更容易理解
    一开始我所做的重构都像是停留在细枝末节上。随着代码越来越简洁,我发现自己可以看到一些以前看不到的设计层面的东西。如果不对代码做这些修改,也许我永远看不见它们,因为我的聪明才智不足以在脑子里把这一切都想象出来。Ralph Johnson 把这种 “早期重构” 描述为 “ 擦掉窗户上的污垢, 使你看的更远”。

  • 重构帮助找到bug
    对代码进行重构,可以深入理解代码的行为。

  • 重构提高编程速度
    良好的设计是开发的根本,事实上,拥有良好的设计才可能做到快速开发。如果没有良好的设计,或许某一段时间内你的进展迅速,但恶劣的设计很快就让你的速度慢下来。你会把时间花在调试上面,无法添加新功能。修改时间愈来愈长,因为你必须花愈来愈多的时间去理解系统,寻找重复代码。随着你给最初的程序打上一个又一个的补丁,新特性需要更多的代码才能实现,真是恶性循环。

    重构可以帮助你更快速地开发软件,因为它阻止系统腐败变质,它甚至还可以提高设计质量

何时重构

几乎任何情况下我都反对专门挑出时间进行重构。在我们看来,重构本身就不是一件特别拨出时间做的事情,重构应该随时随地进行。你不应该为重构而重构,你之所以重构,是因为你想做别的事情,而重构可以帮你把那些事做好。

三次法则

Don Roberts 给了我一条准则:第一次做某件事时只管去做;第二次做类似的事会产生反感,但无论如何还是可以去做;第三次再做类似的事,你就应该重构了。

事不过三,三则重构

添加功能时重构

最常见的重构时机就是我想给软件添加新特性的时候,此时,重构的直接原因往往是为了帮助我们理解需要修改的代码 —— 这些代码可能是别人写的,也可能是我们自己写的。无论何时,只要我想理解代码所做的事,我就会问自己;是否能对这段代码进行重构,使我们能更快的理解它。之所以这么做是为了下次再看到这段代码的时候,我们能更好的理解它。

另外的一个原动力是,代码的设计无法帮助我轻松添加我们所需要的特性。我看着设计,然后对自己说: “如果用某种方式来设计,添加特性会简单的多。” 这种情况下 我不会因为自己过去的错误而懊恼— 我会用重构来弥补它。之所以这么做,部分原因是为了让未来添加新特性时能够更轻松一些。

修补错误时重构

调试过程中运用重构,多半是为了让代码更具可读性。当我看着代码并努力理解它的时候,我会运用重构帮助加深自己的理解。我发现以这种程序来处理代码,常常能够帮助我找出bug。你可以这么想:如果收到一份错误报告,这就是需要重构的信号,因为显然代码还不够清晰 —— 没有让你能一眼看出bug。

复审代码时重构

公司开代码复审的时候,大家可以提出自己的意见。

重构是一条摆脱困境的道路。如果你发现昨天的决定已经不适合今天的情况,放心改变这个决定就是,然后你就可以完成今天的工作了,明天,喔,明天回头看今天的理解也许觉得很幼稚,那时你还可以改变你的理解。

是什么让程序如此难以相与?眼下我能想起下述四个原因,它们是:
- 难以阅读的程序,难以修改;
- 逻辑重复的程序,难以修改;
- 添加新行为时需要修改已有代码的程序,难以修改;
- 带着复杂条件逻辑的程序,难以修改。

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

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

间接层和重构

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

由于软件工程师对间接层如此醉心,你应该不会惊讶大多数重构为程序引入了更多间接层。重构往往把大型对象拆成多个小型对象,把大型函数拆成多个小型函数。

间接层的某些价值:
- 允许逻辑共享,比如说一个子函数在两个不同的地点被调用,或超类中的某个函数被所有子类共享。
- 分开解释意图和实现 你可以选择每个类和函数的名字,这给了你一个解释自己意图的机会,类或函数内部则解释实现这种意图的做法。如果类和函数内部又以更小单元的意图来编写,你所写的代码就可以描述其结构中的大部分重要信息。

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

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

重构与性能

并不赞成为了提高设计的纯洁性而忽视性能,把希望寄托于更快的硬件身上也绝非王道。已经有很多软件因为速度太慢而被用户拒绝,日益增高的机器速度也只不过略微放宽了速度方面的限制。但是换个角度说,虽然重构可能使软件运行更慢,但它也使软件的性能优化更容易。除了对性能有严格要求的实时系统,其他情况下“编写快速软件”的秘密就是: 首先写出可调的软件,然后调整它以求获得足够速度。
我看过三种快速编写软件的方法:
- 最严格的是时间预算法,这通常只用于性能要求极高的实时系统。
- 持续关注法
- 第三种性能提升法就是利用上述的90%的统计数据。采用这种方法时,你编写构造良好的程序,不对性能投以特别的关注,直至进入性能优化阶段——那通常是在开发后期。一旦进入这个阶段,你再按某个特定程序来调整程序性能。
在性能优化阶段,你首先应该用一个度量工具来监控程序的运行,让它告诉你程序在哪些地方大量消耗时间和空间。这样你就可以找出性能热点所在的一小段代码。然后你应该集中关注这些性能热点,并使用持续关注法中的优化手段来优化它们。

一个构造良好的程序可从两方面帮助这一优化形式。首先,它让你有比较充裕的时间进行性能调整,因为有构造良好的代码在手,你就能够更快速的添加功能。也就有更多时间用在性能问题上。其次,面对构造良好的程序,你在进行性能分析时便有了较细的粒度,于是度量工具把你带入范围较小的程序段落中,而性能的调整也比较容易些。由于代码更加清晰,因此你能够更好地理解自己的选择,更清楚哪种调整起关键作用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值