遗留系统与技术债务
一、什么是技术债务
技术债务(Technical Debt)是 Ward Cunningham 的比喻:为了尽快交付而采用「先这样写」的折中,就像借钱——当下省时间,日后要还「利息」(更难改、更多 bug、更慢迭代)。债务不一定是错的:有时合理借一点债能赶上窗口期;但若一直不还,利息会滚大,最终举步维艰。
常见来源: deadline 压力下的抄近路、缺乏重构与测试、人员流动导致知识流失、依赖与平台老化。还债方式包括:专门安排重构与文档时间、在需求迭代中「顺带」还债、用自动化与测试保护存量逻辑。关键是把债务显式化(列清单、估成本)、与业务方沟通优先级,避免「永远在还旧债」或「永远不还」两种极端。
二、遗留系统的特征与风险
遗留系统(Legacy System)通常指运行多年、仍在服役但难以演进的一类系统。常见特征:文档缺失或过时、依赖老旧(语言、框架、运行环境)、测试不足、结构混乱(耦合高、职责不清)、知识在个别人脑中(bus factor 低)。
风险:改动容易引入回归、招人难(技术栈冷门)、安全与合规隐患(老依赖有漏洞)、扩展与集成成本高。但遗留系统往往承载核心业务,不能简单「关掉重写」;要在评估(债务清单、影响范围、还债成本)基础上,制定增量改进或渐进替换策略。
遗留系统常见特征与风险
- 文档缺失、依赖老旧、测试少、结构乱、知识集中少数人
- 风险:改不动、招人难、安全与合规、扩展与集成成本高
- 先评估再改进,避免盲目重写或长期不还债
三、评估与增量改进策略
评估:列出债务项(模块/依赖/缺失测试/文档)、估影响(改动成本、故障面)、排优先级(高影响且可动手的先做)。可结合代码度量(圈复杂度、依赖关系)、历史故障与变更热点,找出「最痛」的点。
增量改进:不追求一次还清,而是每次迭代留一点时间还债、或新需求顺带重构相关模块。建立回归测试与 CI,防止还债时引入新问题;文档与注释随改随补。这样债务可控、业务不停,团队也有持续的正向反馈。
评估与增量改进要点
- 评估:债务清单、影响与成本、优先级;结合度量与历史数据
- 增量:每迭代留时间还债、新需求顺带重构、测试与 CI 保护
四、Strangler Fig 与防腐层
Strangler Fig(绞杀者模式):不一次性替换整个系统,而是在旧系统外围逐渐长出新功能,新请求先走新实现,老请求仍走旧逻辑;随着新实现覆盖越来越多场景,旧代码被「绞杀」、最终可下线。例如:在网关或路由层把新 API 指到新服务,老 URL 仍指到老系统;或在新老之间加一层,逐步把调用从老迁到新。这样风险可控、可随时回退、业务不中断。
防腐层(Anti-Corruption Layer, ACL):新系统不直接依赖遗留系统的「脏」模型与接口,而是通过一层适配:把老系统的数据与调用转成新系统能理解的模型与语义,隔离老系统的怪异与变更。ACL 属于新系统一侧,老系统接口变动时只需改 ACL,不污染新域模型。常用于新旧系统并存、或对接第三方遗留接口时。
五、何时重写、何时不
慎重重写:重写成本高、周期长、容易重复踩坑(需求理解不全、隐性依赖未发现)。只有在「遗留系统已严重阻碍业务、且增量改进与 Strangler 都难以推进」时,才考虑整体重写;且要当做一个新项目做需求与设计,而不是「照抄老系统」。
优先不重写:能通过增量还债 + Strangler + 防腐层解决的问题,优先用这些方式。先稳住运行、补测试与文档、用 ACL 隔离新旧,再逐块替换或重构。这样业务连续、风险分散、团队也能在过程中积累对新设计的理解。
何时重写、何时不
- 慎重重写:成本高、易重复踩坑;仅当遗留严重阻碍且增量/Strangler 难推进时考虑
- 优先不重写:增量还债、Strangler、防腐层能解决则先用;重写当新项目做需求与设计
一句话: 技术债务像借钱,要显式化与还债计划。遗留系统特征明显、风险要评估。增量改进与Strangler Fig、防腐层优先于整体重写;何时重写要谨慎,能渐进则渐进。
六、小结
技术债务:短期省事、长期付利息;要评估、排优先级、增量还。遗留系统:文档缺、依赖老、测试少、知识集中;先评估再改进。Strangler Fig:外围长新、逐步替换;防腐层:隔离老接口与模型。何时重写:慎重重写,优先增量与 Strangler。下一章讲架构演进与重构策略,从演进式架构、fitness function 到大规模重构与 ADR。