返回笔记首页

增量的项目如何基于sdd驱动开发

主题配置

对于增量的项目,一个老的项目 里面有80万行代码, 现在要加一些小功能的改动,如何基于skill sdd驱动开发,让ai基于旧的代码增量添加功能,还有遵循老代码的规范,还能高度还原高保真的视觉

老项目增量开发是 SDD 最难的场景。核心挑战有三个:AI 看不到全部代码、不知道老规范、不知道视觉标准

阶段一做代码考古 — 给 AI 建"上下文地图"

Step 1 — 用 Claude Code 生成项目结构快照

在项目根目录运行,让 AI 先看整体骨架,不是具体代码

markdown
find . -type f \( -name "_.vue" -o -name "_.ts" -o -name "\*.tsx" \) \
 | grep -v node_modules | grep -v dist \
 | head -200 > project-tree.txt

# 然后把 project-tree.txt 喂给 Claude:

# "这是项目的文件列表,我要新增XX功能,

# 请告诉我哪些文件最相关,我需要给你读哪些?"

Step 2 — 提取"最相关的 5~10 个文件"给 AI

不要一次性扔所有代码。按功能类型精准喂:

markdown
# 要加"用户标签筛选"功能,相关文件:

@src/components/UserList.vue ← 要改的组件
@src/api/user.ts ← 相关接口
@src/store/userStore.ts ← 状态管理
@src/types/user.d.ts ← 类型定义
@src/utils/filter.ts ← 已有的筛选工具函数

# 告诉 AI:只读这几个文件,理解现有模式后再动手

Step 3 — 让 AI 反向总结"老代码规范"

这一步是关键:不是你告诉 AI 规范,而是让 AI 读代码自己归纳,再让你确认

markdown
请阅读以上 5 个文件,总结这个项目的编码规范,包括:

1. 组件结构顺序(script/template/style 顺序?Options API 还是 Composition API?)
2. 接口调用方式(axios 封装?统一 try/catch?还是 .catch 链式?)
3. 状态管理模式(Pinia 还是 Vuex?actions 怎么命名?)
4. CSS 规范(BEM?scoped?用了哪些 CSS 变量?)
5. TypeScript 使用习惯(interface 还是 type?枚举怎么定义?)

总结完后等我确认,不要先写代码。

AI 归纳完后,你只需要纠正偏差,形成 code-style.spec.md,后续所有新功能都引用它。

**阶段二****建三份 Spec — 规范、视觉、功能各一份**

三份 Spec 分工明确,AI 每次生成代码时全部引用

Spec A — code-style.spec.md(编码规范)

由阶段一 Step 3 的 AI 归纳结果整理而来,示例:

markdown
# code-style.spec.md

## 组件结构(必须按此顺序)

<script setup lang="ts"> → <template> → <style scoped>

## 接口调用
- 统一用 src/utils/request.ts 封装的 axios
- 错误统一在 request.ts 拦截,组件层不写 try/catch
- 接口函数命名:动词 + 名词,如 fetchUserList / updateUserTag

## 类型定义
- 业务实体用 interface,工具类型用 type
- 所有接口响应类型放在 src/types/ 目录
- 禁止在组件内 inline 定义接口类型

## CSS 规范
- 统一用 scoped + CSS 变量(变量定义在 src/styles/vars.css)
- 类名用小写 kebab-case,不用 BEM
- 禁止写内联 style,除非是动态绑定

## 命名规范
- 组件:PascalCase(UserTagFilter.vue)
- 函数:camelCase(getUserTags)
- 常量:UPPER_SNAKE_CASE(MAX_TAG_COUNT)

Spec B — design-token.spec.md(视觉规范)

从老项目的 CSS 变量 / UI 库配置中提取,这是高保真还原的核心

markdown
# design-token.spec.md

## 色彩系统(从 vars.css 提取)

--color-primary: #1677FF ← 主色,按钮/链接
--color-success: #52C41A ← 成功态
--color-warning: #FAAD14 ← 警告态
--color-danger: #FF4D4F ← 危险/错误态
--color-text-primary: #1A1A1A
--color-text-secondary: #666666
--color-text-disabled: #BFBFBF
--color-border: #E5E5E5
--color-bg-base: #F5F5F5

## 间距系统(8px 基准)

--space-xs: 4px --space-sm: 8px
--space-md: 16px --space-lg: 24px --space-xl: 32px

## 字体规范

--font-size-sm: 12px --font-size-base: 14px
--font-size-md: 16px --font-size-lg: 20px
正文行高:1.6,标题行高:1.3

## 圆角规范

--radius-sm: 4px --radius-md: 6px --radius-lg: 8px

## 已有公共组件(禁止重复造轮子)

BaseButton / BaseInput / BaseTable / BaseModal
TagBadge / StatusDot / PageHeader

Spec C — feature.spec.md(本次新功能)

只描述这次要加的功能,不重复写规范(规范引用 A/B 即可)

markdown
# user-tag-filter.spec.md

## 引用规范

遵循 @code-style.spec.md 和 @design-token.spec.md

## 功能描述

在 UserList 页面顶部新增标签多选筛选栏,筛选后实时刷新列表

## 改动范围(最小化)

