返回首页

老系统现代化里,Copilot 先整理证据

先把基线、改动面和测试边界固定住,模型才有资格帮忙

老系统现代化里,Copilot 先整理证据

我第一次把一个 1.5 时代的 Java 项目拉到现代机器上,最先冒出来的不是代码问题,而是证据问题。build 能不能重现,测试输出是不是同一份,失败点到底来自 JVM、镜像还是源码,这些东西比“开始重构”更早决定后面怎么走。老系统现代化最怕的,不是改动慢,而是改动以后根本说不清发生了什么。

先把现场固定住,后面的动作才有意义。那一步里最值钱的不是 IDE 里的补全,而是一个能重复跑的盒子:老 JDK、老构建工具、旧入口、旧测试命令,全都锁进 Docker 里。下面这类命令不漂亮,但很管用:

docker run --rm -v "$PWD":/src -w /src legacy-jdk8 \
  sh -lc './gradlew test 2>&1 | tee logs/baseline.log'

这条命令的作用只有一个:把“今天的失败”固定成可回放的证据。没有它,后面的每一次成功都可能只是环境碰巧宽容了一次。Copilot 在这里的角色也很明确,不是替代判断,而是帮忙整理痕迹:长日志里重复出现的报错、构建脚本里彼此呼应的路径、旧测试里那几个一再出现的入口,都可以先让它做一次粗筛。筛出来的不是结论,是一张可下手的地图。

真正动刀的时候,改动面必须收得很窄。老项目最容易翻车的做法,是一口气改包名、改构建、改入口、改测试,最后连是哪一步把系统弄坏的都分不出来。更稳的做法,是先抓住一个最小的缝:例如把旧入口外面包一层适配器,先让新工具链能站在旧世界外面看清结构,再慢慢往里挪。Copilot 很适合处理这类机械活:补 import、搬配置、提取重复片段、生成临时测试骨架,这些事情让模型来做,效率确实高;但这个缝该不该切、切完保住什么行为,还是得人来定。

测试这边也容易被表象骗到。旧测试通过,不代表现代化已经安全,只能说明某些历史行为暂时还没被打散。很多老项目的测试更像行为快照,不像业务语义说明书。绿色只是绿色,不能直接被解释成“理解了系统”。改造时最重要的动作之一,是给每个小切口补上新的、窄一点的测试边界,让测试逐步从“历史遗留”变成“当前约束”。Copilot 可以帮着把旧断言拆细、把样板补齐、把重复的测试壳子铺开,但测试该守住什么语义,不能让模型自己替系统做决定。

考古式现代化里,最可靠的分工其实很朴素:环境和日志负责把事实钉住,Copilot 负责搬砖和翻译,人负责决定哪些历史要保留,哪些历史该切掉。模型一旦被安排去解释系统的过去,它往往会把猜测说得比证据更顺;把它放回证据管理和机械整理的位置,反而更像一个真正有用的助手。