![]()
去年TeamCity团队做了个实验:让AI把旧数据库API迁移到新版本。代码能跑,测试全过,资深工程师Pavel Sher却直接打回——新API套着旧架构,像给电动车装了个蒸汽机的壳子。
这不是个例。AI写代码的能力已经够用了,真正卡脖子的是"代码品味"。
频率≠正确:AI的"从众陷阱"
AI agent(智能体)的工作原理听起来很合理:扫描代码库,找到重复100次的模式,照着写。问题是,那100次重复的可能正是团队想淘汰的 legacy code(遗留代码)。
Pavel Sher打了个比方:agent看到满地的旧鞋印,以为那是路,其实大家只是在绕开前面的坑。
TeamCity作为2005年诞生的老牌CI/CD工具,代码库里埋着近20年的技术债。实验里那个迁移任务,新API和旧API不是简单替换关系,需要重新设计数据流、错误处理、边界情况处理。AI交上来的作业,API调用是新了,周围的骨架全是老的——它把"保持一致"执行得太彻底了。
核心矛盾在于:AI能判断"能不能跑",但判断不了"该不该这么写"。
第一个补丁:用"先例"替代"频率"
团队的第一个改进很朴素。不再让AI自己翻代码库找规律,而是直接喂给它已经通过评审的迁移案例。
指令变成:"Class A是这么迁的,Class B照做。"
效果立竿见影。AI开始模仿被认可的做法,而不是被重复的做法。Pavel注意到,agent生成的代码结构开始贴近团队真正想要的方向,legacy patterns(遗留模式)的残留明显减少。
但这个方案有天花板。先例再多,也覆盖不了所有场景。遇到没见过的边界情况,AI还是会退回到"看周围怎么写"的安全模式。
团队需要让AI理解的不是"怎么做",而是"为什么这么做"。
![]()
第二个补丁:把"设计意图"写进上下文
突破口来自一次复盘。Pavel在评审时发现,自己判断代码好坏的依据,很大程度上是"这个项目之前做过什么决定"。
那些决定很少写在文档里。它们散落在过去的pull request讨论、代码评审注释、架构决策记录(ADR)里。新人靠耳濡目染慢慢吸收,AI没这个条件。
团队开始实验:把这些分散的设计意图整理成结构化上下文,随任务一起喂给AI。
具体做法分三层。第一层是显式规则——命名规范、API白名单、禁止使用的模式,直接写进系统提示。第二层是迁移先例,像之前那样打包成案例库。第三层最关键:提炼"我们为什么选这个方案"的简要说明,让AI理解约束背后的逻辑。
举个例子。旧API的错误处理是返回null,新API改为抛异常。AI如果只模仿先例,会在新场景下机械复制;但如果同时告诉它"我们正从静默失败转向快速失败,方便调试",agent遇到未覆盖的情况时,能做出方向一致的判断。
Pavel的观察是:AI开始表现出类似"代码嗅觉"的东西——说不清为什么,但知道这里该改。
还没解决的:谁来维护"意图"?
这套方法在TeamCity的实验里跑通了,但团队很清楚代价。设计意图的整理是人工活,需要熟悉项目历史的人持续投入。 precedents(先例库)会膨胀,需要定期清理过时的。规则写多了,AI可能变得过于保守,错过合理的创新。
更深层的问题是:当AI开始依赖这些上下文,代码库本身的"自解释性"会不会变差?新人不再通过读代码学规矩,而是直接问AI,那些未成文的团队智慧会不会断层?
JetBrains没有给出标准答案。他们开源了实验框架,把问题抛给了更广泛的开发者社区。
一个有趣的细节是,Pavel现在评审AI生成的代码时,会特意检查agent有没有"过度学习"某个先例——就像老师看学生是不是在死记硬背。最近一次,他发现一个agent在三个不同场景下用了同一套异常处理模式,其中两个合适,一个明显过度设计。他在评审注释里写:"这里不需要这么重,参考#2847的讨论。"
那条注释会被收录进下一个版本的上下文。AI的"品味"就是这样,一行一行地,从人的判断里长出来。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.