写点什么

与其硬啃“屎山”代码,不如用这六步有条不紊实现代码重构

  • 2022-04-28
  • 本文字数:2851 字

    阅读完需:约 9 分钟

与其硬啃“屎山”代码,不如用这六步有条不紊实现代码重构

对大规模系统进行重构,如果一个人对着又臭又长的代码硬刚,即使花了大量的时间进行手工验证,最后仍然会有很多问题,特别是一些深路径及特殊场景下的问题。其实,大规模的系统级别重构时是有方法的。我们采访了 Thoughtworks 数字化转型与运营 资深咨询师黄俊彬(QCon+案例研习社讲师),请他来分享 MV*模式重构演进的方法和经验。

 

InfoQ:请问,开发人员什么时候需要进行代码重构呢?

 

黄俊彬:重构的范围很广,基于实际对代码的调整的工作量及影响范围,可以细分为表中 3 种类型:


类型

修改范围

示例

小型重构

对单个类内部的重构优化

重命名、提取变量、提取函数等

中型重构

对多个类间的重构优化

提取接口、超类、委托等

大型重构

针对系统组件架构重构优化

单体应用组件化等


由于不同类型的重构影响及工作量不同,重构时机也不同:

 

  • 小型重构,建议任何阶段及时重构,同时借助 IDE 提供的自动化重构,保证安全。

  • 中型重构,建议在添加新功能或者修复 Bug 时集中设计及修改,需做好测试。

  • 大型重构,特别针对大型的遗留系统改造,建议立专项,结合业务的迭代需求,将大型的重构进行拆分,在不同的研发迭代中进行。


InfoQ:您在 QCon+分享了 MV* 模式重构演进,请问在重构的过程中,有什么通用的流程吗?


黄俊彬:在 MV*模式重构演进分享中,我将重构分为了 3 个维度 6 个步骤,如下图所示:



对于遗留系统来说,通常最常见的问题就是需求的上下文存在断层,所以第一步需要尽可能地分析了解原有的业务需求。


第二步是需要仔细去分析原有的代码设计,分析原有代码的设计及存在的坏味道,作为重构后的改进项及有优化点。


第三步,补充守护测试。在开始进行重构时先补充中大型的自动化测试将主要的业务场景进行覆盖,每当小步进行安全重构时都能运行测试进行快速的反馈,更好地减少修改代码导致的风险。


第四步是进行简单设计,结合未来架构的设计模式,设计关键的接口及数据模型,作为重构的输入。在这一步通常先结合未来的架构设计划分出主要的分层,例如 MVP 模式会有 Model、View 及 Presenter 层。接下来需要重新梳理领域模型,重新划分出合适的模型。最后需要定义出层之间关键的接口,例如 MVP 中 View 及 Presenter 之间交互及会调的接口。


第五步,进行小步安全重构。在重构的过程中尽可能运用前面重构基础中介绍的安全重构手法,减少人工修改,并且在过程中尽可能做到小步提交及借助测试进行频繁验证,逐步将代码修改为设计的架构模式。


第六步,集成验收测试。重构后的代码需要保证编译通过、所有的自动化测试运行通过及进行集成的验证。


InfoQ:您认为在重构过程中,如何更好提高效率及安全性?


黄俊彬:重构如果在没有好的保障机制下,很容易引起新的问题。这里有 4 种在重构过程中常用的技术实践,可以更安全及高效地对代码进行重构。


第一是结对进行重构,通过实时 Review 保障正确性。


例如在对某大型的通讯类系统进行重构时,我与客户的架构师一起结对进行重构。因为客户的架构师熟悉业务及原有代码的上下文,在结对进行重构时的一些上下文能实时进行确认,能更有效地保障重构的安全性。


第二是尽可能自动化,借助 IDE 的安全重构进行优化,避免手工修改代码的风险。


在进行大型重构时,我们经常需要移动相关的代码及类到合适的位置。特别是当移动的类有关联到其他相关的类的时候,手工进行移动风险非常大,效率也非常低。


