如何对一个项目进行重构?

一、重构 Or 重写

重构是对现有项目的代码进行整理和优化,偿还技术债务,消除代码的坏味道。
重写是重构带来的成本已经超过了重新写一个新项目的成本。这个新项目需要实现原有项目所有的功能。
如何判断一个系统是否需要重构?

  1. 拥有沉重的技术债务
    技术债务包括但不限于大量复制粘贴的代码、文件代码行数过多、UI不统一、代码不规范,没有组件化,过度优化。
    在部门制定的标准中,一个标准Vue文件的代码行数是250行。如果系统中大量存在500行以上的代码文件,那么它就需要重构。
  2. 技术版本升级
    比如:Webpack2 -> Vue Cli,Vue2 -> Vue3

我们后面主要讨论如何偿还技术债务,消除代码中的坏味道

二、如何进行重构?

重构的过程可以分为确定目标、制定计划、进行重构和评估结果。

确定重构的目标

在实际的项目开发过程中,我们很难有时间进行整个系统的重构,更多的是在开发的间隙中进行小重构。我们需要明确重构的目标,估算时间和人力成本,确保它可以顺利的达成。
我们可以优先制定整个系统的重构目标,然后把它拆解成一堆小目标按顺序去达成。每个小目标对应一个小重构任务,就可以像PBI一样去管理它们了。比如:


image.png

制定重构计划

重构是小步快走,步步小心谨慎。

确认方向

重构计划要有一个整体的方向,可以为以下几种:

  1. 从全局到个体


    image.png
  2. 从个体到全局


    image.png

    在时间充裕的情况下,我们可以选择第一种方式, 它的影响范围大,需要更多的时间调整;在时间较短的情况下,比如正在工作当中,我们可以选择第二种方式, 它的影响范围更小,而且成果会经过不断的检验。后面主要讨论第一种方式。

列出重构的内容清单

根据重构的方向,分别列出重构的文件清单。
按照风险大小可以分为:

  1. 修改或增加了文档,对系统代码没有修改
  2. 只修改了样式,没有修改逻辑代码
  3. 修改了逻辑代码


    image.png

确定验收标准

重构是可以分段进行,在不同的阶段解决不同的问题,比如:我们此次重构可以解决css的问题,下次重构再解决js的问题。所以在重构之前以要列清楚此次重构的标准项。
部门暂时没有一个“重构标准”这样的文档去参考,当下主要是凭借我们自己的经验去总结。希望可以慢慢地形成部门的“前端重构标准”文档。


image.png

重构可以按照一个迭代任务来做,内容清单就是它的待办列表,重构的验收标准就是任务的的验收标准。

确定测试范围

在《重构-改善既有的代码设计》一书中作者反复的强调:确保即将修改的代码拥有一组可靠的测试。测试是我们进行重构工作的保障,所以需要我们列出此次改动的影响范围。
重构按影响范围我们可以分为:

  1. 影响整个系统。比如:修改了公共样式或者公共组件。那么需要对系统进行去全量测试。
  2. 影响某个页面。比如:某个页面是另一个开发写的,UI和交互跟系统的不一致。那么需要测试这个页面以及其关联页面。
  3. 影响了某个功能。比如:任务列表数据过多时,性能很差。那么需要测试这个功能以及使用到它的所有页面。


    image.png

进行重构工作

在进行重构工作之前,我们需要先建一个新的代码分支,确定重构的工作跟正在进行的开发工作相互不干扰。
重构主要分三种模式:

  1. 集中式的重构。随着需求的不断积累,开发的代码量会不断增大,系统越来越难以维护。团队在这个系统产出的价值已经快要低于开发团队的成本了,这个时候就需要花费单独的时间进行重构。开发团队期望通过一定的时间集中对代码进行整理和优化,让系统的症状得以缓解乃至根除。
  2. 阶段式的重构,它贯穿在整个开发过程中。项目开发过程中都会有休整期,这时就是进行重构的最佳时机。大家一起回顾之前开发中的系统遗留问题, 把对系统的维护和优化当做开发任务去做。
  3. 每日重构。开发人员每日检视自己的代码,并进行整理和优化。这是最理想的重构方式,也是最难的,由开发人员自主进行。跟codeReview的区别是:codeReview更侧重于检视代码中的问题,而重构则侧重于写出易于维护的代码。
    重构工作应按照计划 - 执行 - 测试 - 处理的循环来进行展开。
    image.png

    在集中式和阶段式的模式中,重构工作是由开发团队来承接的,团队里面包含了:产品、测试和开发。计划-执行 就是需求-迭代任务开发的过程,测试-处理就是测试提交缺陷-开发修改缺陷的过程。重构的内容本身就是需求开发的内容,跟着开发节奏走就可以了,一个迭代就代表着一次循环。
    在每日重构的模式中,重构工作是由开发个人进行的,需要自己来控制时间,并承受风险。它需要巧妙地借用开发团队,保证重构的代码能得到测试,所以重构的时机显得特别重要。这些时机是指某个需求的修改范围大于重构工作的测试范围,而我们正在开发这个需求的时候。
    image.png

    就像冲浪一样,我们需要提前准备好,等待一片合适的浪,然后乘浪而去。我们也需要优先计划重构的内容,甚至提前进行一些代码开发工作,将代码Commit到本地,当时机来临时,再Push上去,与系统的代码合并。这样的话,重构测试验证的工作就能与测试人员的工作重合了,就不需要我们自己为重构的风险买单了。
    切忌不要悄悄地修改了代码,然后成功地瞒过所有人。开发人员都有一种奇怪的自信:自己写过的代码没有任何问题。然而在实际项目中,这种自信可能会让系统处于危险之中。修改的代码没有经过测试和验证,直接合入了系统之中,它是很可怕的。一个优秀的程序员,都应该对系统代码,特别是生产环境上的代码,抱有一颗敬畏的心。
    每日重构会增加开发的工作量,增加风险,但是短期内不会带来更大的产出,所以能保持每日重构的程序员都是优秀的,是团队宝贵的财富。他们秉承一颗强烈的责任心,任劳任怨,一点一点地消除系统的风险,让它变的更好。
    不管是集中式、阶段式重构,还是每日重构,都需要按照计划 - 执行 - 测试 - 处理的循环来展开。测试验证是重构的重要保障,只有确认此次重构的内容对系统是没有风险的,我们才可以开启下一次的重构之路。

