【译文】如何坚持长期重构
在繁忙的公司中,很难完成大型(或 “长期”)重构。要取得成功,我们必须
- 说服业务部门值得延迟。
- 决定哪些功能需要等待。
- 定期更新状态和 ETA。
- 在重构过程中证明其合理性。这是正确的方法吗?
- 让自己不至于焦头烂额。
- 让团队有时间消化和回顾巨大的差异。
- 修复大量的 QA 问题。
而且我们最好尽快完成这一切,因为上帝不允许原始代码和重构代码共存!
这真的是唯一的办法吗?功能冻结、仓促上马、漏洞百出,很可能会让人精疲力竭?
另一种方式
我有一种理论,认为冗长的重构工作之所以被人诟病,是因为大多数重构工作所耗费的时间远远超出了我们的预期。漫长的重构会导致压力、笨拙的代码库、混乱的团队,而且往往看不到尽头。相反,如果我们有意识地进行长期重构呢?几年前,我开始尝试这种方法,并取得了令人惊喜的成功:
- 我们不需要就业务时间表进行谈判。
- 我们不需要与业务优先级竞争。
- 随着时间的推移,团队很快就理解了重构,甚至掌握了重构的主动权。
- 压力和倦怠风险没有增加。
- PR 很容易审核,没有巨大的差异。
- 整个团队始终如一地共同对重构进行重新评估。
- 我们从不浪费时间重构不需要的代码。
- 我们的功能开发依然畅通无阻。
- 团队拓展了架构知识。
- 新工程师的第一项任务就有了很好的来源。
- 我们循序渐进地推出了重构,使质量保证更加容易,并减少了错误。
长期重构让整个团队从一开始就参与进来,这是它最强大的地方之一。到目前为止,我已经在两家公司的至少 3 个不同团队中使用这种方法参与了约 10 次大型重构,还从未见过出错的情况。下面是我们的方法。
前提条件
开始时,您应该具备以下条件:
- 一名经验丰富的软件工程师,对重构工作有远见。
- 一支由不同专业水平的软件工程师组成的团队。
- 一个内部知识库。(任何 Github 维基、Notion、Confluence、Markdown 文件等)。
- 少于 ~5-10 个已在进行中的长期重构,具体取决于其范围。
过程
我遇到的几乎所有大型重构都遵循一种半一致的模式。重构之大,在于必须应用该模式的次数之多。在理想的情况下,这种劳动是分工合作的。不幸的是,重构往往需要逐个决策。我建议的流程以向同事解释重构想法为中心,这样他们也能做出决定。
注意:该流程适用于前提条件 1 中的 “经验丰富的工程师”。
1.确定应重构的代码。
2.确定重构模式。
探索代码库,找出需要修改的共同模式。现在有一个粗略的想法就可以了。忽略特殊情况,关注共性即可。
3.实施重构示例。
找到一个最小的代表性样本,将你的粗略模式应用到这个样本中,并对其进行重构。在这一点上,你要非常勤奋。试验并彻底完善你的模式。不要吝啬最佳实践。遵循留下代码注释的 4 个理由。传达 “如何”、”什么 “和 “为什么”。让它成为你最好的作品,因为它将成为团队其他成员的主要参考。提交合并请求。
4.为重构准备代码库。
既然你已经亲身尝试过重构、做出过决定并与摩擦作斗争,那么你对你的同事们将要面对的情况就有了一定的了解。利用你的经验为他们铺平道路。检查代码库,做一些小的准备工作:重新调整代码、填补空白、重新命名以提高清晰度、解决歧义、创建新的目录结构。改动要小。不要自己重构所有内容。关键是要分担大部分工作。提交合并请求。
5.为重构命名
给重构起一个方便的名字,以便在讨论和文档中使用。确保名称简洁、清晰并具有描述性。例如,”移除对 [package X] 的依赖”。
6.编写重构说明。
在内部知识库中创建一个文档,并用步骤 5 中的名称作为标题。一些提示:
- 明确说明要做什么以及如何做。简明扼要。
- 不要讲故事:”多年来,我们意识到我们一直使用的方法……”
- 列出具体步骤:”找到一个有函数 X 的类,创建名为 Y 的新类,将函数 X 移入类 Y”。当然,步骤不可能都很简单,但你可以挑战一下自己,看看自己能把步骤写得多么简短和具体。
- 将步骤 3 中的合并请求示例链接起来。人们应该看到前后的代码。
- 最后,在结尾处随意添加一些上下文。在这里,欢迎你提供背景、讲述故事、链接相关资源和讨论。不过,请将这一部分隐藏在一个可扩展的元素下,比如 <details>。我们希望文档专注于模式本身,并在需要时提供扩展上下文的选项。
7.将此重构添加到长期重构列表中。
确保知识库中有一个页面列出了所有长期重构。步骤 6 中的文档应添加到该列表中。
8.向团队介绍此次重构。
可以使用书面公告或会议的形式。向他们解释如何挑选需要重构的代码块,并以你的示例来引导他们。别忘了把你在第 6 步中编写的说明链接起来。让工程团队了解当前正在进行的每一次长期重构是非常重要的。这就是为什么你希望一次只介绍几个,并正确介绍每一个的原因。添加新的长期重构应该是一件大事。
9.分配重构任务。
重构工作已经准备就绪,可以随着时间的推移逐步完成,但我建议不要在任务跟踪器中预先创建所有任务。这样做的主要好处之一就是不会在不重要或即将删除的代码上浪费时间。相反,在计划中自然而然地出现任务时再创建任务。”嘿,既然你要修改这个,也许可以在修改的同时移除对 X 软件包的依赖?此外,我建议将整个伞形重构远离任务跟踪器,或至少远离业务人员能看到的地方。一个成功的长期重构应该由工程师来跟踪,而不是公司管理层。只要它被写入知识库,并一直存在于工程师的脑海中,那就没问题了。至于重构是否完成、需要多长时间,这对企业来说并不重要。
10.注意长期重构。
让每位新加入团队的工程师阅读第 7 步中的列表。确保在入职流程中包含这一步骤。这也是他们的第一项任务,帮助他们了解现有代码和新方向。随时参考列表很方便(记住,列表必须简短),而且工程师们在计划时也会互相提醒这些重构。
11.完成重构。
长期重构并不需要 100% 完成。相反,有一天你会发现你的文档是多余的,因为代码库已经说明了一切。如果所有的主要部分都已重构,而且你的方向也不再令人困惑,那么你就可以放心地将其标记为 “已完成”。这就为下一个文档创造了空间。
在认真遵循这一流程后,我看到了一些很棒的事情发生。团队养成了根据需要自行分配重构的习惯。当他们有问题时,他们会发起讨论和会议。这让每个人都能站在同一条战线上,共同做出如果单独做出可能会引起争议的决定。每完成一项重构任务,我们都会获得新的范例,以便在接下来的任务中加以借鉴。
相比之下,自己独自工作数周或数月,却给团队带来了巨大的差异。
缺点
以下是我能想到的一些缺点。
- 尽管很少见,但有些大型重构并没有共同的模式。有可能你实际上在处理多个重构,而这些重构不应该归属于同一个范畴。请尝试将它们分开。
- 你需要耐心来完成这些重构。它们可能跨越一年、两年,谁知道呢。在这段时间里,新旧代码会共存,如果步骤 7 中的列表没有被每个人牢记,可能会造成一些混乱。我个人在实践中没有遇到过这种弊端,因为这个过程始终让每个人都保持在同一起跑线上。通过组织和沟通,没有人会对我们的出发点和目的地感到困惑。
- 代码的某些部分可能永远不会被重构。这可能是有原因的。可能是因为这部分代码很容易维护,不需要更改。又或者,这部分代码即将被淘汰。把这看作是一种胜利–你节省了时间,也没有引入不必要的错误。
- 如果你喜欢独自完成所有事情,那就不适合采用这种方法。这种方法旨在让每个人都站在同一战线上。您必须就解决方案达成一致,并阐明您的理由。如果你不喜欢这样做,你就不会喜欢长期重构。
试试吧,告诉我结果如何!
本文文字及图片出自 Long Term Refactors
你也许感兴趣的:
- 【外评】好的重构与不好的重构
- 【译文】高风险重构
- 【译文】关于重构的十条戒律
- 再见了,干净整洁的代码
- 十年“屎山”终重构,但 QQ选用了微软 Teams 放弃的 Electron
- 重构的重构 – 《重构》第二版导读
- 代码重构技巧
- 代码重构的那些坑和实战经验
- [外文翻译]Martin Fowler:机会主义式的代码重构
- 代码审查与重构的5个层次
你对本文的反应是: