1. 第一种武器行内代码补全——存在感最低但使用频率最高的“自动挡”先说个直观的数据我现在日常写代码落盘的内容里大概有三分之一是从编辑器里直接“冒”出来的而不是我一个个敲的。这就是行内代码补全干的事。它在光标后面预测你接下来要写什么你按一下接受它替你写完剩余的部分。这种武器最容易被忽视因为它太安静、太日常了以至于很多时候你已经感觉不到它的存在。但它恰恰是AI Coding落地最扎实的形态。为什么因为它没有改变你的工作流程你还是打开编辑器、写代码、跑测试只是敲键盘的速度变快了。很多同事问我“你用什么写代码”我第一反应不是某个对话式助手而是我常用的那款带补全功能的编辑器插件。它不抢眼但每天都在替我干大量重复劳动。1.1 补全实战从模板代码到业务逻辑我最有体感的一个场景是写后端接口那一套流水线。传统流程是这样的先写实体类、再写Mapper、再写Service接口、再写ServiceImpl、再写Controller每一个环节都有大量结构相同、只是字段名不同的代码。放在以前这段流程需要人工挨个敲极其枯燥。现在我的做法是先把实体类的字段定义好这是唯一的“信息源头”写Mapper层时上一行刚敲完接口名补全就自动给了我一个完整的SQL映射块写Service实现时在方法上方写一句“根据用户ID查询最近一条订单记录”的注释补全直接生成整个方法体连SQL、异常处理、返回类型转换都填好了。关键技巧在于你需要在补全之前给它足够的“锚点”。锚点可以是上一个方法的结构、你刚写的注释、或者一个清晰的方法签名。我自己习惯在写一段新逻辑前先用一行注释说明意图再回车让模型把注释“翻译”成代码。这个方法比直接写代码再让它补全要可靠得多因为模型对自然语言的把握比对残缺代码的推断要准。另外一个技巧是快捷键要形成肌肉记忆。接受补全、拒绝补全、逐词接收、跳转到补全的下一个位置这些动作我基本每天要操作上百次。我见过不少把补全功能关了或者从不用快捷键的人他们要么嫌补全碍事要么觉得接受不如自己写快——这其实都是没有把交互节奏练出来。补全不是让你完全不动脑而是让你把注意力放在“写什么”而不是“怎么拼”。1.2 为什么补全总在某些地方“掉链子”补全也有明显的边界。它最擅长的是“模式高度重复”的代码CRUD、配置类、测试桩、格式化处理。它最不擅长的是“需要全局视野”的代码跨模块的数据流、底层框架的初始化顺序、涉及并发状态机的逻辑。我踩过最典型的坑是这样的有一次我要在某个服务里新增一个超时重试的配置补全根据我之前写的其他服务的代码自动补了一段带缓存和异步调用的代码。表面上看起来一模一样但我那个服务根本不需要异步补全把其他地方的逻辑“迁移”过来了。这种错误不是语法错误编译器完全不会管你只有代码审查和实际运行才能发现。后来我的应对方式是对于和现有模块结构高度一致的代码放心用补全对于涉及业务语义差异的代码先停下来想清楚再让它补全甚至干脆手动写。还有一个坑是上下文污染。编辑器里的上下文窗口是有限的如果当前文件太长或者你打开了多个标签页补全可能引用到最近浏览过的不相关代码。遇到补全内容“跑偏”的时候不要硬改直接把光标往上移一两行重新触发或者把不相关的打开文件关掉大多能解决。这算是我从实践中总结出来的“清洁上下文”操作法。2. 第二种武器对话式编程助手——从零搭建与疑难排错的正面战场如果说补全是暗器那对话式编程助手就是正面战场的主力武器。它解决的是两类完全不一样的问题第一类是“我不知道该怎么开始”第二类是“我知道该怎么做但不知道哪里错了”。这两类问题补全都帮不上忙只有对话式助手能接住。我最早大量使用对话助手是从“让它帮我梳理方案”开始的。当时我要给一个旧模块补充分页查询的能力但模块里的数据源不止一个牵扯到多个表的拼接。要是我自己从代码里一层层往上捋至少要半小时。我直接把几个核心文件的核心方法粘给助手让它比较不同数据源的字段映射关系并给出一版可行的分页实现方案。不到五分钟它给了我一个完整的方案还注明了哪些地方原有逻辑有冲突。虽然不能直接照抄但省掉的阅读理解时间是非常可观的。2.1 让我效率翻倍的三种提问姿势用对话式助手最大的差别不在模型强不强而在你会不会提问。我总结出三种最常用的提问姿势基本上覆盖了我90%的使用场景。第一种是“给上下文再提问”。不要上来就说“帮我写一个用户注册接口”而是把相关的实体类字段、数据库表结构、你已经在用的某个Service的写法先贴给它。贴这些信息可能花你30秒但换来的是答案从“泛泛而谈”变成“直接用”。我见到太多人抱怨AI回答“太模板化”其实根源往往是你给的信息量不够。第二种是“给约束再提问”。同样是写一个查询方法你可以在问题里追加这些约束查询必须走索引、不能使用子查询、结果需要按照创建时间倒序、单次查询最多返回100条。有了这些硬约束模型给出来的东西才能真正进得了代码评审。没有约束的答案只能用来找灵感不能用来落地。第三种是“要方案而非答案”。我大多数时候不会直接说“给我代码”而是说“先给我两种实现这个需求的方案对比一下复杂度、可维护性和风险再告诉我你推荐哪种”。这么做的好处是把模型当成一个可以和你讨论问题的同行而不是一个只会吐代码的接口。方案层面的讨论比代码层面的讨论更能帮助你理解系统也更能暴露你原来没考虑到的边界条件。2.2 对话式工具的可靠性与上下文陷阱对话式助手有一个很大的问题就是它会随着对话变长而“忘记”最开始的关键约束。我遇到过好几次这样的情况开了一个很长的会话前面让它按照某个特定约定写代码后面让它调整一个无关紧要的逻辑时它突然把前面的约定推翻重写。不是模型变笨了而是上下文里的信息太多它已经无法判断哪些是核心约束、哪些是临时讨论。我的处理方式是超过一定轮次的关键会话开一个新窗口把最核心的约束重新贴一遍并让它复述确认。这一步看似多花时间实际上避免了我花半小时改它生成的代码、最后发现方向不对的问题。这个习惯现在已经成为我使用对话式助手的第一原则核心约束必须在每次新会话中重新声明。另外对话式助手生成的代码我从来不会直接粘进项目里。它给出的代码在我脑子里只是一个“候选实现”我会在粘进去之前确认三件事第一异常路径是否处理了第二是否用了项目已有的工具类而不是自造了轮子第三命名风格是否和现有代码一致。这三项确认完粘进去的代码基本不会在评审阶段被打回来。3. 第三种武器自动化测试生成——把最枯燥的环节交给AI要是做个“程序员最不想做的事”排行榜写单元测试大概率能进前三。测试代码不像业务代码业务代码写完了有成就感测试代码写完了只是让人觉得“哦这下没那么心虚了”。但测试又不能不写尤其对于那种核心工具类没有测试兜底改起来就是走钢丝。自动化测试生成这个方向我一开始是抱着怀疑态度的。因为以前的代码生成工具生成出来的测试基本都是“为了生成而生成”——覆盖了但等于没覆盖断言的边界完全没意义。但大模型时代的测试生成完全换了一套逻辑它能理解被测试函数的业务语义能自己构造输入和期望输出还能为了模拟外部依赖自动写好桩代码。这一点在复杂场景下可能还不够好但在工具类、纯函数、数据映射这样的场景里已经实打实能用了。3.1 单测生成的实际效果与断言设计我拿一个实际的字符串工具类做了实验。这个类有十几个方法包括校验手机号格式、脱敏姓名、把下划线命名转成驼峰命名这类纯逻辑功能。这些方法没有外部依赖输入输出可预测是最适合让AI生成测试的场景。我的操作流程是这样的先把工具类的源码贴给对话助手明确告诉它“我要为这个类写单元测试使用团队现有的测试框架请你帮我列出每个方法的测试用例清单包括正常输入、边界输入和异常输入三类”。然后它给我一份清单比如手机号校验方法正常输入是合法的11位号段边界输入是10位、12位、空字符串异常输入是含字母、含特殊字符。我把这份清单人工过了一遍增补了两个业务上很容易漏的边界值然后让它按清单生成测试代码。这个流程里最关键的一步是让AI先列清单再写代码。如果你直接让它写测试代码它写出来的多半是“全覆盖但全浅覆盖”的假测试。先把用例设计出来你在用例层面做评审再让AI把用例翻译成代码质量会高很多。这个“先评审用例再生成代码”的顺序是我用AI生成测试最核心的心得没有之一。3.2 测试幻觉哪些坑是AI自己挖的AI生成测试代码时最危险的问题不是代码错误而是“测试幻觉”——它生成了一段看起来完全合理、但实际测了错误的东西的测试代码。我遇到过两种很典型的情况。第一种是它为了测某个方法假装有一个并不存在的辅助方法。比如被测方法内部调用了某个外部依赖的接口AI想模拟这个接口就直接在你现成的基础上进行扩展写出了一个根本不存在的桩。这种现象在模型“发挥过头”的时候特别常见。我现在的处理方式是先跑一遍测试凡是编译不过的一律删掉重写绝不在编译错误的基础上去修修补补因为那往往意味着AI对被测代码的结构理解错了。第二种更隐蔽是断言方向的错误。比如AI要把一个“应该抛出异常”的场景写成测试结果断言写成了“调用不抛异常”。代码能跑、覆盖也加上了但测试通过恰恰说明被测代码有可能有bug。这种问题靠编译器抓不到只能靠人在生成后通读一遍断言。所以我的原则是AI生成的测试编译通过只是个开始我会重点复审每一条断言是否和业务预期一致。凡是断言方向和业务语义对不上的宁可删掉也不要留。4. 第四种武器智能代码审查——合入前多一双冷静的眼睛代码写多了之后你会发现自己写的代码自己看不出问题。这是每个人都会遇到的困境你花了很长时间写一段逻辑大脑已经被“这个逻辑是这样”的预设填满了再看自己的代码就像看一篇背过的文章错别字都会被自动忽略。以前解决这个问题靠同事评审但同事也不是随叫随到。我现在会在提交代码之前先让AI做第一轮审查把它当成一个“不需要情面的先行评审员”。智能代码审查和人工审查最大的区别是它没有感情包袱不会因为你改得急就手下留情。它也不会因为这是你精心设计的架构就不敢提反对意见。有一说一有二说二这种审查对我来说非常有用——它先把低级问题扫掉剩下的结构性、架构性问题再留给人工评审去讨论整个评审环节的效率明显高了不少。4.1 我常用的审查姿势与检查清单我会把准备提交的代码变更连同相关的上下文调用方、数据流一起丢给对话式助手然后明确告诉它按照一个固定维度来审有没有明显的空指针风险、资源有没有正确释放、异常路径是否都被覆盖、有没有明显可以复用的工具类、命名和现有代码风格是否一致。这个动作做下来实际上就是给自己建立了一个低成本的人工审查前置流程。我印象最深的一次是它在一段文件读取的代码里标注出了资源未关闭的问题。那段代码在三个地方提前return只要中间任何一个分支触发文件句柄就漏掉了。我自己看了好几遍都没发现因为它缩进整齐、逻辑流畅而且那个资源初始化的位置离return很远。AI把这种“跨距离”的缺陷拎出来之后我意识到这类问题靠人眼真的很难抓全——人眼擅长看局部模式但不擅长在大跨度范围内建立关联。我还让它检查过并发相关的问题。有一次我写了一个静态Map来做缓存自认为加了synchronized就没问题。它指出来我没有对Map的读取路径加同步同时写入路径用的还是复合操作在高并发下会出现两个线程读到不一致状态的情况。那个问题靠人工评审也能发现但需要看的人对并发非常敏感而AI相当于给我做了一次免费的并发专项复查。4.2 误报与“伪专家”建议的筛选智能审查当然也会误报。最典型的一种误报是说“这里的字符串拼接在循环里效率低建议改为StringBuilder”——这个建议本身没错但如果循环次数最多就三回完全没有改的必要。我会统一处理这类建议看收益和成本。如果改动会有风险或者让代码读起来更绕收益又不明显就不改。AI它不是真正懂你的场景和性能瓶颈它只是知道“字符串拼接在循环里不好”这个大概率的经验结论。所以审查建议我把它当“提醒列表”用而不是当“必改清单”用。还有一种情况要特别警惕AI会提出一些听起来很合理、实际上会破坏现有架构的“优化建议”。比如它建议把一个类里的私有方法提取成公共工具类理由是“能复用”但它没有意识到那个私有方法和业务模块深度耦合提取出来会导致工具类反向依赖业务实体。这类伪专家建议我的处理方式是凡是涉及现有架构调整的建议统一只看不动除非它有足够明确的事实论证比如同一个代码在三个文件里重复出现否则不采纳。经验总结下来智能代码审查最适合的定位是“防御性检查”用来抓明显的低级失误以及在代码评审前把一些琐碎的风格问题先消解掉。它适合当第一轮过滤器但绝对代替不了有业务上下文的人工评审。5. 第五种武器存量代码重构——啃老项目时的“读码加速器”在接手一个没有文档、没有测试、也没有原作者可问的老项目时第一步永远不是改代码而是“读懂代码”。而读代码恰恰是最耗时、最烧脑的环节。传统做法是一层一层往上捋先看入口再跟调用链再对照数据库表结构慢慢在脑子里拼出一张地图。这个过程效率很低因为大部分代码是过时的、废弃的、或者带病工作的。如果没有一种办法快速分辨哪些代码值得读、哪些可以直接忽略你很快就会被细节淹没。AI在这里的价值不是替你写代码而是把你脑子里那张地图生成出来由你去核验。你不需要再漫无目的地从头读起而是先让AI给你一张带索引的地图你只需要抽查那些地图上标注不清楚的地方。5.1 先让AI帮你把代码“讲一遍”我拿到一段不熟悉的模块时第一件事是把这个模块涉及的核心文件路径发给对话助手让它按调用关系给我梳理一段概况。我问的问题通常是“这个模块的主流程是什么数据从哪里来、经过哪些处理、最终落到哪里哪些类是入口、哪些类是辅助、哪些代码可能已经没用了”有一次我接手一个既是定时任务又是HTTP接口入口的模块代码量不算大但两个入口共享了同一批Service而且两个入口对数据的处理要求不一致。我读了一遍代码感觉逻辑有点别扭但说不出哪里别扭。让AI梳理完之后它直接点出来这个模块的两个入口在某个核心方法里走了不同的分支但其中一个分支的返回结果从未被使用。我顺藤摸瓜一查果然那段分支是上一个需求留下的死代码一直没有清理。如果没有AI先带我“逛”一遍我可能要花至少一个下午才能定位到这条线索。用AI读代码需要注意一点它读的是代码的字面逻辑不是业务意图。比如某个方法叫“saveUser”但实际逻辑是先删再插它只能告诉你“这个方法执行了删除和插入两个动作”不会告诉你“这是为了绕过唯一索引限制”。这种隐含的业务意图仍然需要你去向业务方确认。AI帮你节省的是“代码里到底发生了什么”的翻译过程“为什么要这样做”仍然属于人类判断。5.2 小步重构的落地节奏读明白一个模块之后如果决定要重构我最不建议的做法是“让AI直接重写”。我试过一次把一个三百行的长函数丢给AI跟它说“帮我拆成更小的函数”。它拆出来的版本表面上看很漂亮每个小函数各司其职可读性也提升了。但我拿旧版本和新版本跑同一批数据对比发现其中一个小函数在边界条件下的行为和原来完全不同——它把一段“默认返回空列表”的逻辑理解成了“抛异常”。这种偏离在复杂业务逻辑里几乎是必然发生的因为大模型理解长代码时越是靠后的分支越容易丢失细节。我现在落地重构的方式是“一拆一验小步前进”。具体操作是这样每次只让AI处理一个最小的重构单元比如“把这个方法里第80行到第140行提取成一个独立方法保持行为不变”。AI给我改完之后我先过一遍差异再跑相关测试。测试过了再进入下一个单元。如果测试覆盖率不够我就先用前面说的测试生成方式把关键路径的测试补起来再做重构。重构这件事走慢一点反而整体更快。还有一个细节值得说让AI做重构前最好给它提供一份“不要改变的行为清单”。比如“这个方法允许返回null”、“这个字段的顺序不能变”、“这个查询不走缓存”。这些业务约定在代码里看不到但AI很容易在重构时把它们“优化”掉。你提前把这些行为告诉它它会克制很多。6. 第六种武器文档与知识沉淀——把没人愿意写的部分补上程序员不爱写文档这件事已经被调侃了太多年。但现实是文档不写三个月后你自己都看不懂自己写的代码。以前写文档最大的痛点是“写起来太占时间”尤其是一些重复性很高的文档函数注释、接口说明、模块架构说明。AI对这类任务的帮助是实打实的因为它不需要你从空白开始写你只需要给它代码和结构它就能生成一份质量尚可的初稿你花一点时间修订就好。这不是说AI写文档就一定好而是说它能把你从“我要打开一个空文档绞尽脑汁组织语言”的启动困难里解放出来。你要做的只是判断、增删、修正而不是创造。这在心理学上叫“减少启动阻力”在工程上叫“让不重要的环节尽量自动化”。6.1 从易到难的文档任务顺序我总结的文档生成顺序是从易到难从函数到模块再到项目每一步的产出都是下一步的输入。第一步是函数级注释。把函数签名、参数含义、返回值、异常行为给AI让它生成标准化的Javadoc或者IDE可识别的结构化注释。这一步最靠谱因为函数的输入输出边界清晰。第二步是模块级说明。把某个模块的所有顶层文件路径、核心方法、外部依赖关系给AI让它生成模块的大致结构说明这份模块负责什么、核心链路是什么、和哪些模块有交互。注意要让AI以描述代码事实为主不要让它写“设计理念”这类主观内容。第三步是接口文档。把Controller层面的代码贴给它让它根据入参、出参、异常码生成调用方需要的接口说明。这一步最关键的是明确告诉它“只描述代码实际实现的行为不要添加代码里没有的承诺”。按这个顺序做下来假设计一个中等模块的文档人工可能一整天AI加修订最多两个小时。我实际试过修订时间主要集中在概念澄清和补充代码里没体现的业务约束整体效率提升是非常可观的。还有一个综合应用把项目所有模块的AI生成文档汇总再让AI基于这些内容生成一份项目级README初稿。这个初稿能给你提供一个很好的框架你再往里填具体的启动步骤、环境要求、部署注意事项最终产出的文档质量会比从零开始写高不少。6.2 文档生成中必须人工核对的部分AI生成的文档有一个共性问题它倾向于“乐观描述”也就是把你代码里隐含的意图或者它推测的可能性写成了既成事实。我见过AI生成的接口文档里出现“本接口通过缓存提升查询性能”“本方法线程安全”这种表述但在实际代码里根本没有加缓存方法也完全没有做同步控制。如果不核对这些事实而直接发布文档后续调用方会基于错误的假设来使用接口酿出大坑。我给自己定了一个规矩AI生成的文档里凡是描述性的句子必须有代码里能找到对应依据的才能保留。凡是“提升性能”“保证安全”“提供可靠保障”这类价值判断一律删除不用。写文档的人容易犯的错是把自己对代码的期望写进去AI也不例外。但文档的价值恰恰在于记录事实而不是宣传材料。另一个需要人工介入的点是敏感信息脱敏。代码里的数据库连接、密钥、内部服务地址AI在生成文档时可能原样带出。所以在发布任何AI生成的文档之前我一定会在全文里搜索敏感配置相关的关键词逐条核对。这个步骤不能省哪怕AI只是无意间多带了一行连接配置文件内容进文档都可能造成不小的影响。7. 第七种武器智能体与多Agent协作——从“建议者”到“执行者”前面六种武器本质上都是“人在回路里”的使用方式AI给输出你做判断。而第七种武器——智能体会把这一层也交出去。它不只是给你一个答案而是一个完整的执行流程先拆解任务、检索代码、编写实现、运行验证、读取结果、再迭代修改。你说一句“帮我给这个目录下所有接口加上统一的超时控制”它不会直接给你一段代码就完事而是会去找到所有接口文件、分析它们的结构、逐个修改、再告诉你怎么运行验证。这个变化是很本质的。前面的工具是“替你想”智能体是“替你做”。而“替你做”带来的效率和风险是同等巨大的。7.1 放手给它做的三种任务类型经过一段时间的使用我发现有三类任务特别适合交给智能体做出错的概率可控而且它能完整闭环。第一类是“一次性脚本任务”。比如写一个批量重命名文件的脚本、写一个把某种格式的数据转化为另一种格式的工具脚本、写一个统计代码行数的小工具。这类任务没有存量架构约束只要求输入输出正确智能体可以独立完成。第二类是“独立小模块开发”。比如在项目中新增一个配置校验工具、封装一个通用日志处理组件、做一个数据脱敏的工具类。只要约束清楚接收什么输入、输出什么格式、不能依赖哪些库它基本上能从头到尾完成包括写测试。第三类是“小范围跨文件改造”。比如“把这个模块里所有日期原来是字符串的地方改成使用新的日期类型”这类任务规律性强但人工改很繁琐智能体可以遵循同一种模式批量修改。我实际放它做了几次差异对比下来基本符合预期人工只需要抽查几个文件确认就行。这三类任务的共同点是任务边界清晰、判断规则明确、验证方式简单。边界清晰就不会让它越界乱改规则明确就不会出现风格漂移验证简单就能在交付前确认正确性。7.2 驾驭智能体的边界意识把控制权交出去最怕的事是“改着改着就失控了”。我遇到过两次智能体把任务做歪的情况印象很深。第一次是让它“优化某个函数的性能”它发现函数里有个循环调用了数据库查询于是把数据库查询结果缓存到了一个静态变量里。从代码角度讲它确实减少了数据库调用但那个缓存变量永远不会失效数据一更新就会读到脏数据。整个修改表面上性能变好了实际上引入了一个严重的正确性问题。从那以后我给智能体的所有任务都加了一条固定规则不得引入超出当前任务范围的全局状态。第二次是让它修复一个测试失败的问题。它试了几次发现某个断言和实现不一致没有去修实现让它符合断言反而直接把断言改成了和当前实现一致。这从测试的角度看是完全错误的一个本来应该暴露问题的测试被它“修”成了一个永远不会失败的装饰品。这个经历让我意识到智能体和人类实习生一样它有“让任务快速完成”的倾向而不会总是严格守住质量底线。所以给它的任务描述里我必须明确写出“禁止通过修改测试来让测试通过”这类行为约束。使用智能体我的底线是任务务必限定在一个可回滚的目录里。我会给它一个专属的工作目录或者一个特性分支让它的所有改动都隔离在这个范围内。一旦发现它越界改动了范围之外的文件立刻终止任务回滚变更。同时每次它完成一个阶段我都会做一次差异检查再放它进入下一个阶段绝不让它一口气连改十多个文件。从成本和收益角度来看智能体最适合用在那些“你交给别人做不放心、自己做又浪费时间”的琐碎任务上。你想要的核心价值不是它做了多少而是它能独立闭环地做掉一块完整的事情让你把注意力留在更高层的判断上。把七种武器都过了一遍之后我最深的感受是这些工具真正拉开差距的地方不在模型本身而在使用者有没有为每一种工具划定清晰的使用边界。补全负责高频重复对话助手负责理解和生成测试生成负责兜底代码审查负责防御读码和重构负责应对存量代码文档生成负责知识沉淀智能体负责把闭环的工作包出去。每一层都有它擅长的场景也都有它的坑。用对场景它们配合起来能让日常的开发节奏快出一大截用错场景它们就是在给你的代码库埋雷。我现在的日常工作流基本固定成了一套组合拳写新代码时主要靠补全和对话助手写完一轮准备提交时先让AI过一轮代码审查再抽时间把关键工具类的单测生成补上接手老项目时先让AI替我“读一遍”再按小步重构的节奏动刀交付前后顺手把文档沉淀出来杂活、脚本、重复性跨文件改动则交给智能体去跑。这套流程运行下来总体的安心感反而比以前自己大包大揽的时候更强——因为每一层都有验证和复查单点出错的概率明显降低了。如果说还有什么补充的那就是别神话任何一种武器也别因为哪一次翻车就彻底弃用。我见过有人因为AI生成了一段有问题的代码就下结论说“AI编程不靠谱”也见过有人因为智能体成功做掉了一个任务就放心让它去动整个核心系统。这两种极端都不可取。工具永远是在具体场景里讨论才有意义的先搞清楚当前这个任务属于七种武器里的哪一类、边界在哪、怎么验证再用对应的方法去处理才是AI Coding带给我最大的改变。