在这种场景下,我们可以借助 IDE 的 Move 或者 Moduriaze(Android Studio 带的功能)进行重构,像 Moduriaze 能够智能分析出移动的类及其关联的所有类与资源,一把进行自动化的移动,大大提高了安全性及效率。


第三是增加测试保护,借助自动化测试,在每次重构时频繁执行进行保障,及时反馈。


这里要特别说明的是,很多遗留的系统由于代码的腐化,存在大量的上万行的类及大几千的方法,比较难编写单元测试。在对遗留系统增加的自动化测试的策略上,通常会先覆盖中大型的接口测试或者 UI 测试,守护核心的业务逻辑。在重构完成后,再及时补充小型的单元测试。


第四是小步前进,让每笔提交尽可能小,方便进行问题定位及回滚。


InfoQ:如何更好去度量重构的结果呢?


黄俊彬在重构的过程中,一定要以终为始,思考清楚重构是为了解决什么样的问题,建立有效的度量反馈机制。例如希望将遗留代码重构成为新的架构模式,我们就必须度量重构后的代码是否符合新的架构设计模式,并且尽可能通过自动化的方式进行约束及统计。比如重构为了简化代码的复杂度,如过长的类及方法,我们就必须度量重构的代码复杂度,如圈复杂度、类及方法长度、重复率等。


实际上,通过度量反馈机制,可以让重构的价值更显性比如,中小型的重构可以通过观察代码的健康度相关的指标来显性重构的价值,如重构后代码的圈复杂度、平均函数行数、类行数等指标。大型的重构可以通过工程效率上的指标来显性重构的价值,如组件化后的编译速度的提升,组件化后发布的效率等。


InfoQ:代码重构有哪些常见阻碍因素呢?该如何解决呢?


黄俊彬:重构落地的阻碍因素,我认为主要受下面三个因素影响。


1. 重构带来的价值不够显性。重构后不会改变软件可观察行为,其价值不够显性,往往优先级都会排列在业务迭代之后。


2. 没有足够的重构时间窗口。在实际项目中不可能将业务停下来专门预留充足的时间窗口来进行重构,结合上面提到的重构时机,中小型的重构还是需要结合在日常的开发过程中,化整为零。


3. 缺少激励,风险高。如果组织中缺少这方面的文化及保障机制,重构往往让技术人员望而却步。一方面需要结合有效的度量指标来引导技术人员进行重构,另一方面也需要从组织上做好激励机制,鼓励将重构工作也作为技术故事排入迭代开发中来。


InfoQ:你印象最深的一次遗留系统重构实践是什么?为什么令你印象深刻?


黄俊彬:我印象最深的的一次遗留系统重构是给一个客户做一个超级 App 重构,这次重构主要是进行架构上的优化。让我印象比较深刻的点是因为这个应用规模比较大,代码在百万行级别,开发人员也达到 200+,全量编译构建达到 15 分钟以上。


在系统分析的过程中,我们发现业内像 Sonar 等工具更多是对现有的代码进行通用的代码坏味道扫描,对于遗留系统的大型重构通常需要将现有的系统重构为新的架构模式,所以必须以未来的架构进行输入去梳理出当前系统需要解除的耦合。


基于这个诉求我们自己开发了工具,以未来的架构作为输入,对代码进行扫描分析,梳理出依赖清单,然后基于依赖清单进行重构。


在这个案例中,最后一个业务组件解耦独立出来后,一次组件的构建调试只需要 1 分钟。


嘉宾介绍:黄俊彬,Thoughtworks 数字化转型与运营 资深咨询师,10 年软件开发、设计和架构经验。在移动开发领域的应⽤性能优化、自动化测试、架构设计及组件化等⽅向有丰富的经验。目前主要在智能硬件、通信、互联网、金融等领军企业提供敏捷转型、性能优化、系统架构改造、大型遗留系统重构等服务。


