AI 编程最佳实践:如何写好 Prompt


引言

在 AI 编程时代,“如何与 AI 对话”正在成为一种关键技能。同样的需求,不同的描述方式可能导致天差地别的代码输出质量。Prompt Engineering(提示工程)不再只是 AI 研究者的课题,而是每一位使用 AI 编程工具的开发者都需要掌握的实践技能。

本文将系统地介绍 AI 编程场景下的 Prompt 编写技巧,帮助你在与 Claude Code、Cursor、Copilot 等工具的交互中获得更高质量的代码输出。

Prompt 编写的基本原则

具体胜于模糊

这是最重要的一条原则。模糊的 Prompt 会导致 AI 做出大量假设,而这些假设往往与你的预期不符。来看一个对比:

模糊的 Prompt

写一个登录功能

具体的 Prompt

请实现一个用户登录功能,要求如下:
- 使用 React + TypeScript
- 表单包含邮箱和密码两个字段
- 邮箱需要格式验证
- 密码长度不少于 8 位
- 登录成功后跳转到 /dashboard 路由
- 登录失败时在表单下方显示错误提示
- 使用 fetch API 调用后端 /api/auth/login 接口
- 后端返回 JWT token,存储到 localStorage

具体的 Prompt 让 AI 明确了技术栈、验证规则、交互行为和错误处理方式,生成的代码会精确得多。

提供充分的上下文

AI 在生成代码时,上下文信息至关重要。上下文包括:

  • 项目背景:这是什么类型的项目?目标用户是谁?
  • 技术栈:使用哪些框架、库和工具?版本是多少?
  • 代码规范:团队是否有特定的编码风格或约定?
  • 现有代码:项目中已经有哪些相关的模块或工具函数?

在实际操作中,如果你使用的是 Claude Code 或 Cursor,它们会自动分析项目上下文。但如果你使用的是 Chat 模式,就需要主动提供这些信息。

明确约束条件

告诉 AI 什么不能做,和告诉它要做什么同样重要。约束条件可以有效减少 AI 的”过度发挥”:

请实现一个文件上传组件,要求:
- 只支持图片文件(jpg, png, gif, webp)
- 单个文件不超过 5MB
- 最多同时上传 3 个文件
- 不要使用任何第三方上传库,只用原生 fetch
- 不要使用 class 组件,使用函数组件和 hooks

上下文管理策略

分层提供上下文

对于复杂的项目,建议将上下文信息分层组织:

第一层:项目级上下文(在项目开始时提供一次)

这是一个电商后台管理系统,技术栈如下:
- 前端:React 18 + TypeScript + Ant Design 5
- 状态管理:Zustand
- 路由:React Router 6
- API 请求:Axios,统一封装在 src/utils/request.ts
- 后端 API 基础地址:/api/v1
- 代码风格:ESLint + Prettier,2 空格缩进

第二层:模块级上下文(在具体功能开发时提供)

现在要实现商品管理模块。相关的数据模型:
- Product: { id, name, price, category, stock, status, images }
- 后端 API 已有:GET /products, POST /products, PUT /products/:id, DELETE /products/:id
- 权限要求:需要 admin 角色

第三层:任务级上下文(每个具体任务提供)

请在商品列表页面添加批量导入功能。用户可以上传 CSV 文件,
系统解析后批量创建商品。参考现有的 src/utils/csv-parser.ts 工具。

这种分层方式避免了每次都在 Prompt 中重复项目信息,同时确保 AI 拥有足够的上下文来生成准确的代码。

上下文窗口的取舍

AI 模型的上下文窗口是有限的。在使用 AI 编程工具时,要学会取舍:

  • 相关的文件:一定要包含。直接引用文件路径或粘贴关键代码。
  • 相关的依赖:说明使用的库及其版本,但不需要粘贴整个 node_modules。
  • 不相关的代码:省略。过多的无关信息会干扰 AI 的判断。

在 Claude Code 中,可以使用 @file 语法引用特定文件,工具会自动读取文件内容。在 Cursor 中,可以使用 @codebase 让 AI 搜索相关代码。

分步骤引导技巧

大任务拆分

将复杂的开发任务拆分为小的、可验证的步骤。每一步完成后验证结果,再进入下一步:

