重读《重构》,呼唤匠艺
2019-05-24熊节
熊节
2009年,在为《重构》第1版的中译本再版整理译稿时,我已经隐约察觉行业中对“重构”这个概念的矛盾张力。一方面,在这个“VUCA”(易变、不确定、复杂、模糊)横行的年代,有能力调整系统的内部结构,使其更具长期生命力,这是一个令人神往的期许。另一方面,重构的扎实功夫要学起来、做起来,颇不是件轻松的事,且不说详尽到近乎琐碎的重构手法,光是单元测试一事,怕是已有九成同行无法企及。结果,“重构”渐渐成了一块漂亮的招牌,大家都愿意挂上这个名号,可实际上干的却多是“刀劈斧砍”的勾当。
如今又是十年过去,只从国内的情况而论,“重构”概念的表里分离,大有愈演愈烈之势。随着当年的一线技术人员纷纷走上领导岗位,他们乐于将“重构”这块漂亮招牌用在更宽泛的环境下,然而基本功的欠缺,却也一路如影随形。
此时转头看Martin Fowler時隔将近廿载后终于付梓的《重构》第2版,我不禁感叹于他对“微末功夫”的执着。在此书尚未成型之前,我和当时ThoughtWorks的同事曾有很多猜测,猜Fowler先生是否会在第2版中拔高层次,多谈谈设计乃至架构级别的重构手法,甚或跟随“敏捷组织”“精益企业”的风潮谈谈组织重构,也未为不可。孰料成书令我们跌破眼镜,Fowler先生不仅没有拔高,反而把工夫做得更扎实了。
对比前后两版的重构列表,可以发现:第2版收录的重构手法在用途上更加内聚,在操作上更加连贯,更重视重构手法之间的组合运用。第1版中占了整章篇幅的“大型重构”,在第2版中全数删去。一些较为复杂的重构手法,例如复制“被监视数据”、塑造模板函数等,第2版也不再收录。而第2版中新增的重构手法,则多是提炼变量、移动语句、拆分循环、拆分变量这样更加细致而微的操作。这些新增的手法看似简单,但直指大规模遗留代码中最常见的重构难点,正好补上了第1版中阙漏的细节。这一变化,正反映出Fowler先生对于重构一事一贯的态度:千里之行积于跬步,越是面对复杂多变的外部环境,越是要做好基本功、迈出扎实步。
在《重构》第2版里,重构手法的细节被再度打磨,重构过程比之第1版愈发流畅。细细品味重构手法中的前后步骤,琢磨作者是如何做到行为保持的,这是能启发读者举一反三的读书法。以保持对象完整重构手法为例,第1版中的做法是在原本函数上新添参数,而第2版的做法则是先新建一个空函数,在其中做完想要的调整之后,再整体替换原本函数。两相对比,无疑是新的做法更加可控,出错时测试失败的范围更小。
从这个视角品味一个个重构巨细靡遗的做法,读者大概能感受到重构与“刀劈斧砍”之间最根本的分歧。在很多重构(例如最常用的改变函数声明)的做法中,Fowler先生会引入“很快就会再次修改甚至删除”的临时元素。假如只看起止状态,这些变更过程中的临时元素似乎是浪费:为何不直接一步到位改变到完善的结果状态呢?然而这些临时元素所代表的,是对变更过程(而非只是结果)的设计。缺乏对过程的精心设计与必要投入,只抱着对结果的美好憧憬提刀上阵,遇到困难就靠“奋斗精神”和加班解决,这种“刀劈斧砍”不止发生在缺乏审慎的“重构”现场,又何尝不是我们这个行业的缩影?
是以,重构这门技艺,以及Fowler先生撰写《重构》的态度,代表的是软件开发的匠艺——对“正确的做事方式”的重视。在一个浮躁之风日盛的行业中,很多人会强调“只看结果”,轻视做事的过程与方式。然而对于软件开发的专业人士而言,如果忽视了过程与方式,也就等于放弃了我们自己的立身之本。Fowler先生近廿载对这本书、对重构手法的精心打磨,给了我们一个榜样:一个对匠艺上心的专业人士,日积月累对过程与方式的重视,是能有所成就的。