news 2026/10/4 7:03:45

老系统迁移无文档?从代码逆向提取PRD的实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
老系统迁移无文档?从代码逆向提取PRD的实战指南

1. 接手一个没有文档的老系统,到底难在哪

很多做企业级开发的朋友都遇到过这种局面:领导拍着你的肩膀说,这套系统跑了五六年了,现在要迁移到新架构,你先把需求文档整理出来。你打开代码仓库一看,别说需求文档了,连像样的注释都没几行,README 还是三年前某位已经离职的同事随手写的两句话。数据库里几十张表,字段命名风格从拼音缩写到英文全称混着来,前端页面点进去功能倒是能跑,但没人说得清每个按钮背后的业务规则。

这就是典型的“代码即文档”状态。系统还活着,业务还在跑,但知识已经随着人员流动散掉了。你要做的不是重新发明需求,而是把已经存在于代码里的隐性知识,逆向提取成一份能指导迁移的 PRD。这件事的核心逻辑其实很朴素:代码是系统行为的唯一真相来源,数据库结构、接口定义、前端交互、定时任务、消息消费,这些加起来就是一份比任何文档都精确的需求说明书,只不过它用的是机器语言。

我接手过一套基于 Spring Boot 加 Vue 的多商户商城系统,前后端分离,后端大概四十多个 Controller,前端三十多个路由页面,数据库 MySQL 里一百多张表。原计划两周出迁移 PRD,实际花了将近一个月。踩过的坑、总结的方法,下面一点点拆开讲。

这篇文章适合三类人看:一是正在做老系统迁移、需要补文档的后端或全栈工程师;二是技术负责人,想了解逆向梳理的可行路径和工期预估;三是对 Spring Boot 和 Vue 技术栈有一定了解、想学习如何从代码反推业务的学习者。不需要你精通逆向工程,但需要你能读懂基本的 Java 和 JavaScript 代码。

2. 逆向迁移 PRD 的整体思路与工具选型

2.1 为什么不能直接照着代码翻译成文档

最容易想到的做法是打开每个 Controller,把接口路径和参数抄下来,整理成表格。我一开始也这么干,做了三天就发现行不通。原因有三个:第一,接口数量太多,纯手工抄写效率极低且容易遗漏;第二,接口只是入口,真正的业务规则藏在 Service 层的条件判断里,比如“订单金额大于 500 且用户等级为 VIP 时才免运费”,这种规则不读透代码根本提取不出来;第三,前端页面上的交互逻辑,比如某个字段在什么条件下才显示、某个按钮点击后触发几个接口调用,这些信息分散在 Vue 组件里,光看后端接口是拼不完整的。

所以正确的思路不是“翻译代码”,而是“重建业务模型”。具体来说,分四层来拆:数据层看表结构和字段约束,服务层看业务规则和状态流转,接口层看对外契约和调用关系,交互层看用户操作路径和页面流转。这四层信息交叉验证,才能拼出一份完整的需求画像。

2.2 工具链的选择与理由

工欲善其事,必先利其器。我实际用到的工具组合如下:

工具用途选择理由
IntelliJ IDEA 社区版阅读 Spring Boot 源码免费,对 Java 生态支持好,全局搜索和调用链追踪够用
MySQL Workbench导出表结构、查看索引和外键可视化直观,能直接导出 DDL
Swagger 或 SpringDoc自动提取接口文档如果项目集成了就直接用,没集成可以临时加依赖
Vue DevTools查看组件树和路由结构浏览器插件,能快速理清前端页面层级
PlantUML画状态流转图和时序图文本化绘图,方便版本管理和修改
数据库逆向工具生成 ER 图比如 MySQL Workbench 自带的 Reverse Engineer

