很多人刚开始用 AI 写代码,会在两种极端之间摇摆:要么把 AI 当自动补全,产出碎片化、难以组合;要么把 AI 当全能外包,指令一大坨、代码一大坨,最后谁也说不清边界、也很难验收。本文讲的是一种朴素模式:比随口对话更可控、更可回溯,但又不需要引入复杂的流程框架;只要按固定节奏组织输入与验收,就能稳定地把 AI 的产出变成工程可用的交付物,并且为后续的 Vibe Coding 与 SDD(规范驱动开发)打下前置条件。
核心理念:扮演“架构师与代码评审”角色
将 AI 视为一个能力很强、执行力很高,但缺乏全局视角和责任闭环的初级程序员。你的角色是产品经理、系统架构师和代码评审者,负责下达精确指令、规划路径并严格验收;AI 更适合承担“实现与生成”,而不是替你承担“定义边界与做最终判断”。
第一步:需求澄清与任务拆解(最关键的一步)
-
书面化与结构化需求:
-
不只是写清楚,而是要写详尽。包括:
- 项目目标:一句话说清要做什么。
- 核心功能清单:逐条列出所有功能点(如:用户注册、登录、文章发布、文章列表展示)。
- 用户角色与权限:不同用户(如普通用户、管理员)能做什么。
- 非功能性需求:性能、安全性、易用性等方面的要求。
这一步最朴素、也最管用的补充动作是:让 AI 先复述理解并列出验收点,你确认无误后再进入实现,这样能在写代码前就把“误解”消掉一大半。
-
-
技术选型与架构确认:
- 在对话开始时明确告诉 AI 你的技术栈。
- 示例指令:“我们将开发一个博客系统。技术栈如下:后端使用 Python Flask 框架,数据库使用 SQLite,ORM 使用 SQLAlchemy,前端使用原生 HTML/CSS/JavaScript。请根据这个技术栈来提供代码。”
更稳的做法是顺手把“目录结构、测试框架、依赖管理方式、是否允许引入新库”也一起钉死,因为这些属于长期约束,一旦漂移,后续每一步都会被迫返工对齐。
第二步:分层实现与渐进式交付
“一层一层”实现是绝对正确的,这是控制复杂度的不二法门。以下是更细致的操作:
-
数据库设计:
- 指令:“根据上述博客系统的需求,请设计数据库表结构。请为每个表列出字段名、类型、主键、外键和必要的索引,并用 Markdown 表格形式输出。”
- 验收:仔细检查表关系是否合理,字段是否完整。可以追问:“请为
User表和Post表给出示例数据。”
-
数据访问层:
- 指令:“现在,请基于上面设计的数据库,使用 SQLAlchemy 定义这些表的 Model 类。”
- 接着:“请为这些 Model 编写基本的 CRUD 操作的 DAO 类。”
朴素但很关键的验收点是:DAO 的返回约定与错误约定要统一,比如“查不到返回 None 还是抛异常”“唯一键冲突怎么表达”,否则 Service/API 层会被迫写出多套处理逻辑,最终把一致性拖垮。
-
业务逻辑层:
- 指令:“现在,我们需要实现业务逻辑。请创建
BlogService类,它依赖于上面创建的 DAO 类,并提供以下方法:create_user(username, password),verify_login(username, password),create_post(title, content, author_id)等。”
- 指令:“现在,我们需要实现业务逻辑。请创建
-
API/控制层:
- 指令:“接下来,请使用 Flask 创建 RESTful API 端点。请为
/api/posts(GET 获取列表,POST 创建新文章) 和/api/posts/<id>(GET 获取详情) 编写路由函数,并调用之前定义的BlogService。”
- 指令:“接下来,请使用 Flask 创建 RESTful API 端点。请为
-
前端界面:
- 指令:“现在,请创建一个简单的 HTML 页面。它需要包含一个文章列表,并有一个表单可以提交新文章。使用 JavaScript 的
fetchAPI 与后端刚才定义的 Flask API 进行交互。”
- 指令:“现在,请创建一个简单的 HTML 页面。它需要包含一个文章列表,并有一个表单可以提交新文章。使用 JavaScript 的
关键技巧:在每一步生成代码后,要求 AI 生成该部分的代码摘要或说明。这不是为了“讲道理”,而是为了让你能更快完成评审:它的摘要越贴近你定义的边界,越说明实现没有跑偏;它的摘要越含糊,越说明你需要立刻把约束补清楚,避免下一层继续叠加误差。
第三步:测试驱动与持续迭代
测试用例是“前置条件”,这一点非常深刻:当 AI 产出速度很快时,唯一能把质量拉回可控区间的,就是让“验收标准”变成可运行的东西,而不是靠人脑记忆。
-
为每一层生成单元测试:
- 在生成 DAO、Service、API 代码后,立即要求 AI 为其编写单元测试。
- 指令:“请为上面生成的
BlogService类编写单元测试,覆盖成功和失败的情况。” - 价值:测试用例是你验证 AI 代码逻辑是否正确的“标尺”。当后续修改代码时,运行测试能立刻知道是否引入了新问题。
-
边界 case 与异常处理:
- AI 常常忽略边界情况。你需要主动要求。
- 指令:“请考虑各种异常情况,比如用户注册时用户名已存在、登录密码错误、查询的文章不存在等,并在代码中添加相应的异常处理。同时,为这些异常情况补充测试用例。”
如果你使用的是 unittest,建议明确要求它输出 unittest 风格的用例,并且配合 VS Code 的 Testing 面板完成“发现—单测运行—单测调试—回归全量”的闭环,这样测试就不再是“写了放那儿”,而是每次改动都能顺手按一下的常规动作。
第四步:会话管理与上下文维护
这是保证 AI 不出错的核心:你要做的不是“让它记得更多”,而是让关键事实不依赖对话记忆,从而减少漂移与自相矛盾。
-
单一会话,单一项目:
- 为一个独立项目开启一个新对话。不要在同一个会话中混杂多个不相关的需求,否则 AI 上下文会混乱。
-
主动提供上下文:
- 当会话很长时,AI 可能会“忘记”之前的设计。在提出新要求时,可以附上关键代码片段的引用。
- 指令:“回顾我们之前定义的
Post模型,它有一个title字段。现在,请在前端的文章列表页面中显示这个title。”
-
果断修正与重新生成:
- 一旦发现 AI 生成的代码有错误,或者你改变了设计,不要试图在错误的基础上手动修改。正确的做法是:
- 指令:“我发现在
User模型里缺少email字段。这是最新的完整需求:[粘贴更新后的需求]。请根据最新需求,重新生成User模型的 SQLAlchemy 定义。” - 这样能让 AI 的上下文回到正确轨道上。
-
版本化思维:
- 对于关键模块(如数据库模型、核心 API),当 AI 生成一个令你满意的版本后,你可以说:“请记住
Post模型的这个最终版本,我们后续的对话都将基于这个版本。” 这相当于进行了一次“代码提交”。
- 对于关键模块(如数据库模型、核心 API),当 AI 生成一个令你满意的版本后,你可以说:“请记住
第五步:代码整合与调试
-
亲手运行与调试:
- AI 生成的代码绝非完美。你必须将代码在本地环境中运行起来。
- 遇到错误时,将完整的错误信息日志直接复制给 AI。
- 指令:“我将你生成的 Flask 应用运行起来了,但在调用
/api/postsAPI 时出现了 500 错误。以下是完整的错误堆栈信息:[粘贴错误日志]。请分析并修复这个问题。”
为了避免它“修一处改一片”,你可以加两条朴素约束来强制最小修复:
- “优先给出最小 diff,只改与错误直接相关的文件与逻辑。”
- “修复后必须补一个能复现该 bug 的测试用例,确保回归可发现。”
-
要求解释代码:
- 如果遇到一段看不懂的 AI 代码,一定要让它解释。
- 指令:“请逐行解释一下你刚才生成的这段 JavaScript 代码是如何工作的。”
总结:提示AI写作效率的几个习惯与升级路径
- 边界思维:始终思考“如果……会怎样?”,并要求 AI 把这些边界写进异常处理与测试用例里,这样你的验收口径就不会靠记忆维持。
- 原子化指令:一个指令只做一件事;先让它产出最小可运行版本,再逐步补测试、补边界、补一致性,而不是一次性让它“写全套”,因为那会把错误埋得更深。
- 持续验证:不要假设 AI 第一次生成的代码就是正确的;用测试、可复现的命令、明确的接口契约去验证,让“正确”有证据。
- 保持控制权:你永远是总工程师,AI 是执行工具;你定义路径、节奏、验收口径,它负责把实现推进到可运行状态。
当把这套朴素流程跑顺之后,通常会遇到两个现实瓶颈:
1)你需要不断重复强调“技术栈、目录结构、风格、测试约定”等长期约束;
2)需求、设计、任务如果主要存在于对话里,就很难像代码一样被版本化、被审查、被长期维护。
这就是为什么很多团队会自然走向更工具化的形态:
- Kiro把“需求—设计—任务”固化为 specs,并明确采用
requirements.md / design.md / tasks.md的三段式结构,用来把用户故事与验收标准、设计文档、离散任务计划沉淀成可复用的工件。(Kiro) - Cursor把“长期有效的项目约束”固化为 Rules,通过项目规则持续影响生成与对话,让规则不再靠人肉重复提醒。(Cursor)
- 更广义地看,Martin Fowler 把这种方向概括为 Spec-driven development 的不同强度层次:从“先写 spec 再用 AI 实现”,到“spec 长期保留用于维护”,再到“spec 成为主要源文件”。(martinfowler.com)
展望:从“朴素可控”走向“规范可复用”
现在这套朴素模式的价值在于:它不依赖特定工具,也不要求立刻改变习惯,就能把 AI 编码从“碰运气”拉回到“可验收”,这套方法可以作为个体实践的一个起点。
下一阶段的升级建议会是:先把“长期不变的约束”沉淀成项目规则(例如 Cursor Rules 这类机制),再把“每个功能的需求/设计/任务”沉淀成规格文档(例如 Kiro specs 这类结构),让对话的上下文从“聊天记录”迁移到“仓库工件”。当你的项目开始变大、协作开始变多人、回归成本开始变高时,这一步会让你明显感到:AI 依旧能快,但快得更稳、更少返工、更容易交接与审查。