
如果你现在的工作日常还是“把AI生成的代码粘进项目里改改报错能跑就提交”那我劝你停下来把这篇文章看完。半年多前我也是这么干的直到有一次AI给我连着改了四版代码都没绕过那个边界条件我才意识到我一直在当它的“人肉执行器”而不是程序的拥有者。后来我慢慢把节奏调了过来先用AI Coding铺路再用产品思维拆需求用架构师的眼光定边界用测试和评审兜底。这半年最大的变化不是手速快了而是我从执行者变成了决策者。这篇文章没有什么高深的原理就是把我这大半年的真实工作流、踩过的坑、以及我从“复制粘贴AI代码”到“指挥AI干活”的转型过程完完整整讲给你听。适合那些正在用AI写代码、但总觉得代码不可控、不敢上生产、或者想进一步提升效率的同学。1. 我到底用AI Coding干了什么过去半年工作流的三个演变阶段1.1 第一阶段的Copilot式补全写代码像用输入法最早我开始接触AI Coding用的是编辑器里的代码补全类工具比如GitHub Copilot。那会儿我的工作流很简单写一个函数名AI帮我把函数体补全写一个SQL查询AI自动帮我补齐where条件写一个样板代码AI直接给你整套。说实话在写CRUD、配置类、重复性的胶水代码时这工具简直像输入法一样顺滑敲几个字母就能“联想”出大段内容。但那个时候我只是把它当成加速器。我的角色依然是执行者——每一行代码都需要我读过、理解过、确认过才能进代码库。AI补全了80%的冗余代码我却还是要花100%的精力去review、调试、改边界条件。它真正能帮我节省的只有敲键盘的时间没节省任何思考的时间。现在回头看这个阶段的本质是“人机结对编程”但主导权完全在我。我的大脑依然在处理每个变量、每个分支、每个异常。说实话这个阶段对我的效率提升有限顶多从“一天写200行”变成“一天写300行”但我依然被代码细节绑架根本腾不出手去关心业务逻辑、模块设计和系统演进。1.2 第二阶段的对话式生成从函数到模块的跨越真正让我感觉到AI Coding价值上升的是从“自动补全”过渡到“对话式生成”。我常用的方式是直接打开AI对话窗口把需求描述给它比如“帮我写一个将订单列表导出为CSV文件的函数要考虑大文件内存问题同时包含列映射配置”。它不再只补全一个函数体而是能给我生成一个带注释、带依赖、带异常处理的完整模块。这个阶段我开始产生一种错觉AI已经能承担“写代码”的工作我可以从执行者退一步了。于是我开始让AI生成接口、实体类、Mapper、Service再批量贴进项目里。结果很快发现问题生成的代码风格统一但它对项目上下文的理解几乎为零。它不知道我的项目里已经有ToolUtil工具类不知道公司内部框架的返回体是Result 不知道数据库表里某些字段是枚举值存的还是字符串存的。于是我被迫变成一个“翻译官”把所有上下文手动塞进提示词里。经常一个任务要和AI来来回回对话十几轮它每一次给出的代码还是会有几个地方不合我的项目预期。说实话那段时间我对AI Coding是失望的觉得它只能写面试题不能写真实业务。现在想想问题不在AI而在我还在用执行者的身份跟它协作没切换到决策者的角色。1.3 第三阶段的Agent式协作AI开始自己跑测试、改报错转折点是后来出现的Agent式工具。所谓Agent式就是它不只是生成一段代码等你复制而是能拿到一个任务后自己读代码库、自己定位文件、自己改代码、自己跑测试、自己根据报错重试。早期我尝试过一些命令行Agent工具也用过能直接操作工作区的IDE插件比如Cursor的Agent模式、Cline、开源的Aider这类方案。我第一次用Agent做需求的时候给了它一个任务“在订单模块中新增一个按状态筛选的列表方法要求支持分页、排序、并补充单元测试。”我原本以为它会跟对话式AI一样只给出代码结果它做了四件事先搜索了订单模块现有的Repository和Service结构然后在合适位置加入了新方法再调用项目里的分页工具类最后还补了一个测试并执行了。整个过程我只看了几眼输出日志它自己把编译错误改掉了。那一刻我开始明白AI Coding的进化方向不是“更聪明的代码生成器”而是“能独立执行任务的数字员工”。也正是从那一刻起我的角色被彻底推向了决策者我不需要决定这个方法内部怎么写我需要决定的是——这个需求该不该做、做成什么样子、怎么验收、哪些边界条件不能让步。2. 执行者时期的真实状态AI代码“能用但不敢用”的坑如果你也和我以前一样处于“AI写代码、我负责复制粘贴”的阶段下面这几个坑大概率你都踩过。我不是劝你少用AI而是想让你知道执行者视角下的AI Coding效率再高也掩盖不了质量风险。2.1 最大的问题不是代码质量而是“我不知道它在干什么”很多人吐槽AI生成的代码没有质量但我的真实体会是最大的问题不在于代码写得烂而在于我完全不理解它为什么要这么写。举个例子我让AI写一个Redis分布式锁的工具类它给我生成的代码里加了一个自旋等待循环。代码能跑功能也对但我无法回答以下问题自旋时间为什么是100毫秒如果锁等待时间超过30秒怎么办这个循环会不会导致CPU占用过高如果是自己手写的代码我会知道每一个特殊分支都是从哪些业务场景里推出来的。但AI写出来的代码我只能看到一个“合理”的成品却看不到背后的取舍过程。这就导致当业务场景变化时我根本不敢去改它的代码因为我不知道改了以后会破坏掉什么隐含逻辑。这种“不敢动”的状态比“不会写”更可怕。在这个阶段我逐渐意识到AI执行得越多我对系统的理解就越稀薄。我以前是代码的主人后来变成了代码的搬运工再这样下去整个项目的知识会变成一块块黑盒。这不是效率问题是生存问题。2.2 上下文窗口幻觉AI会一本正经地编造不存在的API第二个大坑是AI的幻觉问题。它不是在“查资料”而是根据概率生成最像样的代码。所以它的输出里经常混着一些看起来合理、实际不存在的API。我有一次让它对接某个第三方支付网关的退款接口它给我写出一个PaymentClient.createRefundWithAutoRetry方法还附带了参数注释。结果我在依赖包里翻了半天根本没这个方法实际接口是RefundService.submitRefund。这种幻觉在执行者阶段特别致命因为执行者的习惯是“代码能跑就行”。每当AI给出一个不存在的方法编译器会直接报错报错后你可能习惯性让AI继续修它修的时候可能会引入更多虚构依赖陷入死循环。有多少人曾经被AI带偏去安装一个根本不存在的npm包我在网上见过有人让AI生成图片处理代码结果AI建议安装一个虚假的第三方库那个库实际是一个恶意包。幸好我用了公司内部的镜像源才没中招。面对幻觉执行者只会抱怨AI不靠谱决策者则会要求自己先建立“接口事实清单”把需要使用到的第三方SDK、内部工具类的真实签名列出来再喂给AI。你越是在一个盘根错节的老项目里越不能依赖AI对你项目内容的“猜测”。2.3 维护成本的隐性炸弹生成代码的债最后都要自己还再聊一个很多AI Coding实践者不敢承认的事实生成代码很爽但维护代码很苦。我以前让AI帮我写了一个报表导出功能它洋洋洒洒生成了300多行代码包含多层嵌套循环、动态拼接SQL、以及一个复杂的映射表。当时跑起来一切正常我也觉得很开心。两个月后业务要求增加一个过滤条件我拆那个方法拆了整整一个下午。原因很简单AI写代码时没有“未来三个月后会有另一个人来维护”的概念。它的代码风格是模块化也好、命名规范也好但对业务逻辑的抽象方式往往是过于局部、过于具体。它不会为了未来的扩展性去预留接口更不会为了可读性去牺牲一点执行效率。这些债务在生成的那一刻就已经注入了只不过要等到需求变更时才会爆炸。执行者最危险的状态就是把AI当成“免维护的队友”。实际上你每一次让AI写代码都是在签发一张远期支票还款人是你自己。所以后来我给自己定了一条规矩凡是AI生成的核心逻辑我必须自己完整重读一遍并且画出它的流程确保下一个人包括未来的我能看懂。3. 逼我从执行者变成决策者的三个转折点说了这么多坑那到底什么契机让我真正转变不是看了某篇文章也不是听了某场演讲而是三个真实到骨子里的项目经历一次一次把“执行者心态”打碎重组我才被迫站到了决策者的位置。3.1 第一次AI连续改了四版还是没绕过那个边界条件第一个转折点来自一个权限过滤需求。我希望实现“普通用户只能看到自己的订单管理员能看到全部订单”。很简单的功能对吧我让AI去改一个查询列表的接口AI给了第一版实现了WHERE user_id ?我把需求补了一句“管理员除外”它改成if (isAdmin) 不添加过滤条件。看起来没问题但测试时发现如果普通用户传了userId另一个用户ID作为查询参数它依然把别人的订单查出来了。我又让AI修正要求服务端强制使用当前登录用户ID忽略客户端传入的用户ID。AI给了第二版确实强制覆盖了。但管理员模式下它用当前管理员ID去做数据范围判断导致管理员只能看到属于自己ID的订单。我又让它改成“管理员不追加用户ID过滤”它给了第三版。结果管理员搜索指定用户订单时其它用户的订单又全都漏出来了。前前后后我改了四版每一步都像是在打地鼠。我终于意识到问题根本不在AI的代码能力而在我自己根本没有把需求定义清楚。我一直用“实现功能”的方式在描述任务但没有把“角色、数据范围、参数来源、异常输入”这些决策项固化成一条不可违背的规则。当规则不清晰时AI只能猜猜就得靠运气运气不好就会反复翻车。从那一刻起我开始要求自己先把需求变成决策树再让AI去实现。3.2 第二次我把任务描述从“实现功能”改成“满足验收条件”第二个转折点是我调整了给AI下任务的方式。以前我写提示词都是“实现一个用户注册接口”后来我改为“实现一个用户注册接口并在以下条件下返回特定状态码手机号格式非法时返回400手机号已存在时返回409验证码错误时返回403成功时返回200并附带用户摘要”。第一次这样写的时候我明显感觉AI的产出质量跳了一档。它不再是自由发挥而是在一组验收条件内做选择。更关键的是为了满足这些条件它自己会去设计校验逻辑、异常分支、状态码映射而这些以前都需要我事后手动补。这个过程让我彻底想明白“实现功能”是执行者思维“满足验收条件”是决策者思维。验收条件本质上就是你对系统行为的定义。你定义得越精确AI的执行越有方向。那天之后我不再花时间写“具体怎么实现”我开始花时间写“怎么算完成”。代码怎么写AI发挥要求怎么定我来。3.3 第三次让AI写测试用例反向纠正了我自己的需求漏洞第三个转折点更意外。有一次我让AI帮我为一个复杂订单折扣计算逻辑写单元测试。我原以为它只是把我口述的几条用例转成JUnit测试结果它生成的测试里有一条我完全没想到的场景折扣券和会员折扣同时生效时两个折扣率是直接叠加还是先算一个再算另一个。我一看这个测试就愣住了因为我从来只想到“叠加”和“取最大值”两种情况完全没想过“叠加的顺序”。那条测试直接暴露了我需求里的未定义区域。我去产品和业务那边确认业务自己也没想清楚最后我们补了一条规则先算会员折扣再对折后金额使用折扣券。也就是说是AI生成的测试倒逼我把需求漏洞补上了。如果没有这个转折我那套折扣逻辑上线后大概率会在某个用户组合下算错而且一时半会儿测不出来。这次经历让我对测试的认知完全刷新测试不再只是验证代码的工具而是把需求变成可验证契约的过程。我作为决策者的核心职责就是维护这份契约。AI可以帮我生成大量测试样例但它必须由我来审因为是它发现了我没想到的维度。4. 我现在的工作方法决策者的四层拆解框架经过这几次折腾我总结了一套自己用了大半年的工作方法。每次接到一个需求我不再直接打开编辑器而是先做四层拆解。这套框架不复杂但确实让我的AI Coding从“碰运气”变成了“可交付”。4.1 第一层目标定义——把“做什么”翻译成“可验证的结果”这是最关键的一层也是执行者和决策者之间最明显的分界线。目标定义不是一句话需求而是把“做某事”翻译成一组可以跑起来验证的结果。举个例子如果一个普通开发者听到“给订单列表加分页”他心里想的是“查数据库时加上limit和offset”。但如果是我现在来定义我会写成当page1时返回前20条订单按创建时间倒序响应体中必须包含total总订单数、hasMore是否还有下一页、items当前页数组当page小于1时后端按1处理当超过最大页数时返回空数组但hasMore为false。当我给AI输入的是这样的目标定义时它几乎不会跑偏。因为所有它可能自由发挥的关键分叉点都被我提前锁死了。当然并不是所有需求都需要定义得这么细但是对于关键业务逻辑和对外接口这个功夫绝对不能省。4.2 第二层边界圈定——明确AI不能碰的部分目标定义完之后我还会单独写一段“边界约束”明确告诉AI哪些地方不允许AI发挥。如果我说“这里调用公司内部的SensitiveDataUtil工具类做脱敏”那AI就没有任何理由自己写一段正则去脱敏如果我说“所有数据库操作必须走现有的BaseRepository”那AI就不能图省事直接用JdbcTemplate。为什么要做这一步因为AI在追求“完成功能”时倾向于选择它训练数据里最常见的实现路径而不是你项目里已经存在的惯例。你在边界约束里每多写一条“不能碰”AI就会少一个机会在核心代码上放飞自我。边界圈定还要包括“人机责任边界”。比如密钥管理、支付回调验签、数据迁移脚本这类敏感或一次性操作我通常直接自己写不让AI碰。这些代码出错成本太高AI试错的机会成本不可接受。作为决策者你要清楚哪些可以交给AI试错哪些必须人来兜底。4.3 第三层验收标准——用测试和人工评审兜底目标定义再清晰AI也可能在实现时出幺蛾子所以验收标准必须前置写进提示词里不能等代码写完再想。我自己最常用的验收标准有三个级别验收级别验收动作通过标准级别一编译与静态检查项目可以正常构建没有新增编译器警告主要依赖锁定在pom/package.json中级别二单元测试与边界用例关键逻辑覆盖正常、异常、边界三条路径全部测试通过级别三人工审查核心契约我亲自review接口行为确认异常处理、权限校验、日志记录都符合约定这里尤其要说一下第三级。人工评审不是把AI生成的代码从头到尾读一遍而是回到接口契约层面去审入参出参是否和行为定义一致异常是否需要被捕获还是应该抛出并发场景是否被人为忽略了这种评审比逐行读代码快得多而且更能发现问题。4.4 第四层反馈循环——带着结果复盘的决策闭环最后一层是闭环。任务交付完之后我会记录两件事一是AI生成过程中返工过几次返工的原因是需求定义不清还是AI能力不足二是我在评审中发现哪些高频问题比如AI总是不处理空列表、总是忘记幂等控制、总是直接用魔鬼数字。带着这些记录我会不断更新我给AI下达任务的模板。现在我常用的提示词模板里已经默认加入了几个约束“不要假设输入非空请显式处理null值”“不要在业务代码里直接创建线程池”“所有外部调用必须加超时时间”。这些规则不是哪本AI编程书教我的是我在一次又一次反馈循环里沉淀出来的。决策者的优势就在这你不是给AI派一个任务就结束了你会带着每次的真实结果去调整下一步的决策质量。你的判断越来越准AI的执行也越来越高效整个系统是持续进化而不是原地打转的。5. 决策者的技能迁移我花大半年才想明白的评审技巧身份转变之后我最直接的感受是以前我的核心技能是“写代码”现在我的核心技能是“评审AI写的代码”。但这里的“评审”跟传统代码评审完全不是一回事。5.1 代码评审从“读代码”变成“审接口契约”传统代码评审里我会一行一行看变量命名、循环逻辑甚至挑缩进风格。但AI生成的代码如果不符风格一键格式化就好了逐行看它没有意义。真正需要关注的是AI有没有实现接口契约。比如一个获取用户信息的接口我的契约是“输入userId输出用户脱敏信息如果用户不存在返回null但不抛异常如果userId为空直接抛参数异常”。评审的时候我就检查AI生成的代码是否遵守这三个行为而不必关心它是用Optional还是用if判断。我还养成了一个习惯在review AI代码时先看它的测试再看实现。因为AI生成的测试反映了它对需求的理解。如果测试里没有覆盖“用户不存在”这种分支我就要警觉它可能根本没考虑这个场景。这时候我不需要去改代码我只需要补充一条验收条件让AI自己把测试和实现补上。这个方法论用熟了以后我每天的代码评审时间反而比过去减少了30%因为AI的大部分机械错误在自带测试阶段就被干掉了。5.2 架构决策必须提前AI不会替你作权衡“让AI写代码自己做架构”听起来很容易但真正做到需要很强的克制力。AI最擅长的是在你给定的模块边界内快速生成实现。但如果模块边界本身画错了AI生成得越快后患越大。我就犯过这个错。有一次我让AI写一个报表模块的存储层它默认使用了JDBC加手写SQL因为它觉得这样“直接、简单”。可当时我们项目里已经启用了JPA统一了事务和审计字段。后来为了接入自定义审计日志我把那部分代码全部重写了。问题不在AI的选择是错的而在于AI根本不知道整个系统未来要朝哪个方向演进它只会选“最容易写”的方案不会选“最不后悔”的方案。所以现在我每次动手之前都会先把模块的依赖方向定死上层接口长什么样下层数据仓库用什么规范领域对象要不要跨层传递。我甚至会把整体结构写成注释放在提示词里告诉AI“这是既定设计你只负责填充实现”。这个习惯让我把AI的能力牢牢锁在可控范围内。5.3 兜底思维你始终要为AI的结果负最终责任还有一件事是我反复提醒自己的不管AI Coding再怎么进化线上出故障的时候老板和客户找的是我不是AI。所以我的兜底思维永远在线。具体来说我会给所有AI生成的核心代码做两件事。第一强制掌握核心路径比如如果AI生成了密码加密的逻辑我哪怕不自己写也必须能徒手画出一个加解密流程图并指出密钥存储在哪个配置项、是否落盘、轮换怎么处理。第二给AI生成逻辑外圈加保护比如在AI实现的方法入口加上参数校验在调用外部服务时统一包一层超时和重试在写入数据库前增加幂等判断。我不要求AI自己考虑这些因为我的兜底责任本来就不在AI那边。如果你也想完成从执行者到决策者的转变这里最关键的心理建设就是不要再对着AI的代码高呼“它写得真好”或痛骂“它写得好烂”。你应该把它当成一个执行力很强、但全局判断力为零的初级工程师你的价值就是给它划好跑道并负起最终责任。6. 如果你也想从执行者变成决策者一条可复制的路径最后聊点实在的如果你已经被我说动了想开始尝试跳出“复制粘贴”模式我给你一条我自己验证过、身边几个同事也在用的路径。它不是玄学全是粗糙但有效的实操。6.1 先别急着上Agent从单文件重构开始练手我看到很多人看完Agent演示视频以后直接把整个项目的核心模块丢给AI让它自己改。这跟让刚拿驾照的人直接上高速没有区别。我的建议是先拿一个你完全熟悉的、没有依赖复杂度的单文件做练习比如把一个工具类里的重复代码重构为通用方法。之所以强调“你完全熟悉”是因为你要有能力判断AI每一步是对是错。只有当你对原始代码了如指掌时你才能快速建立“AI生成的代码是否存在行为变化”的感知力。等你连这种单文件重构都能轻松驾驭对AI的输出质量和偏差模式有了体感再逐步扩大到多文件模块、再到Agent式任务。进度慢一点没关系这个阶段的核心是建立你自己的判断标准。6.2 给AI写提示词的进阶心法说结果不说过程很多人的提示词之所以翻车是因为他把自己脑子里的过程一股脑塞给AI比如“先建一个DTO、然后写一个Controller、再调Service、最后用MyBatis查库”。这种做法不是不行但会严重浪费AI的灵活性。AI看的是你的步骤不是你的目标一旦你中间有一句话描述偏了后面的实现就会跟着偏。更好的方式是这样先描述输入和输出再描述约束条件最后补充几条具体的验收用例。比如“写一个订单取消接口。输入订单ID、操作人ID、取消原因输出取消成功返回true订单不存在返回false已发货订单返回异常。约束需要记录取消日志。验收用例未付款订单取消成功已发货订单取消抛异常。” 你会发现AI给出的实现路径往往比你预想的更简洁因为它会在约束空间里自己找最优解。6.3 建立自己的AI代码评审清单不要每次都用感觉来评审AI代码一定要形成清单。我目前的个人清单大约十条每一条都是踩坑踩出来的分享给你做个参考是否直接使用了硬编码的密钥、IP、数据库地址是否有不必要的第三方依赖被引入是否考虑了空集合、null参数和极端大输入异常是吞掉了还是转换成了合理错误码是否对耗时外部操作设置了超时控制是否在循环里执行了数据库查询或远程调用权限相关逻辑是否放在了Controller层而不是Service层生成的日志级别是否合适有没有打印敏感字段是否按要求复用了项目现有的工具类和设计模式是否补了单元测试测试是否覆盖了边界路径这条清单我每隔一段时间就会往里面加一条。它不是固定的而是活的。你也可以从十条开始慢慢沉淀出适合自己的版本。6.4 什么情况下应该果断放弃AI手写更快最后还要说一个反直觉的经验我虽然大量使用AI Coding但几乎每周都会遇到“我应该自己写”的场景。这类场景通常有几个特征性能调优的细粒度代码比如一段需要极致优化的热路径算法深度框架定制比如要继承某个框架的内部类并改写核心回调强一致性的分布式事务代码这种地方AI很难理解你对时序和补偿的要求以及任何涉及合规审计的逻辑比如日志脱敏、权限越权判定。在这些场景里AI顶多当一个参考资料生成器核心代码请自己写。我自己现在的决策标准是如果这个模块后续迭代频率高、或者出错会造成重大影响那我宁愿自己把骨架搭好再让AI去填充那些不太重要的部分。如果模块本身是低风险、独立、一次性使用那整个交给AI都没问题。这种“分而治之”的决策能力也算是我这半年最大的收获之一。说实话从执行者到决策者的转变并不容易它需要你暂时放下“手写代码的安全感”去拥抱“定义需求的掌控感”。这半年里我有过很多次不适应甚至有一阵子觉得AI让我变成了一个只会提需求的“假开发”。但后来我想通了工具替我把代码敲出来不等于工具替我把架构想清楚也不等于工具替我对线上负责。真正的核心竞争力永远是你判断“什么是对的”的能力。这半年我自己的体会是现在我和AI的关系更像是一个技术负责人和它的程序员员工。我会花很多时间把为什么、边界、验收条件解释清楚然后看着它把代码交付出来再亲自签字验收。有时候它做得好我赞美它有时候它犯低级错误我会回头反思是不是我又少定义了某个边界条件。AI Coding大半年键盘敲得越来越少脑子用得越来越多。我不再执着于每一行都出自我的手而是执着于每一段代码都在我的掌控之中。这个转变可能才是AI时代程序员最该跨出的一步。