活动推荐:今年 7 月,ArchSummit全球架构师峰会将落地深圳站。官网现已上线研发效率提升、可观测性技术落地探索、出海业务架构、单云架构到多云架构转型、微服务架构落地实践、架构师能力模型、开源和自研选型思考、云原生前沿技术、IoT 系统架构设计、金融领域数字化转型等十余个热门专题,扫描下方二维码即可查看精彩内容。


现在购票可享 8 折特惠,单人购票立减 1760 元,团队购票优惠更多。购票请扫码或咨询:18514549229(微信同电话)



2022-04-28 14:555909

评论

发布
暂无评论
发现更多内容

Flink 最佳实践之 通过 TiCDC 将 TiDB 数据流入 Flink

TiDB 社区干货传送门

性能调优

线上mysql改表操作导致tidb同步延迟解决方法

TiDB 社区干货传送门

TiDB 记录日志原理解读

TiDB 社区干货传送门

TiDB 底层架构

pd集群多副本数据丢失以及修复实践

TiDB 社区干货传送门

实践案例

TiDB 监控架构解读

TiDB 社区干货传送门

监控

PD api基础框架源码分析

TiDB 社区干货传送门

TiDB 底层架构

TiDB HTAP 深度解读

TiDB 社区干货传送门

TiDB 赋权问题

TiDB 社区干货传送门

故障排查/诊断

TiDB run and debug on M1

TiDB 社区干货传送门

实践案例 安装 & 部署

TiFlink: 使用 TiKV 和 Flink 实现强一致的物化视图

TiDB 社区干货传送门

实践案例 TiDB 底层架构

伴鱼数据库之SQL审核系统

TiDB 社区干货传送门

PD api基础框架源码分析

TiDB 社区干货传送门

TiDB 底层架构

伴鱼数据库之监控系统

TiDB 社区干货传送门

TiDB AutoCommit OFF 问题

TiDB 社区干货传送门

实践案例 故障排查/诊断 新版本/特性发布

TiDB Coprocessor 学习笔记

TiDB 社区干货传送门

TiDB 底层架构

一个联合索引使用问题以及优化方案

TiDB 社区干货传送门

管理与运维 故障排查/诊断

TiDB大规模删除实践

TiDB 社区干货传送门

管理与运维

国产主流数据库调研

TiDB 社区干货传送门

性能调优 实践案例

从使用者到开发者,知乎参与 TiDB 社区背后的故事

TiDB 社区干货传送门

实践案例 数据库架构选型

把云数据库服务变成黑盒子:ServerlessDB for HTAP丨Hacking Camp 进行时

TiDB 社区干货传送门

实践案例

PD 关于tso 分配源代码分析

TiDB 社区干货传送门

TiDB 底层架构

不定期更新,记录一些小知识

TiDB 社区干货传送门

监控 版本升级 安装 & 部署

Tidb灾难恢复演练-多副本丢失

TiDB 社区干货传送门

故障排查/诊断

小红书数据架构及 TiDB 使用场景

TiDB 社区干货传送门

使用Zabbix监控TiDB(一)

TiDB 社区干货传送门

实践案例

微众银行数据库架构演进及 TiDB 实践经验

TiDB 社区干货传送门

实践案例

【TiDB 最佳实践系列】PD 调度策略最佳实践

TiDB 社区干货传送门

实践案例

一次 meet_lock 告警异常处理过程

TiDB 社区干货传送门

实践案例 故障排查/诊断

【TiDB 4.0 新特性系列】BR 特性及原理解读

TiDB 社区干货传送门

TiDB GC 之原理浅析

TiDB 社区干货传送门

TiDB 底层架构

Placement Rules 原理

TiDB 社区干货传送门

TiDB 底层架构

与其硬啃“屎山”代码,不如用这六步有条不紊实现代码重构_文化 & 方法_李慧文_InfoQ精选文章