这里重点说一下 IntelliJ IDEA 社区版。很多人觉得社区版功能不够,但对于读代码这件事,它的全局搜索(Ctrl+Shift+F)、查找用法(Alt+F7)、调用层级(Ctrl+Alt+H)完全够用。我通常的做法是先用全局搜索找到所有 Controller 类,然后逐个追踪每个接口的调用链,一直追到 Mapper 层的 SQL 语句。这个过程虽然笨,但最可靠。

提示:如果项目用了 MyBatis,建议把 Mapper XML 文件全部打开,因为很多业务查询逻辑直接写在 SQL 里,光看 Java 代码会漏掉关键过滤条件。

2.3 逆向 PRD 的文档结构设计

一份能指导迁移的 PRD,和写给新产品用的 PRD 不一样。新产品 PRD 侧重“要做什么”,迁移 PRD 侧重“现在是什么”和“迁移后必须保持什么”。我的文档结构是这样的:

第一部分是系统概览,包括技术栈、部署架构、模块划分。第二部分是数据模型,包括核心表结构、字段含义、表间关系。第三部分是功能清单,按模块列出所有功能点,每个功能点标注对应的接口、页面和业务规则。第四部分是状态流转,把订单、支付、退款等核心业务的状态机画出来。第五部分是迁移风险点,标注哪些逻辑是隐性的、容易在迁移中丢失的。

这个结构的好处是,开发人员拿到后可以直接对照着写新代码,测试人员可以对照着设计测试用例,产品经理可以对照着确认业务完整性。

3. 从数据库和代码中提取核心业务规则

3.1 数据库表结构逆向:从字段名读出业务含义

数据库是系统的骨架。我拿到一套陌生系统,第一件事就是导出所有表的 DDL,然后逐张表分析。以那套多商户商城为例,一百多张表里,核心表大概二十张,包括用户表、商户表、商品表、订单表、订单明细表、支付记录表、退款表、物流表、优惠券表、评价表等。

看表结构的时候,重点关注几类信息。第一类是字段命名,比如is_deleted、status、type这种字段,往往对应着业务上的软删除、状态机和分类逻辑。第二类是索引,唯一索引通常意味着业务上的唯一性约束,比如order_no唯一索引说明订单号不能重复。第三类是外键关系,虽然很多互联网项目不建物理外键,但通过字段名也能推断出关联关系,比如order_id关联订单表。

我遇到过一个坑:订单表里有个source字段,类型是 tinyint,注释写的是“来源”。光看这个根本不知道有哪些取值、分别代表什么。后来在前端代码里找到了一个下拉框的选项列表,才确认 1 代表 App、2 代表小程序、3 代表 H5。这种信息如果不从前端反查,光看数据库是猜不出来的。

3.2 Service 层业务规则提取:条件判断里的隐藏需求

Service 层是业务规则最密集的地方。我通常的做法是,从 Controller 入口开始,顺着调用链往下读,把每个 if-else、switch-case 都记下来,因为这些条件判断就是业务规则。

举个例子,那套商城的订单创建逻辑里,有一段代码是这样的:先检查用户是否被禁用,再检查商品是否下架,然后检查库存是否充足,接着计算优惠券抵扣,最后判断是否需要拆单。这一连串判断,在代码里可能分散在五六个方法里,但从前端用户视角看,就是“点击下单按钮后发生的事”。逆向 PRD 要做的,就是把这些分散的逻辑重新组织成一条完整的业务规则描述。

我习惯用一张表格来记录这类规则:

规则编号触发条件业务动作代码位置备注
R001用户状态为禁用拒绝下单UserService.checkStatus返回错误码 1001
R002商品状态为下架拒绝下单ProductService.checkOnSale返回错误码 2001
R003库存不足拒绝下单StockService.checkStock返回错误码 3001
R004优惠券已过期忽略优惠券CouponService.calc不报错,直接按原价

这种表格在迁移时特别有用,因为新系统开发时可以逐条对照实现,测试时也可以逐条验证。

3.3 接口契约梳理:给第三方用的接口要单独标记