评估重构结果

我们有必要对重构的结果进行分析,以证明我们确实让系统变得更好。
在实际场景中,结束重构工作主要是3种:所有目标达成、部分目标达成和异常终止。
所有目标达成是指我们正常进行重构工作,并最终达成了我们所有的目标:让系统焕然一新,稳定高效,文件整整齐齐,代码整洁而优雅。
这是一种最好的结果,我们有充足的时间和人力把系统“清洗”干净,让它能够健康长寿。我们需要将它与之前的“旧面孔”作对比,证明它确实变“干净”了,我们做了很多事情。
我们需要做个统计,以展示我们的成果。
对于整个系统来讲,可以有以下指标:

image.png

对于某个组件的优化来讲,可以有以下指标:
image.png

对于函数方法的(方法是最小的代码单元)优化来讲,可以有以下指标:
image.png

部分目标达成是指我们正常进行重构工作,因为任务优先级的问题,我们不得不在暂停当前的任务,且已经达成了部分目标。重构是可以分阶段进行的,重构的目标也是可以分开的,所以部分目标达成也是对系统有益,并合并到一起的。除了按所有目标达成一样输出我们的重构成果以外,我们还需要列出已达成和未达成的目标。
image.png

异常终止是指因为人力和时间的原因,我们不得不结束当前的重构工作。当被异常终止时,说明所有的目标都没有达成。很遗憾,产出的价值为0。

对业务来讲,重构工作是不具有价值的,反而会带来额外的成本。它压根就不应该出现,因为它是开发过程中的遗留产物。所以通常情况下,重构只是开发团队迫切需要的,重构任务的优先级都要低于需求任务的优先级
开发团队很难说服业务人员进行集中式的重构,经常在需求开发的间隙进行重构工作。而且极有可能会被打断,因为有新的业务需求要开发。这是一种最糟糕的情况,代码写到一半被叫停,让人措手不及。所以我们在重构之前,一定要建一个新的代码分支。重构的代码与开发环境的代码不能相互影响。开发团队是为业务服务的,我们要优先保证业务的需求功能不受影响。
结束重构之后,评估重构结果,输出一份可以彰显成绩的分析报告,是对参与重构的开发最好的馈赠。我们需要对此次工作做一次总结和复盘,就像迭代回顾一样,以便于我们下一次更有序地进行。所有能进行重构的开发团队和人员都值得敬佩,因为他们能挺住了各方面的压力,就为了让系统变得更好。

三、结束语

随着代码的增加和开发的不断变更,系统会变得陈旧、多病,难以让人理解。这个时候就需要我们进行重构。重构的工作可能会消耗大量的人力和时间成本,且很难得到业务认可,所以我们一定要按照PDCA的循环来进行展开,充分测试和验证,尽量降低对现有业务的影响。集中式的重构是对病入膏肓的系统进入一次大型手术,阶段式的重构是对有瑕疵的系统不断进行理疗,而每日重构就犹如让系统拥有了人体自我调节修复的功能。每个进行重构的开发团队和开发者都值得敬佩,因为他们可能默默无闻地就干了一件好事情。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容

  • 大荔县心理咨询协会郭亚婵坚持分享滴752 天: 学习打卡的13天: Taylor也将焦点解决反思团队修改发...
    快乐有我_c00f阅读 91评论 0 0
  • 补昨日记: 代表部门发言,鬼使神差,脑子抽筋,不按原定计划讲,东扯西拉。年纪不小,胆子不大,似乎有点怯场,上不了台...
    5a7bd45c67f8阅读 59评论 0 0
  • 大辩若讷 ----老子《道德经》第四十五章 最厉害的辩论之才,好像是木讷的,不善于言辞的。在三国演义中东吴的鲁肃是...
    陆颜阅读 111评论 0 1
  • 巴菲特曾经说过,“必须有工作激情但又没有贪念,并且对投资的过程入迷的人才适合做这个工作。利欲熏心会毁了自己。当然,...
    文字先生阅读 102评论 0 1
  • 转载自微信公众号--《旧时楼台月》 作者:小林子说历史 (如有侵权,请联系) 74年11月,王近山被诊断出了胃癌,...
    高灯儿下亮阅读 138评论 0 0