ARTICLE DETAIL

资讯详情

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

工程师级 AI 编程工作流:从任务拆解到测试验证的完整实践指南

工程师级 AI 编程工作流:从任务拆解到测试验证的完整实践指南 1. AI 编程现状为什么“拿到提示词就生成”是最容易踩的坑先说一个现象很多开发者拿到 Cursor、Copilot 这类 AI 编程工具后第一反应是把需求直接甩给 AI比如“帮我写一个用户登录模块”然后等着 AI 输出几百行代码最后复制进项目里跑一下。能跑就皆大欢喜跑不起来就开始反复修改提示词或者干脆自己上手改。这种“提示词驱动开发”的方式在小脚本、一次性工具里确实能省时间但一旦进入真实项目立刻会遇到几个问题AI 生成的代码没有结合现有项目结构往往自成一套。它不知道你的业务约束、命名规范、错误处理风格。没有拆解需求代码经常把多个问题混到一起。没有配套测试回归时根本没有保障。大段代码一旦生成人工审查成本极高稍不留神就会引入隐性问题。Matt Pocock 在他的 AI 编程速成课里反复强调一个观点不要把 AI 当成代码生成器而要把它当成一位“能力很强但没有项目背景的新同事”。你要给它上下文、给它任务边界、让它先做计划再写代码最后还要测试和复盘。这其实就是工程师级 AI 编程工作流的核心——AI 辅助开发而不是 AI 替代开发。本文会完整拆解这套工作流从工具选择、提示词设计、任务拆解到编码、测试、审查最后用一个真实小项目演示全流程。2. 环境准备与工具选择在开始之前先把环境和工具选型说清楚。这里的版本信息只是一个参考实际使用时要根据你自己的项目情况调整。2.1 AI 编程工具的三种类型现在市面上的 AI 编程工具大致分三类类型代表工具特点适合场景IDE 内联补全GitHub Copilot、Cursor Tab在你写代码时给出补全建议交互成本低日常编码、写样板代码、补全函数对话式 AgentCursor Chat、Claude Code、Windsurf可以结合整个仓库上下文支持多文件修改、命令执行跨文件重构、功能模块开发、测试生成云端 AI 开发环境Github Codespaces Copilot、Cursor 云端云端运行不依赖本地环境团队协作、统一环境、教学演示本文的实战演示更偏向“对话式 Agent IDE 内联”组合这是目前效率比较高的方案。2.2 建议环境为了演示方便我以一个 Node.js TypeScript 项目为例。你本机需要准备Node.js 18 以上示例里面用到了 Node 的 fetch后续代码也会基于这个版本。npm 或 pnpm。Git。VS Code 或者 Cursor。Claude Code 或 Cursor 或其他支持 Agent 模式的工具。初始化一个演示项目mkdir ai-programming-workflow cd ai-programming-workflow npm init -y npm install typescript ts-node types/node vitest express npx tsc --init这里说明一下Vitest 是用来做单元测试的Express 是演示用的 Web 框架。如果你用其他技术栈替换对应依赖即可工作流思路完全一样。3. 工程师级 AI 编程工作流五步法下面进入本文最核心的部分。不管项目大小我都建议按这五个步骤来组织 AI 协作流程。3.1 第一步明确任务写清用户故事AI 编程最常见的失败原因不是你提示词写得不好而是任务本身就模糊。很多开发者会写“帮我做一个 TODO 应用”。这个描述对 AI 来说几乎等于没有信息量。AI 只能用自己的“世界观”去猜猜测需求边界、猜测功能细节、猜测数据存储方式。正确的做法是像给新同事布置任务一样把用户故事写清楚。一个标准任务描述包括角色谁在用这个功能行为他要做什么收益做完后得到什么结果验收标准什么情况下算完成边界明确不做哪些事。举例作为用户我想要创建一个待办事项以便记录我需要完成的任务。 验收标准 1. 用户可以通过 POST /api/todos 创建待办事项。 2. 请求体包含 title必填和 completed可选默认 false。 3. 创建成功后返回 201 状态码和待办对象。 4. 如果 title 为空返回 400 和错误信息。 5. 数据先保存在内存中不接数据库。把这段描述给 AI它生成的代码大概率比“帮我写个 TODO”靠谱得多。3.2 第二步让 AI 先做实现计划不要直接写代码这一步是很多人忽略的关键动作。拿到一个稍复杂的需求后不要向 AI 说“开始写代码”而是让它先输出实现计划。让 AI 先列出项目当前的结构是什么样的。需要新增或修改哪些文件。每个文件的职责是什么。需要哪些接口、类型、依赖。实现顺序是什么。潜在风险点在哪里。比如我们可以继续用待办任务的描述向 AI 发送这个提示下面是一个待办事项功能的需求描述 需求描述 请不要直接写代码。先阅读项目结构然后输出一份实现计划。计划需要包含 1. 需要新增/修改的文件路径列表。 2. 每个文件的核心职责。 3. API 接口定义。 4. 数据模型定义。 5. 实现顺序。 6. 这个功能可能存在的边界情况和风险点。这一步的价值在于在写代码之前发现问题比如技术方案冲突、数据模型不合理。让后续生成的代码更连贯因为 AI 自己也“看过”计划了。给你一次人工审查机会从设计层面纠正方向。如果 AI 的计划里有你不认可的地方此时是纠正的最佳时机。改动计划比修改代码成本低得多。3.3 第三步把计划拆成小任务逐个实现拿到计划后不要让它一口气把所有代码写完而是按照计划拆成多个小任务逐个执行。原因很简单任务越小AI 的上下文越集中生成的代码质量越高出错后排查范围也越小。以刚才的待办事项功能为例可以拆成下面几个任务定义 Todo 类型和内存存储仓库。实现 Express 路由支持创建待办事项。增加输入校验。编写单元测试。手动验证接口。每个任务都给 AI 单独发起一次对话并把上一步的产物作为上下文。这种“小步快跑”模式和传统结对编程很像每一步都有人盯着出问题能及时回退。3.4 第四步测试先行用测试约束行为Matt Pocock 工作流里特别强调测试。我们可以让 AI 先写测试再写实现也可以并行生成。先写测试的思路是测试天然承载了需求验收标准AI 在写测试时会比写实现更准确地理解“什么算完成”。而且测试跑通与否是全自动的验收信号。你可以这样让 AI 写测试基于下面的需求描述和接口定义使用 Vitest 编写测试用例。 测试文件放在 src/__tests__/todo.test.ts。 覆盖以下场景 1. 创建待办事项成功。 2. title 缺失时返回 400。 3. created_at 字段自动生成。 4. completed 默认值是 false。然后运行测试npx vitest run你会发现在测试驱动下AI 的代码往往更严谨因为测试对行为有硬性约束。3.5 第五步代码审查与迭代AI 生成代码后不要直接相信它。你可以把 AI 当成初级工程师自己做代码审查。让 AI 自己先审查一遍请对以下代码做一次 code review重点检查 1. 有没有空指针或未定义变量。 2. 有没有数组越界。 3. 有没有重复代码。 4. 有没有安全问题SQL 注入、XSS、越权。 5. 有没有不合理的数据结构使用。 6. 是否有更好的写法不改变对外行为。然后你再看 AI 提出的建议决定是否采纳。另外如果测试失败可以这样让 AI 修复项目在运行 npx vitest run 时出现以下错误 粘贴错误信息 请定位问题原因并修复。注意不要破坏已经通过的测试。这个循环可以重复多轮直到所有测试通过、代码符合预期。4. 核心技能提示词的结构化设计很多人以为提示词就是“说一句像人话的话”但在真实项目里提示词需要一定的结构化设计。这里介绍一套通用模板适用于大多数 AI 编程工具。4.1 上下文信息【项目背景】 这是一个基于 Express TypeScript 的待办事项 API 项目。 技术栈Node.js 18、Express 4、TypeScript 5。 测试框架Vitest。 数据存储目前使用内存存储。好的上下文能让 AI 的输出更符合现实约束。4.2 任务描述【任务】 实现创建待办事项的 API 路由。4.3 约束条件【约束】 1. 使用 TypeScript 编写。 2. 使用 Express Router不要把所有路由写在 app.ts 里。 3. 输入校验放在独立的 middleware 中。 4. 不要使用数据库先使用内存数组。 5. 错误消息使用英文。4.4 成功标准【成功标准】 1. 所有测试通过。 2. 返回格式符合项目现有 API 规范。 3. 代码通过 eslint 检查。这套模板不是唯一的但它的核心思想值得借鉴上下文、任务、约束、成功标准四个要素缺一不可。4.5 错误请求文档结构在实战过程中如果你发现 AI 经常偏离方向可以试着让它先输出“问题-方案-影响”结构。比如如果你需要修改多个文件请先按下面的结构输出方案 - 问题当前代码存在什么问题 - 方案你打算怎么改 - 影响这个修改会影响哪些现有功能 - 测试如何验证修改没有引入回归这种结构可以强迫 AI 在动手前想清楚而不是盲目输出代码。5. 完整实战用工作流构建一个待办事项 API前面讲的都是方法论接下来用一个真实的小项目把整个工作流串起来。我会演示提示词写法、AI 输出示例、测试方式以及如何迭代修正。5.1 项目初始化首先创建项目结构mkdir ai-programming-workflow cd ai-programming-workflow npm init -y npm install express cors npm install -D typescript types/express types/cors types/node vitest tsx npx tsc --init修改 tsconfig.json 中几个关键配置{ compilerOptions: { target: ES2022, module: commonjs, outDir: ./dist, rootDir: ./src, strict: true, esModuleInterop: true, skipLibCheck: true, forceConsistentCasingInFileNames: true }, include: [src/**/*], exclude: [node_modules, dist] }创建基础文件结构mkdir -p src/routes src/controllers src/repositories src/types src/middleware src/__tests__5.2 向 AI 下达任务现在把需求描述发给 AI。这是一个 Express TypeScript 项目目录结构已经初始化。 下面要实现一个“创建待办事项”功能。 需求描述 作为用户我想要创建一个待办事项以便记录我需要完成的任务。 验收标准 1. 用户可以通过 POST /api/todos 创建待办事项。 2. 请求体包含 title必填和 completed可选默认 false。 3. 创建成功后返回 201 状态码和待办对象。 4. 如果 title 为空返回 400 和错误信息。 5. 数据先保存在内存中不接数据库。 约束 1. 使用 TypeScript。 2. 使用 Express Router不要把所有逻辑写在 app.ts。 3. 数据类型定义放在 src/types 下。 4. 内存存储逻辑放在 src/repositories 下。 5. 路由层只处理 HTTP 请求和响应业务逻辑放到 controller 中。 6. 错误消息使用英文。 请不要直接写全部代码。先阅读项目目录结构输出一份实现计划包括 1. 需要新增/修改的文件路径。 2. 每个文件的职责。 3. 接口定义和数据模型。 4. 实现顺序。 5. 潜在风险点。AI 通常会返回类似下面这样的实现计划实现计划 1. src/types/todo.ts - 定义 Todo 接口和 CreateTodoInput 接口 2. src/repositories/todoRepository.ts - 内存存储提供 create/findAll 方法 3. src/controllers/todoController.ts - 业务逻辑调用 repository 4. src/routes/todo.ts - 定义 POST /api/todos 路由 5. src/middleware/validateTodo.ts - 输入校验 6. src/app.ts - 注册路由计划合理可以按文件逐个实现。5.3 定义类型和数据模型先让 AI 实现类型定义按照上面的计划现在实现第 1 步src/types/todo.ts。 要求 1. Todo 接口包含 id、title、completed、createdAt。 2. id 使用自增数字。 3. createdAt 使用 Date 类型。 4. 导出一个 CreateTodoInput 类型包含 title 和可选的 completed。期望生成的代码大致如下// 文件路径src/types/todo.ts export interface Todo { id: number; title: string; completed: boolean; createdAt: Date; } export interface CreateTodoInput { title: string; completed?: boolean; }这里需要关注AI 是否正确定义了 createdAt是否使用了可选属性。如果有偏差在这个阶段就要指出。5.4 实现内存仓库继续实现第 2 步src/repositories/todoRepository.ts。 要求 1. 使用一个内存数组存储 Todo。 2. 提供 create(input: CreateTodoInput): Todo 方法。 3. 提供 findAll(): Todo[] 方法。 4. create 方法中自动生成 id 和 createdAt。 5. id 从 1 开始自增。期望代码// 文件路径src/repositories/todoRepository.ts import { Todo, CreateTodoInput } from ../types/todo; let todos: Todo[] []; let nextId 1; export function createTodo(input: CreateTodoInput): Todo { const todo: Todo { id: nextId, title: input.title, completed: input.completed ?? false, createdAt: new Date(), }; nextId 1; todos.push(todo); return todo; } export function findAllTodos(): Todo[] { return todos; } export function clearTodos(): void { todos []; nextId 1; }注意这里我加了一个clearTodos方法后面写测试时需要重置内存状态。如果 AI 没生成你可以提醒它。5.5 校验中间件实现第 3 步src/middleware/validateTodo.ts。 要求 1. 校验请求体中的 title 字段。 2. title 必须是字符串不能为空。 3. 如果 title 为空返回 400返回体格式为 { error: string }。 4. 如果校验通过调用 next()。期望代码// 文件路径src/middleware/validateTodo.ts import { Request, Response, NextFunction } from express; export function validateTodo(req: Request, res: Response, next: NextFunction) { const { title } req.body ?? {}; if (typeof title ! string || title.trim().length 0) { return res.status(400).json({ error: title is required and must be a non-empty string, }); } next(); }这里有一个容易踩坑的地方如果请求体没有传req.body可能是 undefined。AI 如果不注意这一点代码可能直接报错。这也是我们在审查时要重点看的。5.6 控制器与路由接下来是两个配合的步骤实现第 4 步src/controllers/todoController.ts。 实现第 5 步src/routes/todo.ts。期望代码// 文件路径src/controllers/todoController.ts import { Request, Response } from express; import { createTodo, findAllTodos } from ../repositories/todoRepository; export function createTodoHandler(req: Request, res: Response) { const todo createTodo(req.body); return res.status(201).json(todo); } export function listTodosHandler(req: Request, res: Response) { const todos findAllTodos(); return res.status(200).json(todos); }// 文件路径src/routes/todo.ts import { Router } from express; import { createTodoHandler, listTodosHandler } from ../controllers/todoController; import { validateTodo } from ../middleware/validateTodo; const router Router(); router.post(/, validateTodo, createTodoHandler); router.get(/, listTodosHandler); export default router;注意这里我额外加了GET /api/todos路由用来查看列表。AI 如果没加你可以提示“再增加一个查询全部待办事项的接口”。5.7 组装应用最后把路由挂载到应用入口实现第 6 步src/app.ts。 要求 1. 创建 Express 应用。 2. 使用 express.json() 中间件。 3. 使用 cors() 中间件。 4. 将 todo 路由挂载到 /api/todos。 5. 导出 app 实例方便测试。期望代码// 文件路径src/app.ts import express from express; import cors from cors; import todoRouter from ./routes/todo; const app express(); app.use(cors()); app.use(express.json()); app.use(/api/todos, todoRouter); export default app;再加一个启动入口新增 src/server.ts用于启动服务端口使用 3000。// 文件路径src/server.ts import app from ./app; const PORT process.env.PORT ?? 3000; app.listen(PORT, () { console.log(Server is running on http://localhost:${PORT}); });5.8 测试驱动验证到这里基础功能已经写完。接下来是关键一步让 AI 补测试。项目使用 Vitest。请编写测试文件 src/__tests__/todo.test.ts。 测试要求 1. 使用 supertest 调用 Express 应用。 2. 覆盖以下场景 - 创建待办事项成功返回 201title 正确。 - 创建时如果不传 completed默认值为 false。 - title 为空字符串时返回 400。 - 缺少 title 字段时返回 400。 - GET /api/todos 返回已创建的待办列表。 3. 每个测试开始前清空内存仓库。 如果项目缺少 supertest请给我安装命令。先安装 supertestnpm install -D supertest types/supertest然后让 AI 生成测试代码期望效果类似// 文件路径src/__tests__/todo.test.ts import request from supertest; import { describe, it, expect, beforeEach } from vitest; import app from ../app; import { clearTodos } from ../repositories/todoRepository; beforeEach(() { clearTodos(); }); describe(POST /api/todos, () { it(should create a todo successfully, async () { const res await request(app) .post(/api/todos) .send({ title: Write AI workflow article }); expect(res.status).toBe(201); expect(res.body.title).toBe(Write AI workflow article); expect(res.body.completed).toBe(false); expect(res.body).toHaveProperty(id); expect(res.body).toHaveProperty(createdAt); }); it(should default completed to false when not provided, async () { const res await request(app) .post(/api/todos) .send({ title: Buy milk }); expect(res.status).toBe(201); expect(res.body.completed).toBe(false); }); it(should return 400 when title is empty string, async () { const res await request(app) .post(/api/todos) .send({ title: }); expect(res.status).toBe(400); }); it(should return 400 when title is missing, async () { const res await request(app) .post(/api/todos) .send({}); expect(res.status).toBe(400); }); }); describe(GET /api/todos, () { it(should return created todos, async () { await request(app).post(/api/todos).send({ title: Task 1 }); await request(app).post(/api/todos).send({ title: Task 2 }); const res await request(app).get(/api/todos); expect(res.status).toBe(200); expect(res.body.length).toBe(2); expect(res.body[0].title).toBe(Task 1); }); });运行测试npx vitest run如果测试全部通过说明这个功能已经满足验收标准。如果测试失败把失败日志贴给 AI让它定位修复。5.9 手动验证测试通过后还可以手动启动服务验证npx tsx src/server.ts然后打开另一个终端curl -X POST http://localhost:3000/api/todos \ -H Content-Type: application/json \ -d {title:Learn AI workflow}预期输出{id:1,title:Learn AI workflow,completed:false,createdAt:2025-01-20T10:30:00.000Z}再请求 GET 接口curl http://localhost:3000/api/todos预期输出一个包含刚才创建的待办事项的数组。到这里一个最简单的 AI 辅助功能开发闭环已经跑通需求 → 计划 → 编码 → 测试 → 验证。6. 常见问题与排查思路在实际使用 AI 编程工作流时下面这些问题是出现频率最高的。我整理成表格方便查阅。问题现象常见原因解决思路AI 生成的代码不符合项目风格没有提供足够的项目上下文把项目结构、代码规范、现有文件示例放进提示词AI 一次生成大量代码错误难排查任务拆分粒度过大强制 AI 按计划分步实现每次只做一个小功能测试覆盖不到关键逻辑提示词中缺少验收标准和测试要求在需求描述中明确列出需要测试的场景AI 修改一个文件导致其他模块报错修改前没有分析影响范围要求 AI 先输出“问题-方案-影响”再动手AI 反复生成相同错误代码没有给 AI 足够的失败反馈把报错信息、测试结果、预期行为明确写出来测试随机失败数据互相污染在测试的 beforeEach 中重置内存数据生成代码使用了旧 API 或废弃方法依赖版本信息缺失在提示词中明确依赖版本和关键 API索引越界或空指针数据边界校验不够在 code review 环节让 AI 重点检查边界条件提示词任务太宏大AI 输出混乱缺少拆解先让 AI 出计划再按计划逐步执行AI 生成的代码“能用但看不懂”没有要求解释和注释要求 AI 在关键逻辑旁加注释并给出简短说明这里要提醒一点AI 编程最常见的错误不是“代码不能跑”而是“代码能跑但没有正确覆盖业务约束”。比如上面的示例里如果 AI 忘记校验 title测试很容易发现但如果 AI 在创建时间时使用的是服务器本地时间而业务要求使用 UTC 时间这种问题必须靠审查和明确约束才能发现。7. 最佳实践与工程建议AI 编程不是玄学它是一套可以不断优化的工程流程。下面这些建议来自实践过程中踩坑后的复盘。7.1 建立团队级提示词规范不要每个开发者各写各的提示词。建议把常用的上下文模板、需求描述模板、代码审核模板沉淀到团队文档里。这样 AI 的输出风格和准确度都会更加稳定。一个简单的模板可以包含# 项目背景 - 技术栈 - 目录结构 - 现有工具链 # 需求描述 - 角色 - 行为 - 收益 - 验收标准 - 技术约束 # 执行要求 - 先出计划再写代码。 - 每次只完成一个小任务。 - 提供测试用例。 - 自查安全与边界条件。7.2 把测试当作验收线在 AI 编程工作流中测试的意义不只是保障质量它还是你与 AI 之间的“验收协议”。建议在给 AI 派任务时明确写出测试文件路径。需要覆盖的场景。测试通过命令。这样无论 AI 怎么改代码只要测试跑通你就知道功能没有被破坏。7.3 永远保留代码审查环节AI 生成的代码必须经过至少一轮 code review包括 AI 自审和人工抽审。重点检查输入校验是否完整。错误处理是否合理。是否有不必要的全局状态。敏感信息是否被硬编码。是否有明显性能问题比如循环里查数据库。是否遵循项目的接口约定。7.4 使用 git 分支管理迭代过程在 AI 协助下进行较大改动时建议创建一个独立分支每一步都及时提交。git checkout -b feature/ai-todo-api git add . git commit -m AI: implement todo repository这样做的好处是如果某一步 AI 把代码改乱了可以快速回退到上一个稳定提交而不是手动删除大段代码。7.5 给 AI 足够的“失败信息”当 AI 生成的代码运行失败时不要让 AI 盲猜。正确的做法是直接把完整的错误堆栈、测试输出、复现步骤粘贴到对话里。AI 看到真实错误信息时的修复成功率远高于你只描述“运行报错了”。7.6 警惕 AI 生成代码中的隐蔽副作用AI 在“修正”问题的时候有时候会顺手改掉一些无关代码导致回归。建议你在 prompt 里明确约束修复问题时最小化修改范围。不要重构无关代码。这个约束非常重要能避免很多莫名其妙的回归问题。7.7 从“提示词工程”走向“上下文工程”提示词工程的本质是用文字引导 AI 完成特定任务。但在大型项目里提示词只是一部分更重要的是上下文。现代 AI 编程工具里面有很多方式可以提供项目上下文把关键文件内容粘到对话中。使用 符号引用文件。让 AI 先阅读 README 或项目文档。在对话开始前把项目结构展示给 AI。上下文越充分AI 生成代码的准确度就越高。8. 总结与下一步学习方向这篇教程从“为什么不要瞎用 AI 写代码”出发整理了一套工程师级的 AI 编程工作流明确任务写清用户故事和验收标准。让 AI 先出实现计划不要直接写代码。把计划拆成小任务逐一实现。用测试约束行为把测试当作验收线。保持代码审查和迭代循环。整个流程的核心不是“让 AI 写更多代码”而是“让 AI 减少你的重复劳动同时不降低代码质量”。这要求你比 AI 更清楚自己的需求、约束和期望结果。接下来你可以继续深入几个方向研究你自己常用的 AI 编程工具的高级功能比如 Cursor 的 Rules、Claude Code 的 CLAUDE.md 项目记忆文件。尝试把这套工作流应用到更大的模块开发中比如用户认证、订单流程、权限体系。学习如何为 AI 提供更精准的项目索引让它在大型仓库里也能准确定位相关文件。探索 AI 在代码重构、技术债清理、依赖升级等场景中的适用边界。AI 编程工具每天都在迭代但无论工具怎么变“明确目标 → 制定计划 → 小步实现 → 测试验证 → 审查迭代”这个工程化流程不会过时。希望这篇文章能帮你把 AI 从一个“偶尔好用的大模型对话框”变成一位真正可靠的开发育人。如果你在实际操作中遇到其他问题欢迎在评论区留言交流。下一篇可以继续聊聊如何用类似工作流做全栈项目或者深入讲某个 AI 编程工具的配置细节。
返回列表