技术文档写作效率心法:写文档不是浪费时间,是省时间
一、"代码即文档"——三个月后你自己也看不懂
我见过太多这样的场景:开发者说"我的代码自解释,不需要文档"。三个月后他休假了,接手的那个人花了两个全天来理解那段"自解释"的代码逻辑。这两个全天的成本远超当初花 2 小时写一份设计文档。
但另一个极端同样糟糕:为了文档而文档,写出来的内容是代码的 plain English 翻译——"这个循环遍历了数组"——完全多余。
高效文档的关键不是"写得多",而是写得对地方、写得让读者 5 分钟能上手。
flowchart TD A[文档需求] --> B{读者是谁?} B --> C[新加入的开发者] B --> D[调用方/API 使用者] B --> E[运维/SRE] B --> F[我自己/3 个月后] C --> C1[架构概览 + 本地启动 + 核心流程] D --> D1[API 契约 + 示例 + 错误码] E --> E1[部署方式 + 配置项 + 健康检查端点] F --> F1[设计决策 + 为什么这么写] C1 & D1 & E1 & F1 --> G{文档形式} G --> H[README: 启动 + 概览] G --> I[API 文档: 自动生成] G --> J[RFC/Design Doc: 设计决策] G --> K[代码注释: 为什么]二、五种文档的定位与写法
README.md
长度:5 分钟内能读完
内容:是什么 → 怎么启动 → 核心概念 → API 入口
不写什么:不需要写"代码结构"——IDE 能展示的东西不写
API 文档
自动生成,不要手写。用 OpenAPI/Swagger 从代码注解生成。手写 API 文档的第一天就过时了。
架构决策记录(ADR)
最重要的文档类型。记录每次重大的技术决策:
- 背景:为什么需要做这个决定
- 选项:考虑了哪些方案
- 决策:选了哪个 + 为什么
- 后果:这个选择带来的影响
代码注释
只写"为什么",不写"是什么"。注释回答"为什么这里用sort.Slice而不是sort.Sort"——而不是"这里对切片排序"。
故障排查 Runbook
价值最高的运维文档。格式是:症状 → 可能原因 → 检查命令 → 修复步骤。每条不超过 10 行。
三、高效文档的模板
ADR 模板(最值得套模板)
# ADR-{序号}: {一句话描述决策} - **状态**: {提议 / 已接受 / 已废弃 / 已替代} - **日期**: YYYY-MM-DD - **决策者**: {名字} - **替代**: ADR-{被替代的 ADR 编号}(如有) ## 背景与问题 {2-3 句:为什么需要做这个决定?现状有什么问题?} ## 考虑的方案 ### 方案 A: {名称} - 优点: ... - 缺点: ... - 成本: ... ### 方案 B: {名称} - 优点: ... - 缺点: ... - 成本: ... ## 决策 **选择方案 X**,因为 ... ## 后果 - 正面影响: ... - 负面 tradeoff: ... - 如果这个决定被证明是错的,怎么回退?Runbook 模板
# Runbook: {服务名} ## 症状 1: 服务 P99 延迟突然升高 **判断**: 检查 Grafana Dashboard `{link}` **可能原因**: 1. 下游服务超时 → 检查 `${service}_upstream_latency` 2. GC 频繁 → 检查 `${service}_gc_duration` 3. 线程池耗尽 → 检查 `${service}_thread_pool_active` **排查步骤**: ```bash # 1. 检查下游依赖 curl http://{service}:8080/health/dependencies # 2. 检查慢请求日志 kubectl logs -l app={service} --tail=100 | grep "SLOW"修复步骤:
- 如果是下游超时 → 临时降级到缓存
- 如果是 GC → 滚动重启(rolling restart)
- 如果是线程池 → 调整线程池参数 + 发布
症状 2: 错误率 > 1%
...
## 四、文档维护的心法 ### 原则一:文档越靠近代码,更新概率越高 README 在代码仓库里比 Wiki 更新率高 10 倍。把文档和代码放在同一个 PR 里——改代码必须改文档。 ### 原则二:文档应该能自动验证 API 文档自动生成不会过时。README 中的命令示例应该能在 CI 中执行验证(`npm install && npm start`)。代码片段用 `<!-- testable -->` 标记。 ### 原则三:过时的文档比没有文档更危险 没有文档你会去看代码。过时的文档会给你错误信息。定期检查文档的"最后更新日期"——超过 6 个月没更新且有活跃代码变更的模块,文档标记为"可能过时"。 ### 原则四:文档不是一次性产出 用 DACI 模型分配文档责任: - **Driver**:谁驱动这个文档的创建 - **Approver**:谁批准 - **Contributor**:谁提供输入 - **Informed**:谁需要被告知文档更新 ## 五、总结 高效文档的核心不是"写得好",是**写得对**——对的类型(README vs ADR vs Runbook)、对的读者(新人 vs 运维 vs 未来自己)、对的时机(代码变更时同步更新)。写文档的时间投入不是成本,是对未来自己和同事时间的预支。花 2 小时写一份好的 ADR,可能省下未来 20 个小时的无效讨论。