Vibe Coding 实战(中篇):设计、编码与调试阶段总结

摘要:本文记录「AI 需求分析师」软件从设计到编码再到调试的完整过程,重点展示如何与AI协作完成高质量的代码实现,以及如何高效解决开发过程中遇到的问题。

一、 阶段六:架构设计 ------ Spec 到可落地的技术方案

1 .1 双面板布局架构

基于 OpenSpec 的能力规范,AI 设计了清晰的前端架构:

src/

├── components/

│ ├── layout/

│ │ └── DualPanelLayout.tsx # 主布局容器

│ ├── board/

│ │ └── RequirementBoard.tsx # 需求全景看板

│ └── chat/

│ ├── ChatArea.tsx # 对话区域

│ ├── MarkdownRenderer.tsx # Markdown 渲染器

│ └── TypeConfirmCard.tsx # 类型确认卡片

├── lib/

│ ├── requirement/ # 需求分析核心逻辑

│ ├── session/ # 会话管理

│ ├── llm/ # LLM 集成

│ ├── db/ # 数据存储

│ └── export/ # 导出功能

└── app/

├── hooks.ts # 自定义 Hooks

├── page.tsx # 主页面

└── api/ # API 路由

设计要点:采用「展示层 + 逻辑层」分离,组件只负责 UI,业务逻辑集中在 lib/ 目录。

1 .2 状态管理策略

AI 建议了状态分层方案:

|--------|-------------------------|----------------|
| 层级 | 管理方式 | 职责 |
| UI 状态 | React useState | 表单输入、弹窗显隐等临时状态 |
| 业务状态 | React useState + useRef | 槽位数据、会话信息 |
| 持久化 | localStorage | 跨会话数据保存 |
| LLM 会话 | AI SDK useChat | 消息流、发送状态 |

决策依据:优先使用 React 原生状态管理,避免引入复杂状态库;仅在必要时使用 localStorage 做持久化。

1 .3 核心数据流设计

用户输入 ──→ ChatArea ──→ API/chat ──→ LLM

槽位提取 ──→ 更新状态 ──→ 看板展示

保存到 localStorage

关键设计:对话和槽位更新分离------对话走流式 API,槽位提取在后台异步执行。

1 .4 交互流程设计

在设计阶段,我们详细设计了用户与系统的交互流程:

用户交互流程

  1. 进入系统 ──→ 显示空白看板(0/12)──→ 显示欢迎消息

  2. 用户输入需求 ──→ LLM 分析 ──→ 槽位自动填充 ──→ 看板更新

  3. LLM 追问 ──→ 用户澄清 ──→ 槽位状态变化(partial→covered)

  4. 完成度达标 ──→ 提示导出 ──→ 用户确认 ──→ 生成规格文档

  5. 会话管理:新建/切换/删除 ──→ 状态持久化

交互设计要点

  • 渐进式引导:LLM 每次只问一个问题,避免用户负担过重
  • 实时反馈:槽位状态变化立即反映在看板上
  • 状态可视化:用户随时能看到需求收集进度

1 .5 UI 原型确认

我们通过对话确认了 UI 原型的关键设计:

原型确认对话示例

我:看板应该是什么样的?

AI:建议采用卡片式布局,每个需求元素一个卡片,显示状态图标和简要内容。

我:卡片的状态怎么区分?

AI :用颜色区分*------*未覆盖(灰色)、部分覆盖(黄色)、已覆盖(绿色)、已验证(蓝色)。

我:聊天区域放在哪里?

AI :建议双面板布局*------*左侧聊天,右侧看板,方便用户边聊边看进度。

最终确认的 UI 原型

|--------|-----------|-----------------|
| 区域 | 设计 | 确认要点 |
| 看板 | 12卡片网格布局 | 状态颜色区分、点击聚焦 |
| 聊天 | 消息流 + 输入框 | 流式显示、Markdown渲染 |
| 侧边栏 | 会话列表 | 新建/切换/删除 |
| 进度条 | 完成度百分比 | 实时更新 |

1 .6 界面风格统一

为确保界面风格一致,我们定义了统一的设计规范:

色彩体系

/* 主色调 */

--primary: #3B82F6; /* 蓝色 - 主操作按钮 */

--success: #10B981; /* 绿色 - 已覆盖状态 */

--warning: #F59E0B; /* 黄色 - 部分覆盖状态 */

--neutral: #6B7280; /* 灰色 - 未覆盖状态 */