那套系统有一部分接口是给外部合作伙伴调用的,比如商户系统对接、物流回调等。这些接口和内部接口混在一起,如果不仔细区分,迁移时很容易漏掉或者改错。

我的做法是在梳理接口时,给每个接口打上标签:内部接口、外部接口、回调接口。外部接口通常有签名验证、IP 白名单、频率限制等额外逻辑,这些在迁移时必须保留。回调接口则要特别注意幂等性处理,因为外部系统可能会重复调用。

注意:有些接口虽然路径看起来是内部的,但实际上被前端跨域调用了,这种也要标记出来。判断方法是看 Controller 上有没有@CrossOrigin注解,或者看前端代码里的请求地址。

4. 前端交互与状态流转的还原方法

4.1 Vue 路由与页面结构还原

前端是用户直接接触的部分,也是需求最直观的体现。那套系统用的是 Vue 2 加 Element UI,路由配置在router/index.js里。我先把路由表导出来,整理成页面清单,然后逐个页面去看组件代码。

看 Vue 组件的时候,重点关注几个东西:data里定义了哪些字段(对应页面上的表单项和展示项)、methods里有哪些方法(对应页面上的操作)、watch里监听了什么(对应字段联动逻辑)、computed里计算了什么(对应派生数据)。把这些串起来,就是一个页面的完整功能描述。

比如商品编辑页面,data里有商品名称、价格、库存、分类、图片列表等字段,methods里有保存、上架、下架、删除等操作,watch里监听了分类变化去加载对应的属性模板。这些信息组合起来,就能写出“商品编辑页面支持修改商品基本信息、控制上下架状态、根据分类动态展示扩展属性”这样的需求描述。

4.2 状态流转图:订单从创建到完成的全链路

状态流转是迁移中最容易出问题的部分。因为状态机往往分散在多个 Service 方法里,而且可能还有定时任务在后台修改状态。那套商城的订单状态有:待支付、已支付、待发货、已发货、已完成、已取消、退款中、已退款。这些状态之间的流转条件,我花了整整两天才理清楚。

理清之后,我用 PlantUML 画了一张状态图,标注了每个流转的触发条件和对应的代码位置。这张图后来成了迁移 PRD 里最有价值的部分,因为新系统开发时,订单模块的负责人直接照着这张图实现,省了大量沟通成本。

除了订单,还有退款单、优惠券、商户入驻申请等也有状态流转。我的建议是,凡是带status字段的表,都要画一张状态图,不要嫌麻烦。

4.3 定时任务与异步逻辑的排查

这是最容易被遗漏的部分。老系统里往往有一些定时任务,比如每天凌晨自动关闭超时未支付的订单、自动确认收货、自动结算商户货款等。这些逻辑不在用户操作路径上,光看接口和页面是发现不了的。

排查方法是在代码里全局搜索@Scheduled注解,或者搜索quartz、xxl-job等定时任务框架的关键字。找到之后,逐个分析任务的执行逻辑、执行频率、依赖条件。那套系统里有七个定时任务,其中三个和订单相关,两个和结算相关,还有两个是数据同步任务。这些在迁移 PRD 里都必须明确列出,否则新系统上线后会出现订单状态不流转、货款不结算等严重问题。

异步逻辑也是类似,搜索@Async、MQ、消息队列等关键字,把异步处理的业务场景找出来。比如订单创建后发送通知、支付成功后更新库存等,这些在迁移时都要考虑。

5. 实操过程:从零到一份完整 PRD 的完整记录

5.1 第一阶段:环境搭建与代码通读

我拿到代码后的第一周,主要做三件事。第一,把项目跑起来。那套系统依赖 MySQL、Redis、RabbitMQ,我用了半天时间配好本地环境,确保能正常启动和访问。第二,通读项目结构,把 Maven 模块划分、包结构、配置文件都看一遍,心里有个大概的模块地图。第三,导出数据库 DDL 和前端路由表,作为后续梳理的基础材料。

