设计文档(Design Doc)是软件工程中最被低估的技能之一。一篇好的设计文档可以节省数年的开发时间——不是夸张,而是因为它强迫你在写代码之前想清楚关键决策,避免在错误的实现上浪费精力。
Michael Lynch 曾在 Google、Microsoft 任职,现在经营自己的公司。他最近分享了一套经过大厂验证的设计文档方法论。
什么时候该写设计文档?
Lynch 给了一个实用的判断框架。如果以下任何问题你回答"是",就该写:
- 需要多人协作实现?
- 项目周期超过三个月全职开发?
- 实现后会在生产环境运行数年?
- 涉及跨团队协作?
- 项目目标和需求模糊?
- 存在可在设计阶段预防的灾难性风险(安全漏洞、法律风险)?
回答一个"是"→ 值得写。两个以上→ 几乎肯定值得写。
投入多少精力?
设计文档可以是一页纸,也可以是 50 页需要五个团队签字的文档。没有 universal rule。
Lynch 的核心原则是:用"错误的代价"来决定粒度。
不是所有设计决策都同等重要。有些选择一旦错了很难回头(比如用 C++ 写了 20 万行后发现 Ruby on Rails 更合适),有些则 trivial(列表分页用 "Load more" 还是无限滚动,几小时就能改)。
判断标准:如果选错了,修正成本有多高? 高成本决策进文档,低成本决策不必浪费笔墨。
设计文档的核心组件
Lynch 列出了常用章节,但强调不需要每篇文档都包含所有章节,按需选择:
标题
要短、有特色、能代表项目概念。比如给缓存层起名 "RecencyBank" 就很好——好念、好记、有意义。"Project Flying Silver Horse" 就烂透了。
元数据
作者、创建时间、权威 URL。如果是用短链接系统(如 go/links),把短链接也写上。
目标(Objective)
一句话说明项目目的,放在第一页,用任何利益相关者都能听懂的语言。
示例:通过在 Trogdor Web 服务器和 Postgres 数据库之间增加缓存层,提升应用性能。
背景(Background)
回答三个问题:为什么做这个项目?解决什么问题?之前尝试过什么方案?
关键检验:没有外部上下文,你的文档能独立理解吗? 想象读者没听过你的口头解释,第一页就要把来龙去脉讲清楚。
目标与非目标(Goals & Non-goals)
Goals 描述项目完成后世界变成什么样。注意要用用户/团队/公司受益的角度表达,而不是实现细节。
Non-goals 明确划定边界——哪些东西读者可能误以为是项目范围,但其实不是。
其他可选章节
- 场景(Scenarios):用户如何使用这个功能
- 图表(Diagrams):架构图、数据流图
- 术语表(Glossary):避免歧义
- 约束(Constraints):技术、业务、法律限制
- SLO(服务等级目标):可用性、延迟、吞吐量指标
- 监控/告警(Monitoring/Alerting):怎么知道系统出问题了
- 时间线(Timeline):里程碑和交付日期
- 接口(Interfaces):API 契约、数据格式
- 依赖/基础设施(Dependencies):外部系统、所需资源
- 安全、隐私、法律(Security/Privacy/Legal):合规要求
- 日志(Logging):审计和调试需要记录什么
- 未决问题(Open Issues):还没决定的点
- 已解决问题(Resolved Issues):曾经讨论过并决定的问题
- 备选方案(Alternatives Considered):为什么选了 A 而不是 B
给 Agent 开发的启示
这套方法论对 AI Agent 系统开发同样适用。Agent 的 SKILL.md 本质上就是一种轻量级设计文档——它定义了 Agent 的能力边界、工作流、输入输出规范。
Lynch 强调的"用错误代价决定粒度"原则,可以直接迁移到 Skill 设计:Agent 的每个决策点,如果选错了会导致严重后果(比如错误调用生产环境 API),就应该在 Skill 里明确约束;如果是 trivial 的选择(比如输出格式微调),交给 Agent 自主决定即可。
设计文档不是 bureaucracy,是在正确的时间用正确的粒度做正确的决策。