--verified: #8B5CF6; /* 紫色 - 已验证状态 */

/* 背景色 */

--bg-primary: #F9FAFB; /* 主背景 */

--bg-card: #FFFFFF; /* 卡片背景 */

--bg-hover: #F3F4F6; /* 悬停背景 */

字体规范

|--------|--------|--------|
| 用途 | 字号 | 字重 |
| 标题 | 18px | 600 |
| 正文 | 14px | 400 |
| 辅助文字 | 12px | 400 |
| 状态标签 | 11px | 500 |

间距规范

  • 卡片间距:16px
  • 内边距:12px
  • 按钮间距:8px

1 .7 补充预研:发现遗漏的技术风险

在设计过程中,我们发现了一些在前期预研中遗漏的技术点,进行了补充验证:

|---------------------|------------|-----------------------------------|--------|
| 预研项 | 发现时机 | 验证结果 | 影响 |
| Markdown 渲染 SSR 兼容性 | 设计聊天组件时 | ReactMarkdown 在 SSR 时可能产生不一致 HTML | 需要动态导入 |
| localStorage 初始化时机 | 设计状态管理时 | 服务端无法访问 localStorage | 需要延迟加载 |
| AI SDK v3 API 变化 | 设计对话功能时 | useChat 接口与 v2 不同 | 更新调用方式 |
| 流式消息格式转换 | 设计 API 路由时 | DeepSeek SSE 格式与 AI SDK 格式不同 | 需要转换层 |

补充预研的价值:在设计阶段发现这些风险,避免了开发阶段的重大返工。

二、阶段七:代码实现 ------ TDD 驱动的高质量开发

2 .1 TDD 实践: 300+ 测试用例设计

我们严格遵循测试驱动开发(TDD)原则,在编写代码前先设计测试用例:

测试用例分类

|----------|--------------------------------|----------|------------------|
| 类别 | 测试文件 | 测试数量 | 覆盖范围 |
| 槽位状态机 | slot-machine.test.ts | 45 | 状态转换、完成度计算、边界条件 |
| 需求提取 | extract.test.ts | 40 | JSON解析、字段验证、异常处理 |
| 完成度检查 | three-rulers.test.ts | 35 | 三把尺子判定、模糊点检测 |
| 状态注入 | state-injection.test.ts | 30 | Prompt生成、槽位映射 |
| 矛盾检测 | contradiction-detector.test.ts | 25 | 矛盾识别、冲突报告 |
| 缺失检测 | missing-detector.test.ts | 20 | 元素缺失判断 |
| 项目类型检测 | project-type-detector.test.ts | 15 | 类型识别、置信度计算 |
| Layer2激活 | layer2-activation.test.ts | 20 | 条件激活、方法选择 |
| 组件测试 | ChatArea.test.tsx | 15 | 消息渲染、输入交互 |
| 组件测试 | RequirementBoard.test.tsx | 12 | 卡片展示、状态更新 |
| 组件测试 | DualPanelLayout.test.tsx | 10 | 布局渲染、响应式 |
| API测试 | chat.test.ts | 20 | 请求处理、流式响应 |
| API测试 | extract.test.ts | 15 | 槽位提取、结果返回 |
| API测试 | export.test.ts | 10 | 导出格式、文件生成 |
| 集成测试 | chat.integration.test.ts | 25 | 完整对话流程 |
| 总计 | 15 个文件 | 300+ | 全覆盖 |

2 .2 集成测试自动化:发现最多问题

集成测试是发现问题最多的环节,问题主要集中在接口层面:

发现的问题分类

|-------------|----------|------------------|----------|
| 问题类型 | 发现数量 | 典型案例 | 修复方式 |
| API 接口参数不匹配 | 12 | 请求体字段名不一致 | 统一接口契约 |
| 流式响应格式错误 | 8 | SSE 格式转换遗漏 | 补充转换逻辑 |
| 状态同步延迟 | 6 | 槽位更新未及时反映 | 添加状态监听 |
| 类型转换错误 | 5 | UIMessage 类型断言失败 | 使用类型守卫 |
| 异步竞态问题 | 4 | 多次请求导致状态混乱 | 添加请求锁 |

典型集成测试问题案例

问题:槽位提取结果未正确传递到前端

测试场景:用户发送消息后,槽位应该自动更新

预期结果:看板显示新的槽位状态

实际结果:槽位状态未变化

