先说背景。我现在负责的模块里有个配置解析的函数,是我转岗第二个月写的。当时刚独立接需求,特别想证明自己能干活,就用了大概三百行把配置加载、默认值填充、类型转换全塞进了一个函数里,嵌套了四五层 if-else。能跑,上线也没出过事——但每次打开那个文件都想抽自己(我旁边同事说我有次看着屏幕叹气叹了半分钟,我说是在想中午吃什么,其实就是在看那个函数)。
上个月组里做技术债清理,我把它拎出来了。按我做测试的习惯,先写用例把行为全锁住——十几个用例,从正常参数到各种边界值,跑了全绿,才开始动它。然后我把它整个贴给 AI,外加一句话:这是我最烂的代码,帮我看看到底哪里烂。其实本意是让它帮我重写,但我有点心虚,就说先诊断。
AI 挺给面子,列了四条。前三名我大概猜到,内层那个状态机不需要、类型转换散落各处之类的。第四条让我愣住:它说这个函数对空对象的处理是「静默通过」,所有字段都是 undefined,调用方拿到的配置对象跟期望的不一致,但是不报错。我看了半天,它没说错。而且我翻 git 记录,这个 bug 从我写的第一版就存在了,大半年前的事,一直没人踩到,纯属运气好,因为业务上从来没人传过空对象进来。我理解的是,这种 bug 比直接报错的更难发现,对,以我做了八年测试的经验说这个应该没人反对。
接下来两天就是拉锯战。我让它改一版,我跑一遍用例,红了就贴回去让它修,黑了我再看新代码有没有引入我没锁住的行为。中间有个翻车瞬间:AI 为了把那个静默通过改成抛出异常,把函数出口从八个改成两个,逻辑是干净了,但有两条调用路径需要上层接住这个异常,我当时没注意到,导致上线后同事反馈有个页面白屏了(其实就是上个月那两周,我周报里写"处理了一个异常流转问题",说的就是它)。我连夜补了个兜底——把异常接住,记日志,然后按旧逻辑返回,等于留了个后门给上游迁移。这件事告诉我,AI 重构得再好,我也得把它的改动当成别人的代码来审,不能因为它生成的就放松。
但话说回来,挺爽的。最后函数从三百行变成一百出头,嵌套也压平了,每个默认值都是一个独立小函数。我拿原来的用例跑了一遍,全绿,然后再补了三个异常分支的用例,也都过。同事看我说"你这速度可以啊",我说这主要是 AI 写的。他说那你也得看得懂啊。我没接话,但心里想的是:我知道它为什么这么改,因为我写了那十几条用例,是它们在兜底,AI 只是替我把想法写出来。大概是这样。
还有个小片段:它输出新版的时候,我盯着那个空对象处理的分支看了很久,有点唏嘘,这半年来它一直是个假稳定。所以最烂的代码其实不是写得烂,是我一直没发现它烂。
先这样吧,后面那几个类似的函数我准备如法炮制,想到再补。