这个阶段不要急着写文档,先把整体感觉建立起来。我通常会画一张粗略的模块关系图,标注哪些模块之间有调用关系,哪些模块是独立的。

5.2 第二阶段:逐模块深挖与规则记录

第二周到第三周,我按模块逐个深挖。顺序是先核心后边缘:用户模块、商品模块、订单模块、支付模块、商户模块、营销模块、物流模块。每个模块的梳理流程是固定的:先看数据库表,再看 Controller 接口,然后追 Service 逻辑,最后对照前端页面验证。

每梳理完一个模块,我就写一份模块级的逆向文档,包括功能清单、业务规则表、状态流转图、接口列表。这些模块文档最后汇总成完整的迁移 PRD。

这个阶段最耗时间的是订单模块,因为涉及拆单、优惠分摊、退款计算等复杂逻辑。我光读订单相关的代码就花了三天,画了四张状态图,记录了三十多条业务规则。

5.3 第三阶段:交叉验证与遗漏排查

第四周主要是查漏补缺。我把前端所有页面都点了一遍,对照后端接口列表,看有没有页面调用了但接口列表里没有的接口,或者接口列表里有但前端没用的接口。前者说明遗漏了功能,后者可能是废弃接口或者给外部用的接口。

同时,我把定时任务、消息消费、缓存更新这些隐性逻辑再排查一遍,确保没有遗漏。最后,我找了一位还在职的老员工,花了两个小时对着文档过了一遍,他补充了几个我漏掉的业务规则,比如某个优惠券在特定节日会自动翻倍,这个逻辑藏在配置表里,光看代码不容易发现。

5.4 第四阶段:文档整理与评审

最后一周把前面所有材料整理成正式 PRD,按之前设计的五部分结构组织。整理过程中,我把所有业务规则都编了号,方便后续追溯。文档完成后,组织了一次评审会,邀请开发、测试、产品三方参加,逐模块确认。评审会上又发现了几处理解偏差,修正后定稿。

整个流程下来,实际耗时四周多一点,产出了一份约八十页的迁移 PRD,包含一百多张表结构说明、两百多个接口定义、四十多条业务规则、八张状态流转图。

6. 常见问题与避坑经验实录

6.1 代码里的“僵尸逻辑”怎么识别

老系统里经常有一些代码,看起来是业务逻辑,但实际上已经废弃了。比如某个接口还在,但前端早就不调用了;某个配置项还在,但实际不会生效。这些“僵尸逻辑”如果写进 PRD,会误导新系统开发。

识别方法有几个:看代码提交记录,如果某个方法最近两年都没改过,而且没有测试覆盖,大概率是废弃的;看前端调用,如果全局搜索接口路径在前端代码里找不到,可能是废弃的;看数据库数据,如果某个状态值在数据表里从来没有出现过,对应的逻辑可能是废弃的。

我遇到过一个例子:订单表里有个is_urgent字段,代码里有加急处理的逻辑,但查了数据库发现这个字段全是 0,前端也没有设置入口,确认是废弃功能,没有写入 PRD。

6.2 隐式业务规则:配置表里的秘密

有些业务规则不在代码里,而在配置表里。比如那套系统有一张sys_config表,里面存了各种参数:订单超时时间、优惠券最大抵扣比例、商户结算周期等。这些参数在代码里是读取配置表的值,而不是硬编码,所以光看代码只能看到“读取配置”,看不到具体数值。

迁移时,这些配置值必须一并迁移,否则新系统行为会和老系统不一致。我的做法是把配置表里所有和业务相关的配置项都列出来,标注含义、当前值、影响范围。

6.3 迁移 PRD 的验收标准

一份迁移 PRD 写得好不好,有一个简单的验收标准:拿给一个没接触过老系统的开发,他能不能照着这份文档把新系统开发出来,而且行为和老系统一致。如果能,说明文档合格;如果不能,说明还有遗漏。

