重构的威力
软件的复杂性来自于大量的不确定性,而这个不确定事实上是无法避免的。
需求在变,语言在变,软件的复杂性来自于大量的不确定性,而这个不确定事实上是无法避免的。
我们的软件也会像一个生命体,经历从新生到衰老腐化的过程。而重构就像是一次手术,通过优化内部结构,减慢腐化衰老,让软件“青春永驻”,可见重构的威力。
重构教会了我如何通过高效安全地改善内部设计以使之适应外部的不确定性和频繁变化。
重构威力无边,就像是武侠小说中的一件插在石头上的上古神器,但同样也不是一般人可以轻松驾驭的。如果运用不当,造成的损害也会同样巨大。
如何将重构这件神器运用自如,发挥其最大的威力,也是我一直在探寻的,即重构的手法和心法。
合格的重构
在谈手法和心法之前,可能很多人会有疑惑,觉得重构并不像你说的那么难啊,我们每天都在做,就是改改代码改改设计,哪有你说的那么邪乎。那我就先来讲讲我认为怎么样才算是一次合格的重构。
对于什么是重构,《重构》书中已经有明确的定义,分名词和动词两种形式。
重构(名词):对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。
重构(动词):使用一系列重构手法,在不改变软件可观察行为的前提下,调整其结构。
就像“看板”不是“我们看到的那个白板”一样,“重构”也不是“重新修改代码”那么简单。
我就看到过太多打着重构的幌子,把系统改的面目全非,最后出了问题直接甩锅到重构身上的场景了。那怎样才算是一次合格的重构呢?我觉得至少需要做到以下几点:
消除味道:一个重构应该是从识别一个坏味道(Bad Smell)开始,以消除一个坏味道结束,任何不以消除坏味道为目标的重构都是耍流氓。
始终工作:即重构定义中的“在不改变软件可观察行为的前提下”,说白了就是重构过程不能破坏甚至改变软件外在功能。
持续集成:不需要为重构单建分支,重构过程可以做到Feature开发在同一分支上持续集成持续交付。
随时中止:例如一个方法重命名,需要修改100个调用点,当改到50个的时候有个紧急的Feature,我可以随时暂停重构,立即切换到Feature开发上,且不需要回滚已做的重构。
断点续传:还是上边的例子,假如我已经完成了紧急Feature的开发,可以随时继续之前的重构,完成剩下50个调用点的重命名。
过程可逆:对于重构,经常有人会问:你怎么保证重构就会更好而不是更坏呢?重构的伟大就在于他跳出了对错之争,将关注点放到如何快速平滑安全的变化上,当然也包括反向重构。所以我的回答是:无法保证,但是我可以一分钟就重构回来。如果仔细看,《重构》书里的所有重构手法都是双向的,比如“Extract Method”和“Inline Method”。
可以反思一下,我们平时自认为的那些重构,是否都符合了以上的这些要求?
多少次我们打着重构的旗号,七零八碎,无法复原。
多少次我们打着重构的旗号,分支开发,集成困难。
多少次我们打着重构的旗号,半途而废,迷途难返
多少次我们打着重构的旗号,孤注一掷,进退两难。
在我的眼里,这些都不是合格的重构,甚至都不能称之为重构,好的重构应该像一边开车一边换轮胎一样,保证系统随时可工作的前提下,还可以对其结构做出安全高效的调整。
可见重构并不简单,那要怎样才能达到上述的那些要求呢?
重构的心法
有个柔弱书生,无意中掉到了一个悬崖下,找到了一本武林秘籍,照着上边的招式练了练就自以为已绝学在身,结果出去虽然能招架一时,但禁不住更大的挑战。被打的体无完肤后,重新掏出那本秘籍,收起浮躁,怀着诚敬之心努力去参悟那些招式背后更深的哲理,也就是所谓的心法。此时对于我来说,而那本武林秘籍就叫做《重构》。
代码重构、架构重构、服务重构甚至是组织重构,都可以做到上面提到的一个合格重构的基本要求,即平滑安全可停可续。
把其中的原则思路抽取出十六个字,即所谓的:重构十六字心法。
解释起来也很简单,往往我们做”重构“的时候就是在旧的结构(这里的结构可以是一个方法、一个对象、一个服务、一个数据库、一个服务甚至是一个组织结构)上直接修改,导致系统长时间处于一个中间不可用状态,这个状态持续的时间越长,”重构“失败的可能性和负面影响就会越大。
总结
重构可以使软件更容易地被修改和被理解。通过不断地改进软件设计以达到简单设计的目标,减少由于设计与业务的不匹配带来的架构与设计腐化。
掌握了重构的手法和心法,会让重构变得更加简单安全高效可控,从而真正的发挥出其巨大的威力,让我们的软件永葆青春。
网友评论