阅读材料: 第11部分:功能第二阶段

模块「第11部分:功能第二阶段」中第 1 / 5 节课
您正在未登录状态下查看课程。 请登录,以保存进度并参加测试。

第十一部分:功能的第二阶段

功能的第二阶段检验流程是否已变得可重复。第一个功能往往靠热情就能完成。第二个功能则检验你是否能够干净地启动、守住边界、更新变更日志,并且不因变更量过大而感到疲惫。

在 AgentClinic 中,第二阶段可以称为「代理与疾病」。它引入 SQLite、代理表和疾病表、初始数据、/agents/ailments 页面、测试以及导航功能。

干净启动检查清单

在创建新功能分支之前:

git checkout main
git pull --ff-only
git status --short
npm test
npm run typecheck

在 Qwen Code 中:

/clear

检查路线图:

读取 @specs/roadmap.md。
下一个未完成的阶段是什么?
不要修改文件。

如果有未完成的变更,不要开始新阶段。否则,代理生成的变更将难以解释。

为第二阶段创建规格说明

提示:

从 @specs/roadmap.md 开始下一个功能阶段。
创建功能分支和带日期的规格说明目录。

在写入文件之前,向我提出恰好三组问题:
1. 边界:哪些领域实体和页面属于该阶段?

2. 决策:数据库、初始数据、接口约定、测试?
3. 上下文:基调、限制、风险以及应排除在边界之外的内容?

使用 @specs/mission.md 和 @specs/tech-stack.md。
暂时不要实现代码。

回答可能如下:

边界:
仅添加用于读取的代理和疾病。包括列表页面和代理详情页面。
暂时不包含预约和表单。

决策:
使用 SQLite 配合手写迁移。添加虚构的初始数据。
使用 Hono 路由和服务器端渲染的组件。
使用 Vitest 添加路由和组件测试。

上下文:
内容应为讽刺风格,但实现必须清晰。
界面应具有响应式。不使用客户端 JavaScript。

认知负荷与边界检查

第二阶段通常比第一阶段更大。当代理在一次运行中修改数十个文件时,人根本无法理解——眼睛一扫而过,错误就被漏掉了。为了避免被这股洪流淹没:

  • 逐个或成对实现任务组;
  • 进行中间提交;
  • 要求 Qwen Code 按任务组总结变更;
  • 如果您的 Qwen Code 版本支持内置审查流程,请使用 /review
  • 不接受与规格说明不符的变更。

审查提示示例:

/clear
根据 @specs/2026-05-02-agents-ailments/plan.md
和 @specs/2026-05-02-agents-ailments/validation.md 审查当前分支。

重点关注:
1. 超出阶段边界;
2. 数据库迁移安全;
3. 测试覆盖缺口;
4. 与 @specs/tech-stack.md 的冲突。

不要修改文件。

任务组示例

# 计划 — 代理与疾病

## 组 1 — 数据库启动

1. 安装 better-sqlite3。
2. 添加数据库连接模块。
3. 添加可重复运行的迁移机制。

## 组 2 — 领域模式

4. 添加代理表。
5. 添加疾病表。
6. 添加关联表 agent_ailments。

## 组 3 — 初始数据

7. 添加虚构代理。
8. 添加虚构疾病。
9. 关联代理与疾病。

## 组 4 — 路由与组件

10. 添加列表页面 /agents。
11. 添加详情页面 /agents/:id。
12. 添加页面 /ailments。

## 组 5 — 测试与验证

13. 添加路由测试。
14. 添加组件渲染测试。
15. 运行 npm test 和 npm run typecheck。

样式决策也应写入规格说明

如果您决定品牌色为橙色和黑色,这不应只留在聊天记录中。请记录下来:

## 视觉方向

- 主要品牌色:橙色和黑色。
- 将颜色用作点缀,而非整页主题。
- 页面应保持可读且适合演示。

Qwen Code 提示:

更新相关规格说明:AgentClinic 的品牌色为橙色和黑色。
然后仅在需要的地方更新 CSS。
不要更改无关页面的样式。

修复规格说明,而非功能规格说明

并非每个分支都是新功能。部分工作是修复错误:用户发现代理列表排序不对,或表单验证漏过了空消息。对于这类变更,requirements.md 模板并不合适:「应该出现什么」这个问题是次要的,主要的是「什么已经坏了」、「为什么」以及「修复时不应改变什么」。

在这种情况下,使用单独的修复规格说明模式会很有用。文件夹结构相同:

specs/
  2026-05-12-feedback-empty-message-bug/
    bugfix.md
    plan.md
    validation.md

只是用 bugfix.md 替代 requirements.md,包含不同的章节。

# 修复 — POST /feedback 漏过空消息

## 当前行为

提交空 message 字段的表单时,服务器返回 302 并将空消息字符串保存到 `feedback` 表中。在 /feedback 页面上,该记录显示为空块。

## 预期行为

当 message 为空时,服务器返回 400 和 `/feedback/new` 页面,高亮字段并显示错误文本「消息必填」。不创建数据库记录。

## 根本原因证据

在 `src/routes/feedback.ts` 中,POST 路由接收请求体而未调用验证:请求体直接传递给记录操作。这在 2026-05-10-feedback-form 阶段的提交 3a7c1b9 中可见,验证被标记为 `// TODO` 而推迟。

## 不应改变的内容

- GET /feedback 路由继续返回列表页面。
- `feedback` 表中的现有记录不被编辑或删除。

- 表单字段名称(`name`、`message`)保持不变。
- 400 错误格式与项目中的其他路由一致。

## 回归场景

- 带有非空 `message` 的 POST 仍保存记录并返回 302。
- 带有空 `name` 但非空 `message` 的 POST 仍被保存(如果修复前就是如此)。
- /feedback 页面显示所有先前保存的记录,不做更改。

修复的 plan.md 通常更短:一个组用于修复本身,一个组用于捕获该错误的回归测试。

validation.md 必须包含事实复现:修复前失败、修复后通过的命令或场景。这就是验证是否修复了实际损坏内容的依据:

### F1 — 空消息被拒绝

- 命令:`npm test -- feedback`
- 预期:POST /feedback 带空 message 返回 400 且不创建行
- 负责人:自动检查
- 状态:草稿

修复与功能的主要区别——必须有「不应改变的内容」章节和回归测试。没有这些,代理经常会「改进」相邻代码并破坏原本正常工作的内容。

如果过程中发现修复变成了重构——多个相关错误、新模式、模块重写——关闭修复分支,将成果转移到常规功能分支并重新规划。这不是失败,而是任务从「修复」模式增长到「重做」模式的正常信号。

合并前更新变更日志

根据本分支的工作更新 @CHANGELOG.md。
使用当前日期作为标题。
提及领域模式、路由、页面、测试和规格说明更新。
保持简洁。

实践

  • [ ] 从干净的 main 开始第二个功能分支。
  • [ ] 通过访谈创建规格说明。
  • [ ] 分部分实现任务组。
  • [ ] 检查偏离边界的情况。
  • [ ] 更新变更日志。
  • [ ] 仅在审查后合并。

检查问题

  1. 与代理合作时的认知负荷来自何处,SDD 的哪些技巧可以降低它?
  2. 为什么样式决策需要记录在规格说明中?
  3. 哪些迹象表明阶段过大?
我的笔记
0 / 10000

笔记保存在当前浏览器中。在其他设备上将不会显示。

课程菜单

课程

基于 Qwen Code CLI 的规范驱动开发
进度 0 / 135