我通常会在文档完成后,找一个同事做“盲测”,让他只看文档不看代码,描述某个功能应该怎么实现,然后对照代码看是否一致。这个方法很有效,能发现很多自己没意识到的表述不清或逻辑缺失。

6.4 常见问题速查表

问题现象可能原因排查方法解决思路
接口列表和前端调用对不上存在废弃接口或外部接口全局搜索接口路径标记接口类型,区分处理
状态流转理不清状态修改分散在多个地方搜索所有修改 status 的代码画状态图,标注触发条件
业务规则遗漏规则藏在配置表或定时任务里检查配置表和 @Scheduled补充配置项清单和任务清单
字段含义不明命名不规范或注释缺失查前端选项列表或问老员工结合前后端推断,标注确认状态
迁移后行为不一致隐式规则未迁移对比新旧系统测试结果补充隐式规则到 PRD

提示:逆向 PRD 不是一次性的工作,建议在迁移开发过程中持续维护,发现遗漏随时补充。我通常会在文档里留一个“待确认”章节,把不确定的点记下来,后续逐个确认。

7. 迁移 PRD 的后续维护与扩展思路

文档写完不是终点。新系统开发过程中,开发人员会不断提出疑问,这些疑问往往指向文档的薄弱环节。我的做法是,每次答疑后都把答案补充到文档里,让文档保持“活”的状态。

另外,迁移完成后,这份逆向 PRD 还有别的用途。比如新同事入职时,可以用它快速了解老系统的业务逻辑;比如做系统重构时,可以用它评估影响范围;比如做数据迁移时,可以用它核对字段映射关系。

如果后续还要做国产化迁移,比如从 MySQL 换到国产数据库、从 Spring Boot 2.x 升级到 3.x,这份 PRD 同样是基础材料。因为国产化迁移最大的风险不是技术本身,而是业务逻辑在迁移过程中丢失或变形。有了这份文档,至少业务层面是有保障的。

我个人在实际操作中的体会是,逆向梳理这件事,技术难度不高,但耐心和细致程度要求很高。不要指望有什么工具能一键生成 PRD,工具只能帮你提取接口和表结构,真正的业务规则还是要靠人一行行读代码、一个个点页面、一条条问老员工。这个过程很枯燥,但做完之后,你对系统的理解会超过任何一个还在职的人。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/4 7:03:11

偏振光栅衍射效率测量:斜入射条件下的公式修正与实操指南

做光栅衍射实验的人都知道,正入射条件只是理想化模型,真正装到系统里,入射角几乎不可能正好是零。这个项目之所以有意思,在于把"入射角不为零"和"偏振光栅"这两个变量叠在一起之后,原本在普通光栅…

作者头像 李华
网站建设 2026/10/4 7:03:02

滑动t检验的Matlab实现:气候水文突变检测与判读指南

做气候或水文序列突变检测的,十有八九开口就是Mann-Kendall检验。MK确实好用,但真到要判定具体哪一年发生突变的时候,它的UF/UB曲线经常给你画出一大片交叉区,反而让人犯难。相比之下,滑动t检验的思路朴素得多——把序…

作者头像 李华
网站建设 2026/10/4 6:59:55

ANSYS Workbench高斯热源仿真实战指南

1. 项目概述:为什么在Workbench里做增材制造高斯热源仿真不是“选做题”,而是“必答题”我在金属3D打印工艺开发组干了八年,从最早的SLM设备调参员一路做到现在带三个仿真小组的负责人。每天早上第一件事不是看生产报表,而是打开A…

作者头像 李华
网站建设 2026/10/4 6:57:47

Agent长对话失忆怎么办?Context Editing与Compaction实战

1. 从“第20轮失忆”说起:Agent上下文管理的真实痛点如果你正在做 Agent 开发,大概率遇到过这个场景:前几轮对话里,Agent 还能准确引用用户十分钟前提到的偏好、约束和中间结论,聊到第 15 到 20 轮之后,它开…

作者头像 李华