ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

AI编程工作流实战:陌生代码阅读、契约先行与Bug排查

AI编程工作流实战:陌生代码阅读、契约先行与Bug排查 1. 为什么“工作流”比“提示词”更值得花时间这两年我见过太多人把 AI 编程等同于“背提示词”。收藏夹里躺着几百条所谓的万能提示词真到写业务代码的时候还是复制粘贴、改改报错、再复制粘贴。问题不在于提示词不够好而在于提示词是一次性的而工作流是可复用的。打个比方提示词像是一道菜的菜谱你照着做能出一盘菜工作流则是你厨房里的动线设计、备菜顺序、灶台布局它决定了你一天能出多少盘菜、出错率有多低。真正拉开效率差距的从来不是某一句神来之笔的提示词而是你把 AI 嵌进日常开发流程的方式。我自己的判断标准很朴素一个 AI 编程工作流值不值得留下来就看它能不能满足三条——输入稳定、输出可预期、失败可回退。满足这三条它才配叫“工作流”否则就只是一次运气不错的对话。下面这 3 个流程是我从日常开发里沉淀下来、反复用了大半年还在用的。它们分别覆盖了三个最高频的场景读陌生代码、写新功能、改遗留 bug。每一个都能立刻复用不需要你换编辑器、不需要额外付费工具只要有一个能对话的 AI 编程助手就行。提示下文所有流程都不依赖某个特定厂商的模型。你用的是哪家都行关键是流程本身的结构。模型会换代流程不会。2. 工作流一陌生代码库的“三遍阅读法”2.1 这个流程解决什么问题接手一个陌生项目最痛苦的不是代码难而是你不知道该看哪里。几万行代码几十个目录README 还停留在三年前。传统做法是从入口文件开始一行行啃啃到第三天还没搞清楚核心链路在哪。我的做法是把“读代码”这件事拆成三遍每一遍都让 AI 承担不同的角色。核心思路是先要地图再要路线最后要路标。不要一上来就让 AI 解释某个函数那是最低效的用法。2.2 第一遍让 AI 画出项目地图第一遍的目标只有一个——搞清楚这个项目由哪些模块组成、模块之间怎么调用。这一步不要看具体实现看了就是浪费时间。我会先做一件事把项目的目录结构导出来。命令行里一条命令就够find . -type f -name *.py -not -path */node_modules/* -not -path */.git/* | head -100如果是 JS/TS 项目就把后缀换掉。拿到文件列表后我把它连同项目的 README、package.json 或 requirements.txt 一起丢给 AI用这样一段话这是一个我刚开始接触的项目。请基于我提供的目录结构和依赖清单帮我梳理出1这个项目大致分成哪几个功能模块2每个模块最可能的入口文件是哪个3模块之间的依赖方向。不要解释具体代码我只要一张结构地图。注意最后那句“不要解释具体代码”。这是关键。AI 有个坏习惯你给它文件列表它会忍不住开始猜每个文件干什么猜得越多错得越多。明确告诉它“只要结构”输出质量会高一个档次。这一步的产出通常是一张文字版的模块图。我会把它记在笔记里后面两遍都对着这张图看。2.3 第二遍沿着一条主链路走通有了地图第二遍就挑一条最重要的业务链路走通。什么叫最重要通常是这个项目对外提供的核心功能比如一个电商项目就是“下单”一个内容平台就是“发布”。这时候我会把这条链路上涉及的 3 到 5 个文件完整贴给 AI然后这样问这几个文件构成了“下单”这条链路。请帮我按执行顺序梳理出请求从哪个函数进入、经过了哪些关键处理、最终写到了哪里。每一步请标注对应的文件名和函数名。这里有个经验一次只走一条链路。我见过有人图省事把整个 src 目录全贴进去让 AI 分析结果 AI 给出的东西又长又空全是“可能”“大概”。上下文塞太满AI 的注意力会被稀释反而抓不住重点。走通一条链路之后你对这个项目的“骨架感”就建立起来了。后面再看别的模块都能挂到这条主链路上。2.4 第三遍针对性地问“为什么”前两遍解决的是“是什么”和“怎么走”第三遍才轮到“为什么”。这时候你已经有了具体的问题比如“为什么这里要用消息队列而不是直接调用”“为什么这个字段要冗余存一份”。带着具体问题去问 AI效果和漫无目的地让它解释代码完全是两回事。我的提问模板是在这个文件第 X 行代码做了 A 操作。结合上下文我猜测它是为了 B 目的。请帮我确认这个猜测是否合理如果不合理更可能的原因是什么。把 AI 当成一个可以随时请教的同事而不是一个代码翻译机。你给出自己的判断让它来验证或反驳这种对话的信息密度远高于“帮我解释这段代码”。2.5 三遍阅读法的注意事项这个流程我踩过的坑主要有两个。第一个坑是第一遍就陷进细节。看到某个函数写得巧妙忍不住让 AI 展开讲一讲就是半小时结果地图还没画完。后来我给自己定了规矩第一遍绝对不看函数体只看文件名、目录名、依赖关系。第二个坑是上下文给太多。早期我总担心 AI 信息不够恨不得把整个项目塞进去。实测下来单次对话给 3 到 5 个文件、总长度控制在几千行以内效果最好。超出的部分AI 要么忽略要么开始编。遍数目标给 AI 的输入关键提问第一遍画地图目录结构 依赖清单分几个模块、入口在哪第二遍走链路一条链路的 3-5 个文件按执行顺序梳理第三遍问原因具体文件 具体行号验证我的猜测3. 工作流二新功能的“契约先行”生成法3.1 为什么直接让 AI 写代码会翻车很多人用 AI 写新功能的方式是描述一下需求然后说“帮我写个函数”。这么干十次有八次要返工。原因很简单——你和 AI 对需求的理解根本不在一个频道上。你脑子里的“用户列表”带着分页、带着权限过滤、带着软删除AI 脑子里的“用户列表”就是一个SELECT * FROM users。返工的根源不是 AI 写得差而是契约没对齐。所以我的第二个工作流核心就一句话先让 AI 写契约确认无误后再让它写实现。3.2 第一步把需求翻译成函数签名所谓契约就是函数的输入输出。这一步我要求 AI 只输出签名和注释不写一行实现。提问方式是这样的我要实现一个功能根据用户 ID 查询他最近的订单列表支持分页需要过滤掉已取消的订单。请先只给我函数签名和参数说明包括每个参数的类型、是否必填、默认值。不要写实现。拿到签名后我会逐条核对。这一步花的时间通常只有两三分钟但能省下后面半小时的返工。核对的重点有三个参数类型对不对、边界情况考虑没有、返回值结构合不合理。比如上面这个需求AI 可能会给出这样的签名def get_recent_orders( user_id: int, page: int 1, page_size: int 20, include_cancelled: bool False ) - dict: 查询用户最近的订单列表。 Args: user_id: 用户 ID必填 page: 页码从 1 开始默认 1 page_size: 每页数量默认 20最大 100 include_cancelled: 是否包含已取消订单默认 False Returns: { total: int, # 总条数 page: int, # 当前页 items: list # 订单列表 } 看到这个签名我立刻能发现几个需要确认的点page_size要不要设上限include_cancelled这个参数是不是应该由调用方决定而不是写死这些在写实现之前确认成本几乎为零等实现写完再改就是牵一发动全身。3.3 第二步让 AI 先写测试用例契约确认后我不急着让它写实现而是让它先写测试。这一步是很多人会跳过的但恰恰是价值最高的。基于上面的函数签名请帮我写出 5 个测试用例覆盖正常查询、分页边界、空结果、参数非法、包含已取消订单的情况。用 pytest 风格。为什么先写测试因为测试用例是需求的另一种表达。AI 写测试的时候会暴露出它对需求的理解。如果它写的测试用例和你想的不一样说明契约还有歧义这时候改还来得及。我印象很深的一次让 AI 写一个“批量导入”功能的测试它写了一个“导入空文件应该报错”的用例。我一看这不对啊空文件应该返回成功但导入 0 条。就这一个用例让我发现契约里没写清楚空文件的处理方式。如果直接写实现这个 bug 大概率会漏到线上。3.4 第三步实现 自测测试用例确认后才轮到写实现。这时候的提问就很简单了请实现上面的函数让所有测试用例通过。实现时注意数据库查询用现有的 OrderRepository不要直接写 SQL。因为契约和测试都已经对齐AI 写出来的实现通常一次就能过。即使不过也是小修小补不会出现“整个思路都错了”的情况。这一步我还会加一个动作让 AI 自己跑一遍测试并解释结果。虽然它不能真的执行代码但让它“模拟执行”并说明每个用例的预期结果能进一步暴露逻辑漏洞。3.5 契约先行的实操心得这个流程用熟之后我发现它最大的价值不是省时间而是改变了我和 AI 的协作姿势。以前是我说一句、它写一段、我改一段来回拉扯现在是我和它先对齐规格然后它一次性交付。前者像挤牙膏后者像下订单。有个细节值得说契约阶段的对话要短。我见过有人把契约写得比实现还长那就本末倒置了。契约的作用是消除歧义不是替代设计文档。函数签名加几行注释足够了。注意如果需求本身就很模糊比如“做个推荐功能”那契约阶段要往前再推一步——先让 AI 帮你把模糊需求拆成几个具体问题逐个确认后再进入契约。跳过这一步契约也是空中楼阁。4. 工作流三遗留 Bug 的“假设-验证”排查法4.1 遗留 Bug 为什么难搞新功能的 bug 好查因为逻辑是你刚写的脑子里有全貌。遗留 bug 难查难在你不知道这段代码当初为什么这么写。可能有个历史原因可能有个隐藏依赖可能注释和实现早就对不上了。传统排查方式是加日志、打断点、一行行看。这套方法没错但慢。我的做法是用 AI 把“猜测”这个环节加速——让 AI 基于代码给出多个可能的原因假设然后我逐个验证。4.2 第一步把现象描述清楚而不是把代码丢过去这一步和很多人的直觉相反。遇到 bug很多人的第一反应是把报错和相关代码丢给 AI说“帮我看看哪里错了”。这么问AI 通常会给你一堆泛泛的可能性没什么用。我的做法是先描述现象再给代码。现象描述要包含四个要素什么操作触发的、期望结果是什么、实际结果是什么、能不能稳定复现。现象用户点击“导出报表”按钮后偶尔会导出空文件。期望是导出当前筛选条件下的所有数据。实际是文件能下载但内容是空的。大约十次里出现两三次没有明显规律。相关代码在下面三个文件里。把这四个要素说清楚AI 的排查方向会精准很多。因为它知道这是“偶发”问题就会往并发、缓存、异步这些方向想而不是傻乎乎地检查语法。4.3 第二步让 AI 列出假设而不是直接给答案描述完现象后我会明确要求请基于以上现象和代码列出 3 到 5 个可能导致这个问题的原因假设按可能性从高到低排序。每个假设请说明为什么它会导致这个现象、如何验证它。这个提问方式的关键在于要假设、要排序、要验证方法。AI 给出的假设不一定对但它的排序往往有参考价值。而且“如何验证”这一条直接给了我下一步的动作。拿上面那个导出空文件的例子AI 给出的假设里排第一的是“异步导出任务在数据还没查完时就返回了”排第二的是“筛选条件在并发场景下被覆盖”。这两个假设都指向并发问题验证方法也很具体加时间戳日志、检查任务状态流转。4.4 第三步逐个验证用结果反哺下一轮拿到假设列表后我按顺序验证。验证的过程本身也是给 AI 提供新信息的过程。比如验证第一个假设时发现日志显示任务确实提前返回了我就把这个发现告诉 AI验证了第一个假设日志显示任务在查询开始后 200ms 就返回了但数据库查询通常需要 1-2 秒。这说明确实是提前返回。请基于这个发现帮我看看代码里哪个环节可能导致提前返回。这种“验证-反馈-再问”的循环比一次性问“哪里错了”高效得多。因为每一轮对话都带着新的、确定的信息AI 的推理会越来越聚焦。4.5 排查法的避坑要点这个流程有两个地方容易走偏。一是假设太多。让 AI 列 10 个假设你会陷入选择困难。我的经验是 3 到 5 个刚好超过 5 个说明现象描述得不够清楚应该回去补充信息。二是跳过验证直接改代码。看到 AI 说“可能是缓存问题”就跑去加缓存清理逻辑这是大忌。遗留代码的每一处修改都可能引入新问题没有验证过的假设不要动代码。排查阶段我的动作AI 的角色产出描述现象四要素说清楚接收信息明确的排查范围列假设要求排序 验证方法提出假设3-5 个待验证方向逐个验证加日志、复现、观察基于新信息再推理锁定根因修复最小改动辅助写修复代码修复 回归测试5. 三个流程怎么组合成日常习惯5.1 按任务类型选流程这三个流程不是孤立的它们对应三类不同的任务。我日常的判断逻辑很简单拿到一个不熟的项目或模块走三遍阅读法要写一个新功能或新接口走契约先行法要修一个说不清原因的 bug走假设-验证法。大部分开发任务都能归到这三类里。归不进去的通常是那种“既要读代码又要写代码”的混合任务那就拆开先读后写别混在一起。5.2 每个流程的“最小可用版本”如果你觉得上面写的步骤太多记不住那我给你每个流程的最小版本阅读法最小版先要地图再走一条链路。就这两步已经能覆盖 80% 的场景。契约法最小版先要签名再要实现。中间那步测试可以省但签名不能省。排查法最小版先描述现象再要假设。别一上来就丢代码。这三个最小版本我建议你先用一周。用顺了再往上加细节比一上来就全套照搬要靠谱。5.3 关于工具选择的一点实话经常有人问我用什么工具。说实话这三个流程对工具的要求极低——任何能对话、能贴代码的 AI 助手都能跑。我用过好几个不同的助手流程本身几乎不用改。真正影响效果的不是模型多强而是你给它的上下文质量。同样是问“这段代码干嘛的”你贴 50 行相关代码和贴 5000 行整个项目效果天差地别。同样是描述 bug你说“报错了”和你说清楚四要素AI 给出的假设质量完全不是一个级别。所以与其纠结换哪个工具不如先把这三个流程跑熟。工具会一直变但“先对齐再执行”“先假设再验证”这些思路是不会过时的。5.4 我踩过的最大一个坑最后说个我自己的教训。刚开始用 AI 编程那会儿我特别迷信“一次问清楚”总想用一段超长的提示词把所有要求都塞进去指望 AI 一次给出完美答案。结果就是每次对话都很长但每次都要返工。后来我想明白了AI 编程的本质是协作不是许愿。协作就意味着有来有回有确认有修正。这三个流程之所以好用恰恰是因为它们把一次大对话拆成了几次小对话每次只解决一个明确的问题。契约先行是先对齐规格再写代码假设验证是先定位原因再动手改三遍阅读是先建框架再填细节——本质上都是同一个道理。把大问题拆小把模糊变具体把猜测变验证。这三句话比任何提示词模板都值钱。
返回列表