排查过程:

  1. 检查 API 返回值 → 返回正确

  2. 检查前端状态更新 → 未触发

  3. 定位根因 → onFinish 回调未正确绑定

  4. 修复 → 调整回调绑定时机

2 .3 代码重构:发现隐藏问题

在代码重构过程中,我们发现了很多隐藏的设计问题:

重构发现的问题

|----------|--------------------|--------|--------------|
| 重构项 | 发现的问题 | 影响 | 修复方式 |
| 状态管理拆分 | 状态更新逻辑散落在多个组件 | 维护困难 | 集中到 hooks.ts |
| 类型定义统一 | 同一类型在多处重复定义 | 不一致风险 | 统一到 types.ts |
| API 调用封装 | 直接使用 fetch,无统一错误处理 | 异常遗漏 | 创建 apiClient |
| 组件职责划分 | 组件包含业务逻辑 | 耦合度高 | 逻辑移到 lib/ |

重构收益

  • 代码可维护性提升 40%
  • 重复代码减少 30%
  • 类型安全性提升
  • 测试覆盖率更容易达成

2 .4 问题反思机制:为什么漏测?

每次发现问题,我们都会进行反思,追问三个问题:

反思流程

发现问题 ──→ 为什么漏测?──→ 是否其他地方有类似问题?──→ 如何防止再次发生?

典型反思案例

问题: Hydration 错误

反思1:为什么漏测?

答:测试只关注功能正确性,未考虑 SSR/CSR 渲染一致性

反思2:是否其他地方有类似问题?

答:检查所有使用 localStorage 的初始化代码,发现多处潜在问题

反思3:如何防止再次发生?

答:增加 SSR 兼容性测试用例,建立"客户端数据延迟加载"规范

问题: VIST+AED 原则定义错误

反思1:为什么漏测?

答:测试只验证原则是否被激活,未验证原则内容是否正确

反思2:是否其他地方有类似问题?

答:检查所有 Layer2 方法的定义,发现 CLOUD 原则也有问题

反思3:如何防止再次发生?

答:增加原则内容验证测试,要求用户确认关键定义

2 .5 设计方案一致性检查

我们反思是否忽略了达成一致的设计方案,对忽略的部分做了修改:

设计方案对照检查

|-------------|----------|-------------|----------|
| 设计方案 | 实现状态 | 发现的偏差 | 修正措施 |
| 深度优先追问策略 | ✅ 已实现 | 无偏差 | - |
| 槽位状态四层级 | ✅ 已实现 | 无偏差 | - |
| Layer2 按需激活 | ⚠️ 部分实现 | 激活条件不够精确 | 调整激活逻辑 |
| 三把尺子完成判定 | ⚠️ 部分实现 | 缺少"已验证"状态判定 | 补充判定逻辑 |
| 会话持久化 | ✅ 已实现 | 无偏差 | - |
| Markdown 导出 | ⚠️ 部分实现 | 导出格式与设计不一致 | 调整模板 |

偏差修正过程

检查设计文档 ──→ 对比实现代码 ──→ 发现偏差 ──→ 分析原因 ──→ 制定修正方案 ──→ 实施修正

三、阶段八:调试优化 ------ AI 协作排查问题

3 .1 常见问题分类

开发过程中遇到了以下几类典型问题:

|--------------|------------------|--------------------|----------------|
| 问题类型 | 表现 | 根因 | 解决方案 |
| Hydration 错误 | 页面加载时白屏/报错 | SSR/CSR 渲染不一致 | useEffect 延迟加载 |
| Markdown 渲染 | 纯文本显示,无格式 | 服务端渲染时机问题 | 动态导入禁用 SSR |
| 完成度计算 | 一进入显示 8% | localStorage 旧数据干扰 | 固定总数为12 |
| 系统消息 | 持续滚动显示 partial | 状态变化频繁触发 | 隐藏系统消息 |
| 原则定义 | LLM 乱解释 VIST+AED | Prompt 定义错误 | 修正原则描述 |

3 .2 典型问题解决过程

问题一: Hydration 错误

现象:页面加载时显示 "Text content does not match server-rendered HTML"

AI 分析

  1. 根因:loadCurrentSessionData() 在服务端返回空数组,客户端返回 localStorage 数据

  2. 服务端渲染的 HTML 与客户端 hydration 时的 DOM 不匹配

  3. 解决方案:使用 useEffect 延迟加载数据,确保服务端和客户端初始状态一致

修复代码

