内容提要
重构遗留代码前,应先进行“代码库考古”,用AI辅助理解系统而非直接修改。重点包括:映射仓库结构、追踪业务能力、区分业务规则与基础设施、发现隐式契约和副作用、记录不确定性,并验证AI结论。理解优先于重构,避免在未掌握上下文时贸然改动,否则可能破坏关键行为。
延伸解读
为什么理解先于重构
遗留代码中的奇怪条件、重复计算或糟糕命名,往往编码了重要的业务知识或外部契约。直接重构可能破坏关键行为,甚至引发多年前的生产事故。文章强调,AI虽然让阅读代码更容易,但也让在理解之前修改代码变得更容易。因此,在重构前进行“代码库考古”,先回答“为什么”的问题,比立即动手修改更安全。
AI作为调查工具而非解决方案
文章建议将AI置于“调查模式”而非“解决方案模式”,避免过早提出重构方案。有效的提示应要求AI引用文件证据、标记不确定性,并列出无法从代码中回答的问题。AI最有价值的输出有时是“我不知道”或“无法确定”,这能引导工程师关注真正需要调查的领域,而不是生成看似合理但可能错误的解释。
识别隐式契约与副作用
遗留系统常包含未声明的隐式契约,如API响应格式、事件负载、数据库字段等,外部消费者可能依赖这些细节。同时,函数可能产生隐藏副作用,如发送邮件、更新缓存、触发任务等。重构时若只保留返回值,可能破坏这些行为。文章建议通过AI列出所有副作用和潜在契约,并验证其幂等性和重试语义,以降低迁移风险。
验证AI结论的重要性
AI生成的解释可能听起来合理但不完整。文章强调,每个重要发现都应通过其他来源验证,如仓库搜索、测试、数据库模式、日志和Git历史。例如,使用`rg`搜索函数调用,或通过`git log -S`查找引入特定条件的提交。AI可以加速搜索,但不能替代验证,确保结论基于证据而非推测。
Q&A
为什么在重构遗留代码之前需要先理解代码库?
因为遗留代码可能包含重要的业务知识,如特殊条件可能编码了业务异常,重复计算可能因为两个看似相同的过程实际上不同,数据库列名可能属于外部契约,不理解就修改可能破坏关键行为。
如何开始分析一个遗留代码库?
从仓库结构开始,而不是逐个文件阅读。识别入口点、主要模块、数据库技术、外部集成、后台处理、定时任务、认证机制、配置来源、测试和可能的架构边界。使用AI辅助,但要求引用文件作为证据,并标记不确定项。
如何找到遗留系统中的所有入口点?
不要只分析HTTP控制器,还要查找定时任务、队列消费者、数据库触发器、CLI脚本、文件导入、邮件处理、webhook等。使用AI搜索所有能创建、修改、批准、取消或持久化业务对象的位置,并用仓库搜索验证结果。
如何追踪一个业务能力在代码库中的流转?
选择一个具体的工作流,如“创建订单”,从入口点开始,逐步追踪到所有可观察的副作用完成。每一步记录文件、函数、输入、输出、状态变化、外部调用和错误行为。不要合并步骤,以便检查。
如何区分业务规则和基础设施代码?
使用AI将代码中的每个职责分类为业务规则、应用编排、持久化、缓存、消息传递、日志、验证或未知。例如,企业客户信用额度限制是业务规则,而MySQL、Redis和事件总线操作是基础设施。不要移动或重写代码。
如何发现遗留代码中的隐式契约?
查找API响应、事件、数据库结构、CSV导出、文件名、环境变量、错误消息、队列负载和webhook体等输出。使用AI识别可能被外部消费的输出,并询问证据,而不是直接假设存在契约。
如何验证AI对代码库的分析结果?
使用仓库搜索、测试、数据库模式、日志和可观测性、版本历史等证据来验证AI的结论。例如,用rg搜索函数调用,检查测试中的假设,查看数据库约束,利用Git历史解释奇怪的条件。
在重构前应该记录哪些未知问题?
记录无法从仓库安全回答的问题,例如为什么某个阈值是10000,某个事件是否被外部消费,某个状态转换在哪里发生等。这些问题对重构、迁移、模式更改、接口更改和代码删除至关重要。
如何将代码库理解转化为迁移计划?
首先确定必须保护的行为(如定价、API响应、支付负载、事件模式),然后决定可以重构的边界(如定价策略、库存网关),最后标记需要调查的阻塞项(如库存重试行为、事件消费者)。
在遗留代码现代化项目中,不应该首先让AI做什么?
避免一开始就要求AI重写应用、转换为微服务、现代化整个仓库或找出所有坏代码。这些提示已经包含了解决方案,而应该先问“系统实际做什么?”、“我还不理解什么?”、“应该改变什么?”。