2026年7月17日/ AI Application Notes

AI 编程不是直接生成代码:需求、实现、测试、评审的闭环

把 AI 放进需求澄清、实现、验证和评审之间。代码生成只是中间步骤,验收闭环才决定结果能不能交付。

AI CodingEngineering WorkflowTestingCode ReviewSPEC

AI 编程最容易让人误解的一点,是把“模型写出了代码”当成“功能已经完成”。

它当然能把实现速度拉得很高,但交付速度不只取决于敲代码。需求没有边界,生成得越快,返工越快;测试没跑,补丁再漂亮也不知道有没有破坏别处;评审只看语法,风险会被藏在看似合理的改动里。

我现在把 AI 放在一个很普通的工程闭环中使用:读懂 -> 定范围 -> 实现 -> 验证 -> 评审 -> 记录。它不是替代开发流程,而是让每一环的反馈更快。

先把“完成”写下来

开始前最重要的不是让 AI 产出代码,而是明确这次到底要交付什么。一个可执行的任务至少要写清:

目标:用户最终能看到或使用什么变化?
范围:允许改哪些模块,不碰哪些模块?
事实:现有代码、接口、数据和约束是什么?
验收:测试、构建、页面或接口怎样证明它完成?
不做什么:哪些看似相关的重构、依赖升级或功能扩展不在这次内?

这不是为了写文档而写文档,而是给后面的每一个决定设边界。比如“给项目页补一段演示”与“重做整站视觉系统”看上去都涉及页面,但它们的改动量、风险和验证方式完全不同。

对 AI 来说,这也是最有价值的上下文。没有范围时,它往往会顺手换组件、调样式、改配置;有了范围,它才知道哪些地方不能碰。

第一步:先读,再让 AI 提建议

我不再一上来就说“帮我实现 X”。先读项目入口、依赖、路由、相关组件、现有测试和最近改动,至少回答四个问题:

  1. 当前功能从哪里进入,数据或状态在哪里流动?
  2. 项目已有的写法是什么,能否沿用?
  3. 这次改动会影响哪些页面、接口或持久化数据?
  4. 现有项目用什么命令验证?

AI 在这个阶段最适合做的是归纳和追踪,而不是立刻写实现。例如让它列出某个页面用到的组件、找出一条请求的调用链、对比两个相似模块,或者解释一段陌生代码的边界。

这一步的输出应该是一份短计划,而不是 diff。计划里要有文件、影响范围、风险和验证命令。等这些能说清,才进入实现。

第二步:把任务拆成能验证的小块

一个大需求直接交给 AI,通常会得到一大段改动,之后很难判断哪里出了问题。我会按可验证的中间状态拆开:

1. 补齐数据结构或接口合同
2. 实现服务 / 组件中的一条主路径
3. 补异常与空状态
4. 加最小回归测试或手动验证路径
5. 构建、检查 diff,再看页面或接口

每一步的长度不用追求绝对小,但必须能独立回答“它现在对了吗”。例如 RAG 的“返回答案”不能只验证模型有没有输出,还要拆成检索是否有候选、引用是否能回指、低置信度是否拒答、会话是否正确写入。

拆小还有一个直接好处:当 AI 对上下文理解错了,错误会在第一两个步骤暴露,不会堆到最后才发现整个方向偏了。

第三步:让 AI 写实现,但把判断留在代码外

进入实现阶段后,我会把输入写得尽量接近真实任务,而不是只给一句功能描述:

目标:为现有接口补充引用字段。
范围:只改响应 DTO、组装逻辑和对应测试。
现状:引用片段已经在服务层可用,前端暂不改动。
限制:不改数据库迁移、不新增依赖、不改变旧字段语义。
验收:相关测试通过,序列化结果包含 citations,pnpm build / 项目构建通过。

这类输入比“加一个引用功能”更像工作中的任务单。它给了 AI 足够信息去写代码,同时把架构选择、数据边界和发布决定留给开发者。

我会特别盯住三类地方:

  • 默认值和空值:模型很容易假设数据总存在,真实接口必须处理空集合、超时、缺字段和旧数据。
  • 副作用:一次看似只读的调用,可能写缓存、发消息、更新状态或触发外部服务。
  • 兼容性:新增字段能否兼容旧客户端?异常会不会从可控状态变成 500?

AI 可以很快地补实现,但这些问题需要结合业务判断,不能只依赖它“看起来合理”的解释。

第四步:验证不是最后按一下构建按钮

我会把验证分成三层。

1. 结构验证

先让类型、编译或 schema 检查尽早暴露低级错误:导入不一致、字段拼错、前后端合同不匹配、MDX frontmatter 不合法。这类问题不值得留到人工测试才发现。

2. 行为验证

再跑最贴近改动的测试或手动路径。新加了一个响应字段,就验证正常、空结果和异常三种情况;改了一个页面,就至少看桌面和移动端,检查加载、空状态和文字是否溢出。

3. 集成验证

最后才是完整构建或端到端链路。这个顺序能让失败更容易定位:是实现本身错了,还是某个模块之间的合同断了。

在这个博客项目里,内容或页面改动后我会跑 pnpm build,它同时执行 Astro 检查和静态构建;再跑 git diff --check,排除空白字符和补丁格式问题。它们不是全部测试,但至少把“看起来已经改好”的主观判断变成了可重复的证据。

第五步:让 AI 做第二次阅读,而不是替你盖章

代码评审是 AI 很适合参与的一环。前提是把任务切换成“找风险”,不要让它重复说自己刚刚写了什么。

我通常会给它 diff 和明确的检查维度:

请按代码评审方式检查这个 diff。
优先找:行为回归、边界条件、安全或权限问题、并发问题、错误处理、测试缺口。
每条问题说明触发条件和影响;没有高风险问题时直接说明。
不要为了重构而重构。

AI 的评审不能代替真正的批准,但它很擅长做第一轮穷举:参数漏校验、null 分支、异常吞掉、返回字段没有同步、测试没有覆盖失败路径。这会让人工评审更集中在业务取舍和架构风险上。

第六步:把结果和未解决问题留下来

完成一次改动后,我会记录三件事:

  • 改了什么,影响了哪些路径。
  • 哪些验证已经通过,哪些因为环境或依赖没有跑。
  • 还有什么风险、下一步是什么。

这不是为了让记录变长。代码评审、换窗口、隔几周再回来排查时,最需要的就是这些信息。没有它,下一次又要重新猜当时为什么这么改。

对 AI 协作来说,记录还是下一轮上下文的一部分。它能看到上一轮的真实结论,而不是从一堆旧代码和模糊描述里重新推断意图。

我现在的最小闭环

不是每个小修复都需要一套重流程,但我至少会保留这个顺序:

读相关代码
  -> 写清范围和验收
  -> 做一个可验证的小改动
  -> 跑最小测试或页面路径
  -> 看 diff,做风险检查
  -> 记录结果和下一步

AI 让“读、写、查”都变快了,但它没有替我们承担需求是否正确、边界是否合理、验证是否充分的责任。真正可交付的不是一段生成的代码,而是一项范围清楚、验证过、能解释其取舍的改动。

把 AI 放进这个闭环里,我得到的不是更长的 prompt,而是更少的返工和更容易追踪的工程结果。

Brief

Generated code is an intermediate artifact. The deliverable is a verified change with clear scope, evidence and reviewable tradeoffs.

Use AI to accelerate reading, implementation and review, while retaining human ownership of scope, acceptance criteria and release decisions.

A tight loop is: understand, constrain, implement, verify, review and record the next step.