
1. 为什么“工作流”比“提示词”更值得花时间很多人聊 AI 编程第一反应是去搜“最强提示词”“咒语合集”。我早期也这么干过收藏夹里躺了几百条 prompt真到写业务代码的时候一条都想不起来用。问题出在哪提示词是单点的它解决的是“这一次我问 AI 该怎么问”而真实开发是连续的——需求拆解、方案设计、编码、测试、重构、写文档每一步的上下文都不一样指望一条万能提示词打通全流程本身就不现实。工作流不一样。工作流是把“什么阶段、喂什么上下文、让 AI 产出什么形态的东西、人怎么验收”这一整套动作固定下来。它更像是一条流水线而不是一把瑞士军刀。你一旦把某条流水线跑顺了下次遇到同类任务直接复用几乎不用重新思考“我该怎么问”。我自己的判断标准很简单一条工作流值不值得留下来看它能不能让我在第二次遇到同类任务时省掉至少 70% 的思考成本。提示词做不到这一点工作流可以。下面这三条是我在真实项目里反复用、反复改最后稳定下来的。它们分别对应三类高频场景读陌生代码、写新功能、改遗留系统。每一条我都会讲清楚它解决什么问题、为什么这么设计、具体怎么落地以及我踩过的坑。提示这三条工作流不依赖任何特定厂商的模型你用手头的任意一个具备长上下文和代码能力的模型都能跑。重点在流程设计不在工具。2. 工作流一陌生代码库的“三遍扫描法”2.1 这个场景到底难在哪接手一个几万行、没有任何文档、原作者已经离职的代码库是每个程序员都会遇到的噩梦。传统的做法是从入口文件开始顺着调用链一路读下去。这个方法在小型项目里没问题但在中大型项目里你会很快迷失——因为调用链是网状的你顺着一条线走下去走到第五层就忘了第一层是干嘛的。AI 在这里能帮上大忙但前提是你不能一上来就问“帮我解释这个项目”。这种问法得到的回答通常是一堆正确的废话比如“这是一个基于 XX 框架的 Web 应用包含控制器、服务层和数据访问层”。这些你打开目录结构就能看出来不需要 AI 告诉你。真正有价值的问法是带着具体问题去扫描每一遍只解决一类问题。2.2 第一遍只问“数据从哪来到哪去”第一遍扫描我只看一件事核心数据实体的流转路径。比如一个电商系统核心实体就是订单。我会这样操作先让 AI 列出项目里所有跟“订单”相关的文件按目录归类。然后针对每一个文件只问一个问题“这个文件对订单数据做了什么操作读、写、还是转换”最后让 AI 把结果整理成一张表。这一步的关键是限制 AI 的输出范围。如果你问“这个文件是干嘛的”AI 会给你一大段描述里面 80% 是你暂时不需要的。但如果你问“它对订单数据做了什么”AI 的回答会非常聚焦。我实测下来一个 5 万行的项目第一遍扫描大概需要 20 到 30 次对话产出一张 30 行左右的数据流转表。这张表就是你后续所有工作的地图。2.3 第二遍只问“边界和异常”有了数据流转表第二遍扫描就有的放矢了。这一遍我只关心一件事每个关键节点上异常是怎么处理的。具体做法是拿着第一遍产出的表逐个节点问 AI这个函数在参数为空时怎么处理这个接口在数据库连接失败时返回什么这个转换逻辑遇到非法输入时是抛异常还是返回默认值这些问题看起来琐碎但它们决定了你对这个系统的信任边界。你知道哪些地方是可靠的哪些地方是“假设上游一定正确”的后续改代码时心里就有数了。注意这一遍千万不要让 AI 去“评价”代码质量。你一问“这段代码写得好不好”AI 就会开始输出一堆主观意见对你理解系统没有任何帮助。只问事实不问评价。2.4 第三遍只问“如果我要改 X会影响到谁”前两遍做完你对系统已经有了基本认知。第三遍是验证性扫描目的是确认你的理解是否正确。具体做法是假设一个你未来大概率要做的改动比如“我要给订单增加一个折扣字段”然后问 AI这个改动会波及哪些文件、哪些函数、哪些数据库表AI 给出的影响范围你拿去跟第一遍的数据流转表对照。如果对不上说明你对系统的理解还有盲区回去补。如果对得上说明你已经可以安全地动手了。这三遍扫描下来通常需要一到两天。听起来很久但比起“读了两周代码还是不敢改”的情况这个投入产出比非常高。2.5 我在这条工作流上踩过的坑最大的坑是贪多。我一开始想一遍就把所有问题都问完结果 AI 的回答越来越泛最后变成了一篇项目介绍。后来我强制自己每遍只问一类问题效果立刻不一样了。第二个坑是不给 AI 看目录结构。AI 不知道文件之间的物理关系它只能根据你粘贴的代码片段去猜。后来我养成了一个习惯每次开始扫描前先把项目的目录树用tree命令生成去掉 node_modules 之类的噪音贴给 AI让它对项目规模有个概念。第三个坑是对话太长。一条对话超过 40 轮之后AI 对早期内容的记忆会明显衰减。我的做法是每 15 轮左右让 AI 把当前结论整理成一段摘要然后开一条新对话把摘要和目录树一起贴进去继续问。这样虽然麻烦一点但准确率高很多。3. 工作流二新功能开发的“契约先行”法3.1 为什么直接让 AI 写代码往往返工很多人用 AI 写新功能的方式是描述一下需求让 AI 直接输出代码然后复制粘贴跑一下报错再让 AI 改。这个循环会重复很多次而且每次修改都可能引入新的问题。根本原因在于AI 在写代码时对“输入输出”的理解和你不一致。你脑子里的“用户对象”有十个字段AI 可能只实现了五个你以为异常要往上抛AI 可能直接吞掉了。这些分歧在代码写完之后才暴露修改成本就很高。“契约先行”的思路是在写任何一行实现代码之前先把接口契约敲定。契约包括函数签名、输入输出的数据结构、异常约定、边界条件。契约一旦确定实现代码就变成了“填空题”AI 出错的概率大幅下降。3.2 第一步让 AI 帮你把需求翻译成契约假设我要做一个“根据用户标签推荐商品”的功能。我不会直接说“帮我写一个推荐函数”而是先让 AI 做一件事我要实现一个商品推荐功能。输入是用户 ID 和一个可选的标签列表输出是一个商品列表每个商品包含 ID、名称、匹配分数。请你先不要写实现只帮我定义这个函数的契约包括参数类型、返回值结构、可能的异常情况。AI 会给出一个类似这样的契约def recommend_products( user_id: int, tags: Optional[List[str]] None, limit: int 20 ) - List[ProductRecommendation]: 根据用户标签推荐商品。 异常 - UserNotFoundError: 用户 ID 不存在 - InvalidTagError: 标签格式非法 边界 - tags 为空时使用用户历史行为标签 - limit 超过 100 时强制截断为 100 拿到这个契约后我会逐条审查。比如“tags 为空时使用历史行为标签”这个约定是不是我想要的如果历史行为也为空呢这些细节在契约阶段确认比在代码阶段发现要省事得多。3.3 第二步把契约拆成“可独立验证的小块”契约确定后不要一次性让 AI 写完整实现。我的做法是把它拆成几个独立的小块每块单独让 AI 写单独验证。以上面的推荐函数为例我会拆成参数校验逻辑用户是否存在、标签是否合法、limit 是否越界标签获取逻辑显式标签优先否则取历史行为标签商品匹配逻辑根据标签查商品、计算匹配分数排序和截断逻辑每一块写完后我立刻写一个最小的测试用例跑一下。跑通了再写下一块。这样即使某一块出了问题我也知道问题出在哪一块不会在一大堆代码里大海捞针。提示这一步的关键是不要让 AI 一次性输出所有块。你让它一次写四块它会在块与块之间做很多“合理但你没要求”的假设。一块一块来虽然对话轮次多了但总时间反而更短。3.4 第三步让 AI 写测试但你来定测试用例实现代码写完后我会让 AI 生成单元测试。但这里有个陷阱如果你让 AI 自己决定测什么它会倾向于测那些容易通过的路径。真正容易出问题的边界条件它反而会跳过。我的做法是我自己列出测试用例清单让 AI 把清单翻译成测试代码。清单包括正常路径用户存在、标签合法、有匹配商品边界路径标签为空、limit 为 0、limit 超过上限异常路径用户不存在、标签格式非法、数据库查询超时AI 负责把这些用例写成规范的测试代码我负责检查用例覆盖是否完整。这样分工效率和覆盖率都能保证。3.5 这条工作流里最容易被忽略的细节契约的版本管理。我吃过一次亏契约改了但实现代码和测试代码没有同步更新结果测试全绿线上却出了问题。后来我养成了一个习惯契约文件单独放在一个目录里每次修改都在文件头加一行注释写明修改日期和原因。这样至少能追溯。不要让 AI 同时改契约和实现。有一次我让 AI“优化一下这个函数”它把契约和实现一起改了改完之后我完全不知道哪些行为变了。正确的做法是契约的修改必须由人发起AI 只负责执行。留一个“契约快照”。每完成一个功能我会把最终的契约文件复制一份到docs/contracts/目录下。下次有人问“这个接口当初是怎么约定的”直接翻快照比翻聊天记录靠谱得多。4. 工作流三遗留系统改造的“影子实现”法4.1 遗留系统为什么不能直接让 AI 重写遗留系统改造是 AI 编程里风险最高的场景。很多人想的是把老代码贴给 AI让它重写一遍。这个做法在玩具项目里可能可行在真实系统里几乎必然翻车。原因有三个。第一老代码里有很多隐式约定比如某个字段虽然叫status但实际上同时承载了状态和优先级两种信息这种约定不会写在注释里AI 看不出来。第二老代码的副作用往往比主逻辑更重要比如某个函数在返回结果的同时还往日志表里写了一条记录AI 重写时很容易漏掉。第三老代码的性能特征是长期调优的结果AI 重写后的版本可能逻辑正确但性能差十倍。所以我的做法是不重写而是做“影子实现”。4.2 什么是影子实现影子实现的意思是新代码和旧代码同时存在新代码在后台运行但不接管实际流量。每次旧代码被调用时新代码也跑一遍然后把两者的输入输出做对比。对比结果一致说明新代码逻辑正确不一致说明有差异需要排查。这个方法的妙处在于它把“验证”从人工审查变成了自动对比。你不需要逐行读懂老代码只需要让新老代码在真实流量下跑一段时间差异自然会暴露出来。4.3 具体怎么落地第一步给旧函数加一个“旁路调用”。比如旧函数叫calculate_price我在它内部加一行调用新函数calculate_price_v2把相同的参数传进去然后把两个结果都写进一张对比表。def calculate_price(order): old_result _calculate_price_legacy(order) # 影子调用不影响主流程 try: new_result calculate_price_v2(order) log_shadow_comparison(order.id, old_result, new_result) except Exception as e: log_shadow_error(order.id, str(e)) return old_result注意这里有几个细节新函数的调用必须包在 try 里因为新代码可能有 bug不能让它影响主流程对比结果要记录订单 ID方便后续排查新函数的异常也要单独记录这本身就是有价值的信息。第二步让 AI 帮你分析差异。跑了一段时间后对比表里会积累大量记录。这时候把差异记录只取不一致的那些贴给 AI让它帮你归类哪些是浮点数精度问题哪些是边界条件处理不同哪些是真正的逻辑错误。AI 在这件事上非常擅长因为它不需要理解整个系统只需要对比两组数据。我实测下来一个中等复杂度的函数跑一天真实流量差异记录通常能控制在几十条以内AI 几分钟就能归类完。第三步逐类修复直到差异归零。差异归零后再把流量切到新函数。这时候你对新代码的信心不是来自“我觉得它写对了”而是来自“它在真实流量下和旧代码表现完全一致”。4.4 影子实现法的适用边界这个方法不是万能的。它最适合的场景是纯函数、输入输出明确、调用频率高。调用频率高意味着你能在短时间内积累足够的对比样本。它不适合的场景是有大量副作用的函数、调用频率极低的函数、涉及外部系统交互的函数。对于这些场景影子实现要么无法对比副作用没法比要么样本太少跑一个月才调用几次要么对比结果不可靠外部系统本身就不稳定。我自己的经验是一个遗留系统里大概 60% 到 70% 的函数可以用影子实现法安全改造剩下的需要人工介入。这个比例已经能省下大量时间了。4.5 我在遗留系统改造中总结的几条铁律永远不要在没有对比数据的情况下切换流量。我见过太多团队新代码写完测试跑通就直接上线结果线上出问题。测试通过只能说明你想到的场景没问题不能说明你没想到的场景没问题。对比表的保留时间要足够长。我一般会保留至少两周的对比数据。有些差异是周期性的比如月末结算时的特殊逻辑跑一天是看不出来的。新代码的性能要单独监控。影子实现只对比了输出没对比耗时。如果新代码比旧代码慢很多即使输出一致切换后也可能拖垮系统。我的做法是在对比表里同时记录两个函数的执行耗时差异超过 20% 就告警。不要一次改太多。我试过一次改五个函数结果差异记录混在一起排查起来非常痛苦。后来改成一次只改一个函数改完验证完再改下一个。慢是慢了点但稳。5. 三条工作流的共同底层逻辑5.1 都是“先约束后生成”回头看这三条工作流它们有一个共同点在让 AI 生成任何东西之前先给它一个明确的约束框架。三遍扫描法里约束是“每一遍只问一类问题”。契约先行法里约束是“先定契约再写实现”。影子实现法里约束是“新代码必须和旧代码输出一致”。这个思路和很多人用 AI 的方式正好相反。大多数人是先让 AI 生成生成完了再想办法约束它、修正它。但 AI 的生成能力太强了一旦方向偏了修正的成本比重新生成还高。先约束后生成看起来慢实际上快。5.2 都把“验证”当成工作流的一部分这三条工作流里验证不是事后补的而是流程里天然存在的一环。三遍扫描法的第三遍就是验证契约先行法的单元测试就是验证影子实现法的对比表就是验证。我越来越觉得用 AI 编程的核心能力不是“写提示词”而是“设计验证机制”。你能设计出一个让 AI 的输出可以被自动验证的流程你就能放心地把更多工作交给 AI。反之如果你的流程里没有验证环节你就永远得盯着 AI 的每一行输出那效率反而比手写还低。5.3 都假设 AI 会犯错这三条工作流的设计前提都是AI 会犯错而且犯的错不一定能被你一眼看出来。所以三遍扫描法要扫三遍契约先行法要拆块验证影子实现法要跑真实流量对比。这个假设听起来很悲观但它恰恰是效率的来源。因为你不再指望 AI“一次做对”而是设计了一个“即使做错也能被发现和修正”的流程。心态上放松了用起来反而更顺手。6. 怎么把这三条工作流变成你自己的6.1 从最小可复用的单元开始不要一上来就想搭建一套完整的工作流体系。我的建议是从你下周要做的第一个任务开始挑一条工作流完整跑一遍。如果你下周要接手一个陌生模块就跑三遍扫描法。如果你下周要写一个新接口就跑契约先行法。如果你下周要改一个老函数就跑影子实现法。跑完一遍之后你会对这条工作流有体感。哪里顺、哪里卡、哪里需要根据你的项目特点调整这些只有跑过才知道。6.2 把工作流写成清单跑顺之后把它写成一份清单。清单不需要很正式几行字就行。比如三遍扫描法的清单可能是第一遍贴目录树只问数据流转产出流转表第二遍拿着流转表只问异常处理产出信任边界第三遍假设一个改动问影响范围和流转表对照清单的好处是下次你不需要重新回忆流程照着做就行。而且清单可以迭代你每次跑完发现哪里可以优化就改一行。6.3 不要追求“完美工作流”我见过一些人花大量时间设计工作流但真正用的时候发现各种不顺手。工作流是在使用中长出来的不是设计出来的。我的做法是先用一个粗糙的版本跑起来跑的过程中记录哪里不舒服跑完再改。改完再跑再改。迭代个三五次一条适合你的工作流就成型了。6.4 一个我常用的收尾技巧每次用完一条工作流我会花五分钟做一件事把这次用到的关键提示词、关键判断、关键坑记在一个固定的笔记文件里。不需要很详细一两句话就行。比如“三遍扫描法这次项目有 200 个文件第一遍花了 25 轮对话比上次多原因是目录树没去掉测试文件下次记得先过滤。”这个习惯坚持了半年之后我发现自己对“什么项目该用什么工作流”有了直觉。这种直觉是任何教程都给不了的。最后说一句实在话AI 编程工具每天都在变今天好用的模型明天可能就过时了。但工作流这种东西底层逻辑是稳定的——先约束、后生成、再验证。你把这三件事想清楚了换什么工具都能快速上手。