前言
上个月,我尝试了一件听起来很"丝滑"的事:把项目的架构设计文档丢给 Claude,让它自动生成总纲、概要设计、详细设计、开发规约,然后按模块逐个开发。
想象中:文档进 → PRD 出 → 代码跑,全程 AI 包办,我喝茶看报。
实际上:文档进 → 冲突出 → 反复修 → 上下文炸 → 重新喂,我比没 AI 还累。
这篇文章复盘我从"盲目乐观"到"摸清边界"的全过程------不是教你"怎么用 Claude",而是告诉你 Claude 在复杂工程场景下到底哪里行、哪里不行**,以及怎么把不行的部分补上。
背景:为什么会有这个想法
我们项目有一套比较完善的架构设计文档:系统分层、模块划分、数据流向、接口约定都有明确定义。但文档归文档,落地开发还是要人一行行写。
我就想:既然 Claude 号称能理解长文档、能写代码,能不能直接把架构文档喂给它,让它先产出全套设计文档(总纲→概设→详设→开发规约),再按模块逐个生成 PRD,最后根据各模块 PRD 写代码?
流程设计是这样的:
markdown
架构设计文档(输入)
↓
Claude 生成《项目总纲》← 定范围、定目标、定约束
↓
Claude 生成《概要设计》← 模块划分、接口定义、数据流向
↓
Claude 生成《详细设计》← 类图、时序图、字段级定义
↓
Claude 生成《开发规约》← 命名规范、代码结构、异常处理约定
↓
按模块逐个生成《模块PRD》← 每个模块的技术方案、接口清单、数据模型
↓
按模块逐个开发 ← 基于对应的模块PRD生成代码
为什么要加"模块 PRD"这一步? 因为详设和开发规约是宏观约束,落到具体模块时,接口签名、参数校验规则、异常场景处理都需要一个更细粒度的"施工图纸"。我以为这个分层设计是加分项------先锁定方案,再写代码,逻辑上没毛病。
理想很丰满。然后现实开始教我做人。
第一坑:多文档并存时,Claude 的业务理解"串"了
现象
架构文档里对同一个业务概念,在不同章节可能有不同角度的描述。比如"用户订单状态流转",在总纲里是一句话带过,在概要设计里是个状态机图,在详细设计里是字段级的枚举定义。
当我把这些文档同时喂给 Claude 生成详设和开发规约时,问题来了:Claude 产出的详设里,订单状态枚举和概要设计里的状态机对不上------多了两个状态,少了一个状态转换路径。
更离谱的是,开发规约里定义的异常处理方式,和详设里接口的错误码设计互相矛盾:规约说"所有异常统一抛 BusinessException",详设里却在某个接口上写了"此接口需区分 ValidationException 和 BusinessException"。
诊断
我把架构文档、Claude 生成的总纲、概设、详设、规约全部拿出来横向对比,发现冲突集中在跨文档的业务规则一致性上:
| 冲突类型 | 出现频率 | 典型案例 |
|---|---|---|
| 枚举值不一致 | 高 | 概要设计定义 5 个状态,详设定义了 7 个 |
| 异常策略冲突 | 中 | 规约统一异常,详设按接口特化 |
| 命名不一致 | 高 | 同一个 DTO 在概设叫 OrderInfo,详设叫 OrderDetailDTO |
| 接口参数遗漏 | 中 | 概设定义了分页参数,详设接口签名里丢了 |
根因
Claude 不是真正"理解"业务,它是在做跨文档的模式匹配。 当同一个概念在多份文档中以不同粒度、不同角度出现时,Claude 没有"这是同一件事"的强约束意识。它只是分别处理每份文档,然后"拼凑"输出。
换句话说:人类看文档会建立"同一个概念"的心智模型,Claude 不会。 它对每份文档的 attention 是均等的,不会自动识别"总纲里的'订单状态'和概设里的'订单状态机'是同一个东西"。
text
人类的理解路径:
总纲"订单状态" → 概设"订单状态机" → 详设"OrderStatus枚举"
↓ ↓ ↓
三者是同一个概念,必须一致 ← 这是人类的直觉
Claude 的处理路径:
总纲"订单状态" → 独立理解 → 输出涉及订单状态的描述
概设"订单状态机" → 独立理解 → 输出涉及状态机的描述
详设"OrderStatus枚举" → 独立理解 → 输出枚举定义
↓
三者之间没有强制一致性约束 ← 冲突的源头
第二坑:上下文长了,Claude 开始"忘记"参考文档
现象
按模块开发时,我的流程是先让 Claude 生成该模块的 PRD(接口清单、数据模型、异常处理约定),审阅通过后再让它写代码。总纲 + 概设 + 详设 + 开发规约全部作为上下文持续存在。
开发第二个模块时也不错。但到第三个模块,问题来了------不仅是代码偏了,连模块 PRD 本身都开始偏了:
- 模块 3 的 PRD 里,接口路径风格从
/api/v1/order变成了/order/api/v1 - 异常处理方式退化成了 Claude 自己的"默认习惯",完全忽略了规约里"统一抛 BusinessException"的约定
- 我需要在每次对话开头反复说"请参考之前提供的《开发规约》",它才能勉强回到正轨
PRD 偏了,代码必然偏。 这个问题比代码写歪更致命------因为 PRD 在我眼里是"审阅过的施工图",我默认它是正确的。结果代码写出来跑不通才往回追,发现 PRD 本身就和规约冲突了。
诊断
统计了一下,开发 5 个模块的过程中,我明确提醒 Claude "参考之前文档"的次数:
模块 1:0 次(文档刚喂,新鲜)
模块 2:1 次(开始出现小偏离)
模块 3:3 次(大量偏离,需要反复强调)
模块 4:4 次(几乎每次输出后都要纠正)
模块 5:放弃治疗,手动修改
根因
这背后是两个问题叠加:
问题一:上下文窗口的"稀释效应"
Claude 的上下文窗口虽然大,但不是所有内容的"权重"都一样。当对话轮数增加,早期的参考文档逐渐被推到上下文深处,Claude 对这些内容的"注意力"自然降低。
text
对话开始时:
[架构文档][总纲][概设][详设][规约][用户指令1] ← Claude 注意力均匀
对话进行中(第 5 轮):
[架构文档]...[总纲]...[概设]...[详设]...[规约][指令1][代码1][指令2][代码2][指令3]...
↑ 距离当前轮次越来越远,注意力越来越弱
问题二:Claude 的"渐进式漂移"
每次生成代码时,Claude 会参考最近生成的代码风格。当它生成的代码和规约有微小偏差时,下一轮它会把自己的偏差当作"正确示例"继续放大------这是一个自我强化的漂移过程。
text
轮次 1:生成代码,95% 符合规约 ✅
轮次 2:参考轮次 1 的代码 + 部分规约 → 90% 符合规约 ⚠️
轮次 3:参考轮次 2 的代码 + 少量规约 → 80% 符合规约 ⚠️
轮次 4:参考轮次 3 的代码 + 几乎忘记规约 → 60% 符合规约 ❌
问题三(更深也更隐蔽):核心业务逻辑偏差
前面说的主要是格式、风格层面的偏离------这类问题肉眼看得出来。但更让我头疼的是业务逻辑层面的偏差------代码编译通过、风格符合规约、接口签名全对,但跑起来的行为是错的。
这类问题很难举一个"漂亮的代码例子",因为它本质上不是某一行写错了,而是Claude 对整个业务场景的理解停留在文档的文本层面,缺少业务方脑子里的"隐含知识"。
举个例子:PRD 里写了"下单时校验库存并扣减",Claude 生成的代码确实做了这两件事------先查库存、再扣库存,代码结构没问题。但实际跑起来发现,高并发下会出现超卖。因为业务方默认的期望是"校验和扣减是原子的"------这个对业务方来说是常识,PRD 里不需要写。但对 Claude 来说,"先查再扣"和"原子扣减"是两种不同的实现方式,它只会选它见过更多的那个。
再比如订单状态流转------PRD 里写了标准路径 PENDING → PAID → SHIPPED。Claude 按这个写了状态机,没问题。但业务方后来提到"已支付但超时未发货的订单,客服可以介入取消",这是个隐藏分支,不在 PRD 里。Claude 不可能知道,生成的代码就没处理这个场景。
核心矛盾 :PRD 写的是"显式规则",但真实业务里存在大量"隐式规则"------业务方的默认假设、历史遗留逻辑、口头交代的边界条件。这些东西不会出现在任何文档里,但对 Claude 来说,文档之外的世界不存在。
这类问题比格式偏离危险太多------风格偏了肉眼看得到,业务逻辑偏了要跑完整测试、看真实数据才能发现。对于复杂业务场景,Claude 写出"看起来完全正确但逻辑错误"的代码,是比语法错误更隐蔽的坑。
第三坑:你以为"增量开发",Claude 在"重新发明"
现象
完成模块 1 后,我想让 Claude 开发模块 2,并期望它复用模块 1 的基础设施代码(如公共工具类、BaseController、统一异常处理器等)。
结果 Claude 在模块 2 里重新写了一套异常处理逻辑,和模块 1 里已经写好的完全重复,实现方式还不一样。
诊断
我对比了两个模块的代码:
rust
模块 1(手动定义的基础设施):
├── BaseController.java
├── GlobalExceptionHandler.java ← 统一异常处理
├── BusinessException.java
└── Result.java ← 统一返回体
模块 2(Claude 生成的代码):
├── OrderController.java ← 没继承 BaseController
├── OrderExceptionHandler.java ← 又写了一套异常处理!
└── OrderResult.java ← 又定义了一套返回体!
模块 2 不仅没有复用模块 1 的基础设施,还重复发明了功能等价但实现不同的组件。
根因
Claude 没有"项目已经有什么"的全局视图。每次交互它只能看到你喂给它的上下文。我没把模块 1 的代码结构喂给它,它自然不知道基础设施已经存在。
这不是 Claude 的错,是我的 prompt 策略没跟上。 我以为"按模块开发"是自然而然的增量过程,但对 Claude 来说,每次都是重新开始。
改进方案:我是怎么把这件事做对的
复盘之后,我调整了策略,重新走了一遍流程。以下是实测有效的改进方案:
改进一:建立"单一事实来源"------文档合并 + 显式约束
核心思路 :不让 Claude 同时读多份文档,而是由我先把文档合并成一份结构化的"事实来源",消除多文档之间的歧义。
markdown
# 项目事实来源(喂给 Claude 的 unified spec)
## 业务实体定义
- 订单状态:PENDING / CONFIRMED / PROCESSING / SHIPPED / COMPLETED / CANCELLED(共6个,不可增减)
- 支付状态:UNPAID / PAID / REFUNDING / REFUNDED
- ...
## 统一异常策略(强制)
- 所有 Controller 抛出的异常统一使用 BusinessException
- 参数校验失败使用 ValidationException(ExceptionHandler 中统一处理)
- **禁止**在业务代码中 catch 后 return null,必须抛异常
## 命名规范(强制)
- DTO 命名:{Entity}{Action}DTO(如 OrderCreateDTO)
- Service 接口命名:I{Entity}Service
- Controller 路径:/api/v1/{entity}
效果:多文档冲突问题基本消除。因为冲突的源头(同一个概念在不同文档中有不同描述)被我在预处理阶段消除了。
改进二:分层 Prompt 策略------每轮强制注入"锚点"
核心思路:不在对话开头一次性喂完所有文档。而是每轮对话都强注入当前模块需要的"最小规则集"。
text
改进前(一次性注入):
[总纲 + 概设 + 详设 + 规约] → 对话 1 → 对话 2 → 对话 3 → ...
↑ 锚点逐渐丢失
改进后(每轮注入):
对话 1:[当前模块详设 + 规约摘要] → 生成模块 1 代码
对话 2:[当前模块详设 + 规约摘要 + 模块 1 接口清单] → 生成模块 2 代码
对话 3:[当前模块详设 + 规约摘要 + 模块 1/2 接口清单] → 生成模块 3 代码
每轮注入的"规约摘要"控制在 200 行以内,只包含和当前模块相关的规则。宁可多花 30 秒整理上下文,也不让 Claude 在 5000 行的上下文里自己找规则。
效果:偏离率从模块 3 开始就回升的曲线,变成了始终保持 90%+ 的一致性。
改进三:基础设施"锁定"------先让 Claude 知道有什么,再让它写
核心思路:在开发每个模块之前,显式告诉 Claude 项目已有的基础设施。
text
# 每个模块开发前的 prompt 模板
## 已有基础设施(直接使用,不要重新发明)
- 异常处理:GlobalExceptionHandler(路径:com.xxx.exception.GlobalExceptionHandler)
- 统一返回体:Result<T>(路径:com.xxx.common.Result)
- 基础 Controller:BaseController(路径:com.xxx.controller.BaseController)
→ 所有新 Controller 必须继承 BaseController
## 已有模块接口清单(如需调用)
- 用户模块:UserService.getById(Long id)
- 权限模块:AuthService.checkPermission(Long userId, String resource)
效果:重复造轮子的问题彻底消失。而且因为 Claude 知道了已有的接口,模块间的调用代码也是一次生成对的。
改进四:加入校验节点------不要让 Claude 的产出直接进代码库
这是最关键的一步。 改进后的流程中,我在三个节点设了人工校验:
text
1. 详设产出校验:逐项对比概设,检查枚举值、接口签名、异常策略的一致性
2. 规约产出校验:和详设交叉验证,重点看异常处理是否自相矛盾
3. 模块代码校验:CheckStyle / ArchUnit 自动检查 + 核心业务逻辑走查
→ 重点走查:金额计算、状态流转、权限判断、优惠券/积分等敏感规则
→ Claude 最容易在这些地方写出"看起来对、逻辑错"的代码
效果:校验成本远低于修复成本。花 10 分钟校验比花 2 小时修 BUG 划算得多。
改进后的完整流程
text
架构设计文档
↓
┌─ 人工整理为"统一事实来源" ─┐
│ (消除多文档冲突) │
└─────────────────────────┘
↓
┌──────────────────────────────┐
│ Claude 生成总纲 │
│ Claude 生成概设 │
│ Claude 生成详设 ──→ 人工校验节点①
│ Claude 生成开发规约 ──→ 人工校验节点②
└──────────────────────────────┘
↓
┌──────────────────────────────┐
│ 按模块生成 PRD + 开发 │
│ (分层 prompt 策略) │
│ │
│ 模块 1: [规约摘要] → PRD → 代码 │
│ 模块 2: [规约摘要+模块1接口] → │
│ PRD → 代码 │
│ 模块 3: [规约摘要+模块1/2接口] → │
│ PRD → 代码 │
│ 每个模块 PRD + 代码 → 校验节点③ │
└──────────────────────────────┘
核心认知:Claude 是"高级执行者",不是"架构师"
做完这次实战,我最深的体会是:
| 环节 | Claude 能做的 | Claude 做不好的 | 人必须做的 |
|---|---|---|---|
| 理解业务 | 从文档中提取描述 | 跨文档保持一致性 | 定义"唯一事实来源" |
| 产出设计 | 基于模板大量产出 | 保证设计之间的约束不冲突 | 校验跨文档一致性 |
| 写代码 | 单模块内高质量产出结构代码 | 核心业务规则容易遗漏或写错 | 定义业务规则 + 关键路径走查 |
| 复用代码 | 给了接口清单就能用 | 不知道已有什么 | 维护"已有组件清单" |
| 业务逻辑 | 能生成"看起来对"的代码 | 金额/状态/权限等敏感逻辑易出错 | 重点走查 + 单元测试覆盖 |
一句话总结 :Claude 能高质量地执行一个被明确定义的任务,但无法在没有人类"约束框架"的情况下自主保证大型工程的一致性。你的工作不是"让 Claude 替代你写代码",而是为 Claude 搭建一个它不会跑偏的执行环境。
适用场景建议
基于这次经历,我给不同规模的工程需求一个建议:
| 场景规模 | 推荐方式 | 关键动作 |
|---|---|---|
| 单模块独立开发 | Claude 直接上,效果好 | 给清楚需求和上下文即可 |
| 2-3 个关联模块 | Claude + 规约注入 | 每个模块都要注入核心规则 |
| 5+ 模块协同 | Claude + 统一事实来源 + 分层 prompt | 前置工作比开发工作还重要 |
| 系统级重构 | 不建议全靠 Claude | 先用 Claude 做分析和评审,开发自己来 |
本文基于真实项目经历写成。AI 工具的能力边界是试出来的,不是听来的。如果你也正在尝试用 AI 辅助复杂工程开发,欢迎交流踩坑经验------踩过的坑才是真正的护城河。