第三章 架构重构方法论:绞杀者模式、修缮者模式、重构优先级矩阵
架构重构这事儿,说起来容易做起来难。我见过太多团队,一上来就喊着「我们要重写整个系统」,结果呢?半年过去了,新系统没跑起来,老系统也改不动了。说白了,重构不是推翻重来,而是有策略地逐步改善。
这一章,我跟你聊聊三种实战中摸爬滚打出来的重构策略。它们不是什么高深理论,而是我在多个嵌入式项目里真刀真枪用过的招数。
3.1 绞杀者模式(Strangler Fig Pattern)
这个名字挺有意思,绞杀者是一种植物,它缠绕在宿主树上慢慢生长,最终取代宿主。用在软件重构上,意思就是:不直接删除旧代码,而是在旧系统外围构建新功能,逐步把旧模块替换掉。
我在一个工业控制器的项目里用过这招。那套系统跑了七八年,主控模块的代码耦合得跟麻花似的。客户要求加新协议支持,但旧代码一动就崩。怎么办?
我的做法是:在旧系统旁边搭一个新模块,通过一个适配层跟旧系统通信。新协议全部走新模块,旧协议继续跑老代码。等新模块稳定了,再把旧模块的功能一点点迁移过来。
具体步骤是这样的:
- 识别边界 — 找到旧系统中可以被替换的独立功能模块。
- 建立适配层 — 写一个接口层,让新旧系统能互相调用。
- 增量替换 — 每次只替换一个功能点,测试通过后再继续。
- 清理旧代码 — 旧模块完全被替代后,删掉它。
你想想看,这跟外科手术似的,一刀一刀切,而不是拿大锤砸。我建议你在以下场景用绞杀者模式:
- 旧系统还在线上跑,不能停机
- 旧代码没有单元测试,不敢大改
- 团队对新架构还不熟悉,需要时间学习
3.2 修缮者模式(Builder Pattern)
绞杀者模式适合替换大模块,但有些时候,你不需要替换整个模块,只需要在原有基础上「修修补补」。这就是修缮者模式——在旧代码内部做局部改造,不改变外部接口。
我记得有个传感器数据采集的项目,采集线程里塞了一大堆业务逻辑:数据校验、滤波、存储、报警判断……全揉在一个函数里。每次改需求,都得动那个函数,改完就出bug。
我没急着重写,而是用了修缮者模式:
- 先把数据校验抽成一个独立函数
- 再把滤波算法单独拎出来
- 存储和报警也各自拆开
每次只拆一个功能,拆完就跑测试。一个月下来,那个大函数从800行变成了80行,每个小模块都能单独测试。外部接口没变,但内部结构清爽多了。
修缮者模式的核心原则:
- 接口不变 — 外部调用者感知不到变化
- 小步改造 — 每次只重构一个内部细节
- 测试先行 — 改之前先写测试,确保行为不变
- 持续集成 — 每次改动都要能编译通过、跑通测试
3.3 重构优先级矩阵
好,现在你知道了两种模式,但问题来了:先改哪个模块?
我见过不少团队,一上来就挑最烂的模块下手,结果改到一半发现那个模块其实很少被调用,投入产出比极低。这就是典型的「用战术勤奋掩盖战略懒惰」。
我的做法是画一个重构优先级矩阵,横轴是「模块变更频率」,纵轴是「代码质量评分」。这样一画,四个象限就出来了:
| 象限 | 变更频率 | 代码质量 | 优先级 | 策略 |
|---|---|---|---|---|
| 第一象限 | 高 | 低 | 最高 | 立即重构(绞杀者或修缮者) |
| 第二象限 | 高 | 高 | 中 | 保持,定期评审 |
| 第三象限 | 低 | 低 | 低 | 记录问题,暂不处理 |
| 第四象限 | 低 | 高 | 最低 | 不动它 |
你看,第一象限的模块才是你的「心腹大患」——经常要改,但代码又烂。这种模块不改,每次改需求都是在刀尖上跳舞。
怎么给代码质量打分?我一般看这几个指标:
- 圈复杂度 — 超过15就要警惕,超过30必须重构
- 函数长度 — 超过200行的函数,基本是「万金油」
- 耦合度 — 改一个地方,要动几个文件?超过3个就算高耦合
- 测试覆盖率 — 低于30%的模块,改起来心里没底
下面这张图是我常用的重构决策流程,你可以参考:
3.4 三种策略如何选?
好了,现在你有了三种武器:绞杀者、修缮者、优先级矩阵。怎么搭配使用?
我个人的习惯是这样的:
- 模块边界清晰,且需要替换整个功能 → 用绞杀者模式
- 模块内部混乱,但功能稳定,接口不能变 → 用修缮者模式
- 不知道从哪下手 → 先画优先级矩阵,找到第一象限的模块
最后说一句:重构不是炫技,是投资。你把时间花在刀刃上,代码质量会给你回报。花错了地方,那就是沉没成本。优先级矩阵就是帮你做这个判断的。