第一步:先创建数据库模型和迁移脚本
第二步:实现 API 路由和业务逻辑
第三步:编写 API 测试用例
第四步:实现前端页面和组件
第五步:前后端联调
第六步:UI 优化和错误处理完善

每一步的输出都可以独立验证,这样即使某一步的结果不理想,也只需要调整那一步的 Prompt,而不是从头开始。

渐进式细化

不要期望一步到位。先用一个简洁的 Prompt 生成基础版本,然后逐步细化:

第一轮

实现一个 React 任务列表组件,支持添加、删除、标记完成。

第二轮(审查后追加)

请给上一步的组件添加以下功能:
- 任务可以设置优先级(高、中、低)
- 支持按优先级排序
- 添加删除前的确认弹窗

第三轮(继续优化)

请优化性能:
- 使用 React.memo 避免不必要的重渲染
- 添加任务的拖拽排序功能
- 实现本地存储持久化

这种方式比一次性写出所有需求更容易获得高质量的输出,因为 AI 在每一轮都可以基于已有代码进行增量修改。

错误纠正策略

当 AI 生成的代码不符合预期时,不要简单地重写整个 Prompt。明确指出问题所在:

低效的做法

重新写一个任务列表(因为上次的不行)

高效的做法

上一步生成的代码有两个问题:
1. 删除任务后列表没有更新 — 可能是状态更新逻辑有 bug
2. 添加任务时没有验证空标题 — 需要添加非空校验

请修复这两个问题,保留其他部分不变。

明确的问题描述让 AI 能够精确地定位和修复问题,而不是盲目地重新生成。

高级技巧

角色设定

给 AI 设定一个角色,可以让它生成更专业的代码:

你是一位有 10 年经验的高级前端工程师,擅长 React 性能优化和架构设计。
请以你审查团队 PR 的标准来生成代码,注重代码质量、可维护性和性能。

这种角色设定会让 AI 在代码组织、命名规范、错误处理等方面更加严谨。

示例驱动

提供期望的输入输出示例,比用自然语言描述规则更有效:

请实现一个格式化用户信息的函数:

输入:{ firstName: '张', lastName: '三', age: 28, email: 'zhangsan@example.com' }
输出:'张三 (28岁) - zhangsan@example.com'

输入:{ firstName: 'John', lastName: 'Doe', age: null, email: 'john@doe.com' }
输出:'John Doe - john@doe.com'

注意:
- 当 age 为 null 时省略年龄部分
- firstName + lastName 之间不加空格(中文姓名)

思维链引导

对于复杂的逻辑问题,引导 AI 展示推理过程:

请设计一个任务调度系统的数据模型。在给出方案前,请先分析:
1. 系统需要支持哪些操作?
2. 有哪些并发场景需要考虑?
3. 数据一致性的要求是什么?
4. 性能瓶颈可能在哪里?

先给出分析,再给出设计方案。

这种方式迫使 AI 在编码前先进行系统性的思考,通常能产出更合理的架构设计。

常见误区与避坑指南

误区一:Prompt 越长越好

过长的 Prompt 反而会稀释关键信息。保持 Prompt 的简洁和结构化,用要点列表代替大段文字,用代码片段代替自然语言描述。

误区二:一次生成完美代码

AI 编程是一个迭代过程。期望一次生成完美代码是不现实的。正确的做法是快速生成基础版本,然后通过多轮对话逐步完善。

误区三:忽视代码审查

AI 生成的代码”看起来正确”不等于”确实正确”。每一行 AI 生成的代码都应该经过审查,特别是涉及安全、性能和数据一致性的部分。

误区四:盲目复制粘贴

理解 AI 生成的每一行代码。如果你无法解释某段代码的功能,就不要将其纳入项目中。不理解代码就使用,迟早会导致难以排查的问题。

结语

Prompt Engineering 是 AI 编程时代的核心技能之一。好的 Prompt 不仅能让 AI 生成更高质量的代码,还能提升你的需求分析能力和系统设计思维。本质上,写好 Prompt 的过程就是理清思路、明确需求的过程——这本身就是优秀开发者应该具备的能力。

希望本文介绍的技巧能帮助你在 AI 编程的实践中获得更好的体验和更高的效率。记住,AI 是工具,而你是掌控工具的人。