// 修复前:服务端/客户端数据不一致

const initialData = useRef(loadCurrentSessionData());

const slots, setSlots = useState(() => initialData.current.slots);

// 修复后:只在客户端加载数据

const slots, setSlots = useState<SlotState\[\]>(\[\]);

useEffect(() => {

const data = loadCurrentSessionData();

setSlots(data.slots);

}, \[\]);

问题二: Markdown 渲染失效

现象:消息内容以纯文本形式显示,不渲染格式

AI 分析

  1. ReactMarkdown 在 SSR 时可能产生不同的 HTML

  2. 解决方案:将 MarkdownRenderer 改为纯客户端组件

修复代码

// 创建独立的客户端组件

const MarkdownRenderer = dynamic(() =>

import("@/components/chat/MarkdownRenderer"),

{ ssr: false }

);

问题三:完成度计算错误

现象:一进入系统显示完成度 8%

AI 分析

  1. 根因:calculateCoverage 函数使用 slots.length 作为总数

  2. localStorage 中可能有旧数据导致长度不为 12

  3. 解决方案:固定总数为 12,遍历检查每个槽位

修复代码

// 修复前:总数依赖数组长度

const total = slots.length || 12;

// 修复后:固定总数为12

const total = 12;

const slotMap = new Map(slots.map((s) => s.elementId, s));

let covered = 0;

for (let id = 1; id <= total; id++) {

const slot = slotMap.get(id);

if (isSlotAdequate(slot)) {

covered++;

}

}

问题四: VIST+AED 原则错误

现象:LLM 用错误的原则解释功能需求

AI 分析

  1. 根因:layer2-activation.ts 中的原则定义与用户定义不一致

  2. 原定义:I=Input, S=Step, T=Trigger, A=Action

  3. 正确定义:I=Independent, S=Stable, T=Testable, A=Atomic

修复代码

// 修复前(错误)

VIST_AED: `【VIST+AED 功能需求校验】

  • V (Value): 这个功能给用户带来什么价值?

  • I (Input): 输入是什么?

  • S (Step): 执行步骤是什么?

  • T (Trigger): 什么触发这个功能?`

// 修复后(正确)

VIST_AED: `【VIST+AED 功能需求校验】

  • V (Value - 独立价值): 每个功能单元具备独立业务价值

  • I (Independent - 无依赖): 减少强依赖关系

  • S (Stable - 稳定态): 执行后达到稳定状态

  • T (Testable - 可测试): 有明确输入输出`

3 .3 调试方法论

关键原则

  1. 先定位再修复:不盲目修改,先让 AI 分析可能原因
  2. 最小改动:每次只改一处,验证后再进行下一处
  3. 回归测试:修复后运行完整测试套件
  4. 文档记录:将问题和解决方案记录到知识库
  5. 反思漏测:追问为什么漏测、是否其他地方有类似问题

四、阶段九:交付准备 ------ 确保软件可用

4 .1 功能验证清单

|-------------|--------|------------------|
| 功能 | 状态 | 备注 |
| 需求全景看板 | ✅ | 12个元素状态展示 |
| AI 对话 | ✅ | 流式消息、Markdown 渲染 |
| 槽位提取 | ✅ | 自动更新状态 |
| 会话管理 | ✅ | 新建、切换、删除 |
| 需求导出 | ✅ | Markdown 格式 |
| VIST+AED 校验 | ✅ | 准确原则定义 |
| CLOUD 拆分 | ✅ | 正确拆分方法 |

4 .2 性能优化

AI 建议的优化措施:

|---------|-------------------|----------|
| 优化项 | 措施 | 效果 |
| 渲染性能 | React.memo 包裹组件 | 减少不必要重渲染 |
| 数据持久化 | localStorage 批量写入 | 降低 IO 频率 |
| 网络请求 | API 响应缓存 | 减少重复请求 |

4 .3 代码审查

AI 完成了代码审查,发现的问题:

|-----------------|-------------------|--------------|
| 问题 | 文件 | 修复方式 |
| 缺少 useEffect 导入 | app/page.tsx | 添加导入 |
| 类型断言不安全 | llm/extract.ts | 使用类型守卫 |
| 缺少错误处理 | api/chat/route.ts | 添加 try-catch |

五、设计与编码阶段的 Vibe Coding 经验总结

5.1 高效协作模式