- 新增:src/components/UserTagFilter.vue(新文件)
- 修改:src/views/UserList.vue(仅顶部插槽区域)
- 修改:src/api/user.ts(新增 tags 参数到 fetchUserList)
- 不改:UserList 的表格列、分页、排序逻辑(保持原样)

## 交互定义

- 标签来源:GET /api/tags,页面加载时请求一次,缓存在组件内
- 多选模式:可同时选多个标签,全不选 = 不筛选
- 触发时机:选中/取消 立即触发,不需要确认按钮
- 加载态:筛选期间表格显示 loading,不清空现有数据(骨架屏)
- URL 同步:筛选状态写入 query 参数 ?tags=1,2,3,支持分享链接

## 视觉要求(引用已有组件)

- 标签用已有的 TagBadge 组件,选中态加 --color-primary 描边
- 整体样式和 UserList 现有筛选区保持一致(参考截图:见附件)

**阶段三****截图 + Spec 双驱动生成代码**

高保真还原的核心:先截图锚定视觉,再用 Spec 约束代码

Step 1 — 截图已有的相似组件给 AI 看

不要描述视觉,直接截图。截老项目里风格最接近的区域:

markdown
[截图1] 现有的"状态筛选栏"区域(已有的筛选组件样式)
[截图2] TagBadge 组件现有的选中态 / 未选中态

Prompt:
"新的 UserTagFilter 组件视觉风格需要和截图1的筛选栏完全一致,
标签的选中态参考截图2,请先描述你看到的视觉规律,
我确认后再生成代码。"

让 AI 先"说"它看到了什么再动手,可以提前发现视觉理解偏差。

Step 2 — 一次性喂全部上下文生成代码

markdown
请基于以下所有上下文生成代码:

【规范】@code-style.spec.md
【视觉】@design-token.spec.md
【功能】@user-tag-filter.spec.md
【参考代码】@src/components/StatusFilter.vue(风格最接近的已有组件)
【相关代码】@src/api/user.ts @src/types/user.d.ts
【视觉参考】[截图1] [截图2]

生成任务:

1. 新建 UserTagFilter.vue,复用 TagBadge,CSS 变量全部用 design-token 中定义的
2. 修改 UserList.vue,只动顶部插槽,其余代码一行不改
3. 修改 user.ts,只新增 tags 参数,不改已有函数签名

输出完后告诉我改动了哪些行,方便我 diff 检查。

Step 3 — 视觉还原度验收(截图对比)

代码生成后,在浏览器截图新组件,和老组件截图一起发给 AI:

markdown
截图A] 老的 StatusFilter 筛选栏(目标风格)
[截图B] 刚生成的 UserTagFilter(实际效果)

Prompt:
"对比两张截图,列出所有视觉不一致的地方
(间距/颜色/字体大小/圆角/边框),逐条修复。"

这个"截图对比"的循环平均跑 2~3 轮就能达到高保真,比手动调样式快 5 倍。

阶段四最小化改动验证 — 防止 AI 动了不该动的代码

老项目最大风险:AI 顺手重构了其他地方

Step 1 — 用 git diff 做改动范围审查

markdown
git diff --stat # 看改了哪些文件
git diff # 看具体改了什么

# 把 diff 输出发给 AI:

"以下是你生成代码后的 git diff,
请确认改动范围是否超出了 feature.spec.md 中定义的范围,
如有超出,告诉我哪里需要还原。"

Step 2 — 跑类型检查和已有测试

markdown
npx tsc --noEmit # 确保没有引入新的类型错误
npx vitest run # 跑已有单测,不能有新增失败
npx eslint src --ext .vue,.ts # 确保符合老项目 lint 规则

如果 tsc 或测试报错,把报错信息发给 AI:"请修复以下错误,不要改动其他逻辑。"

Step 3 — 把本次 Spec 存档,下次增量继续复用
markdown
docs/
specs/
code-style.spec.md ← 长期维护,每次有新规范就更新
design-token.spec.md ← 长期维护,UI 库升级时同步
features/
2024-11-user-tag-filter.spec.md ← 归档,可追溯
2024-12-export-excel.spec.md ← 下次新功能继续写这里

三份 Spec 中,A(编码规范)和 B(视觉规范)是复用的,只有 C(功能)每次新写。边际成本越来越低。

整套方案的核心逻辑补充几点

为什么要"让 AI 反向归纳规范"而不是自己写?

80 万行代码的老项目,规范往往是隐性的——没人写文档,但大家都在遵守。让 AI 读 5~10 个核心文件自己归纳,再由你纠正,比你从零回忆准确得多。这份归纳出来的 code-style.spec.md 本身就是项目的隐性知识显性化,是这套方案最有价值的副产品。

视觉高保真的本质是"给截图而不是给描述"

你告诉 AI "间距要和现有组件一致",AI 会猜。你把截图直接给它,它看到的就是你看到的。两张截图对比让 AI 自己 diff,比你逐条说"这里少了 4px"精准得多。

"改动范围最小化"是老项目 SDD 的第一原则

feature.spec.md 里明确写"不改 XX 文件、不动 XX 逻辑",比写"要改什么"更重要。AI 有重构冲动,你要在 Spec 层就把边界锁死,然后用 git diff 做事后验收。