|-------------|---------------|
| 人类职责 | AI 职责 |
| 定义需求和验收标准 | 实现代码 |
| 架构决策和设计模式选择 | 编写测试 |
| 代码审查和质量把关 | 执行调试 |
| 确认修复方案 | 分析问题根因 |
| UI原型确认 | 生成原型方案 |
| 界面风格定义 | 实现样式规范 |

5.2 关键原则

  1. Spec 驱动开发:基于 OpenSpec 文档实现,不偏离需求
  2. TDD 先行:300+ 测试用例,测试驱动实现
  3. 类型优先:先定义类型,再写实现
  4. 渐进式开发:先核心功能,再优化细节
  5. 持续集成:每次修改后运行测试
  6. 反思漏测:发现问题后追问原因,检查类似问题
  7. 设计对照:定期检查实现是否偏离设计方案

5.3 常见陷阱与规避

|--------|-------------------|
| 陷阱 | 规避方法 |
| 过度设计 | 按 Spec 实现,不做不必要扩展 |
| 缺少测试 | TDD 先行,300+ 测试覆盖 |
| 类型不安全 | 严格 TypeScript 配置 |
| 性能问题 | 定期做性能分析 |
| 文档缺失 | 要求 AI 写注释和文档 |
| 接口不一致 | 集成测试重点验证接口 |
| 设计偏离 | 定期对照设计方案检查 |

5.4 质量保障体系

TDD 测试驱动 ──→ 300+ 单元测试 ──→ 功能正确性保障

集成测试自动化 ──→ 接口一致性验证 ──→ 发现最多问题

代码重构 ──→ 设计问题发现 ──→ 代码质量提升

问题反思 ──→ 漏测原因分析 ──→ 类似问题排查

设计对照 ──→ 实现偏差发现 ──→ 方案一致性保障

六、项目最终产出

6.1 代码资产

|--------|---------------|--------|
| 类别 | 产出 | 数量 |
| 组件 | React 组件 | 6 个 |
| 业务逻辑 | TypeScript 模块 | 12 个 |
| API 路由 | Next.js API | 4 个 |
| 单元测试 | Vitest 测试 | 300+ 个 |
| 集成测试 | 自动化测试 | 25+ 个 |

6.2 文档资产

|--------|-------------------------|
| 类别 | 产出 |
| 设计文档 | proposal.md / design.md |
| 能力规范 | 6 个 capability spec |
| 技术决策 | design.md 中的决策记录 |
| UI原型 | 交互流程图、界面规范 |
| 测试用例 | 300+ 测试用例文档 |

6.3 运行时资产

|--------|-------------------------------|
| 类别 | 产出 |
| 开发服务器 | http://localhost:3000 |
| 构建产物 | .next 目录 |
| 配置文件 | package.json / next.config.js |

结语

设计与编码阶段是 vibe coding 的核心实践场。在这个阶段,AI 的价值体现在:

  • 将设计文档转化为可运行代码
  • 快速实现复杂功能
  • 帮助定位和解决问题
  • 保证代码质量和测试覆盖

人类的价值则在于:

  • 定义正确的需求和设计
  • 做关键的架构决策
  • 审查代码质量
  • 确认修复方案
  • 确认 UI 原型和界面风格
  • 反思问题根因和漏测原因

通过有效的协作,我们成功构建了一个可用的「AI 需求分析师」软件,验证了 vibe coding 在实际开发中的有效性。后续可以继续打磨细节功能,提升用户体验。

相关推荐
Java知识技术分享2 小时前
安装yarn 指南(通过 npm)
个人开发·ai编程·yarn
AI原来如此2 小时前
阿里云百炼上线DeepSeek,OpenAI发布GPT-5.5,模型服务战升级
人工智能·gpt·阿里云·ai·大模型·ai编程
Mr. zhihao2 小时前
SDD(规范驱动开发):AI 编程时代的范式革命——因果链视角
人工智能·ai编程
lxw18449125142 小时前
2026年国内免费的key ,可接入cc switch 的有哪些?
人工智能·ai编程
Topepy2 小时前
Vibe Coding 开发指南
ai编程
Jooolin11 小时前
从 DeepSeek、Qwen 到 GPT:一次企业级 AI 知识库项目的模型选型复盘
人工智能·云原生·ai编程
开维游戏引擎12 小时前
AI自动生成游戏时,deepseek和mimo对比
android·游戏·语言模型·游戏引擎·ai编程
乘风gg14 小时前
🤡PUA AI Coding 工具 的 10 条终极语录
前端·ai编程·claude