技术文档怎么写——我用过最有效的技术文档结构
技术文档怎么写——我用过最有效的技术文档结构
适读人群:经常需要写技术文档但不知道从哪里下手的工程师 | 阅读时长:约15分钟 | 核心价值:几套经过实战验证的技术文档模板,直接拿去用
我对技术文档有一个坚定的观点:大多数工程师写的技术文档,都写错了重点。
他们写的是"技术是什么",而不是"读者需要知道什么"。
结果是:文档写了很多,但没有人爱读,没有人真正用,最终沦为需要手动同步但永远不准确的"历史文件"。
这篇文章我想讲讲,我用过的几套技术文档结构,以及更重要的——怎么让文档真正被人用起来。
先说一个反直觉的观点:好文档不等于长文档
工程师有一种错误的判断标准:文档越详细、越长,就越好。
这是不对的。
文档的好坏,应该用一个标准来衡量:读者能不能在5分钟内找到他需要的信息,并且能正确执行相应的操作?
如果一份文档很长,但读者每次查的时候都要花20分钟翻来翻去、找不到关键信息,这份文档是失败的。哪怕它覆盖了每一个技术细节。
好文档的核心属性:
- 可发现:读者能快速找到他要找的部分
- 准确:内容和实际情况一致
- 够用:包含了读者需要的信息,不多也不少
- 可维护:更新成本低,能跟上代码的变化
几种常见的技术文档及其结构
类型1:API 文档
API 文档是使用频率最高的技术文档,读者通常是调用这个 API 的开发者,他们需要快速找到"如何调用"和"会发生什么"。
我推荐的结构:
接口概述(一句话)
查询用户的订单列表,支持按状态和时间范围过滤。
接口信息
- Method: GET
- Path: /api/v1/users/{userId}/orders
- 认证:Bearer Token(必须)
请求参数
| 参数名 | 类型 | 是否必须 | 说明 |
|---|---|---|---|
| userId | Long | 是 | 用户ID,从URL路径中获取 |
| status | String | 否 | 订单状态,可选值:PAID/SHIPPED/COMPLETED/CANCELLED,默认返回所有状态 |
| startDate | String | 否 | 开始日期,格式:yyyy-MM-dd |
| pageSize | Integer | 否 | 分页大小,默认20,最大100 |
响应示例
成功响应(200):
{
"code": 0,
"data": {
"total": 42,
"orders": [
{
"orderId": "2024032100001",
"status": "PAID",
"amount": 99.00,
"createdAt": "2024-03-21T10:30:00+08:00"
}
]
}
}错误响应:
- 401:Token 无效或过期
- 403:无权限查询该用户订单
- 404:用户不存在
注意事项
- 每次最多返回100条,超过请使用分页
- 历史订单仅保留3年
这个结构的关键是:示例优先。工程师看 API 文档的方式,通常是先看示例,确认大概的格式,再去看参数细节。把示例放在醒目的位置,会让文档的使用效率大大提高。
类型2:架构设计文档(ADR)
ADR(Architecture Decision Record)是我认为最被低估的技术文档形式。它记录的不是"系统是什么",而是"我们为什么这样设计"。
标准的 ADR 格式:
# 使用 Kafka 替换 RabbitMQ 作为消息队列
状态:已采用(2024-03-15)
## 背景
随着用户规模增长,消息队列的日消息量从100万增长到5000万,
RabbitMQ 的吞吐量瓶颈和运维复杂度问题日益突出。
## 决策
迁移到 Apache Kafka 作为主要消息队列。
## 考虑过的选项
### 选项A:升级 RabbitMQ 集群
优点:迁移成本低,团队已熟悉
缺点:吞吐量上限有限,不支持消息持久化重放
### 选项B:迁移到 Kafka(采用)
优点:高吞吐(单机可达百万 TPS)、消息持久化、支持消费者组
缺点:运维复杂度高,学习曲线陡峭
### 选项C:使用云厂商托管 MQ
优点:运维压力小
缺点:成本高,且与厂商绑定
## 理由
当前消息量已超出 RabbitMQ 的实际吞吐上限,且业务有消息回放需求(用于数据修复),
Kafka 的这两点优势是决定性的。运维复杂度问题通过引入云服务商的 Kafka 托管服务来缓解。
## 后果
- 需要3个月完成平滑迁移
- 团队需要培训 Kafka 的使用和运维
- 消费端代码需要改造(从推模式改为拉模式)ADR 的价值体现在6个月或1年之后。新来的工程师看到系统在用 Kafka,会困惑:为什么用 Kafka 不用其他的?如果有 ADR,他5分钟就能了解背景,而不需要去问"当时在场的人"——而那些人可能已经不在了。
类型3:运维 Runbook
Runbook 是给操作者(开发/运维/值班人员)在紧急情况下使用的文档,核心是"怎么做",不是"为什么"。
Runbook 的结构:
# 数据库连接池耗尽处理手册
## 识别方法
- 告警:ConnectionPoolExhausted 告警触发
- 或症状:大量请求返回"获取数据库连接超时"
## 快速检查
1. 查看当前连接数:
SHOW STATUS LIKE 'Threads_connected';
(正常值 < 80,超过100需要处理)
2. 查看等待连接的线程:
SHOW PROCESSLIST;
## 处理步骤
### 临时缓解
1. Kill 占用连接最久的查询:
KILL QUERY [processId];
2. 如果以上不够,临时提高最大连接数:
SET GLOBAL max_connections = 200;
(注意:这是临时措施,重启后失效)
### 根本解决
通常是以下原因之一:
- 连接池配置太小 → 检查 hikari.maximum-pool-size 配置
- 慢查询占用连接时间过长 → 使用 EXPLAIN 分析慢查询
- 连接泄漏 → 检查是否有未关闭的连接
## 恢复验证
处理后观察5分钟,确认:
- Threads_connected 回落到正常范围
- 应用层无新的连接超时告警
## 升级处理
如果以上步骤无效,联系 DBA(@王DBA)Runbook 的关键特点:
- 命令要直接可复制,不要只说"查看连接数",要给出具体命令
- 把预期结果写出来("正常值 < 80"),让操作者知道自己看到的是否正常
- 给出升级路径,当自己处理不了时知道找谁
类型4:新人上手文档(Onboarding Guide)
这类文档的读者是刚加入团队的工程师,他们需要:快速了解系统全貌,能独立完成第一个任务。
结构:
系统概述(不超过一段话)
我们的核心业务是XXX,技术栈是 Java/Spring Boot + MySQL + Redis + Kafka,主要包含3个服务:用户服务、订单服务、支付服务。
本地开发环境搭建 逐步骤,精确到命令,确保一个完全没有上下文的人能跑通。这部分要经常更新,因为依赖和配置会变。
代码结构说明
- 主要的包结构和每个包的职责
- 核心业务流程(用流程图或时序图)
第一个任务建议 推荐1-2个适合新人的真实任务,帮助他在有意义的上下文中学习。
团队规范
- 分支策略
- Commit Message 规范
- PR 要求
- 代码风格要求
常见问题 把新人常见的困惑和问题提前收集进来,每次有新人问了新问题,就更新这个列表。
让文档真正被用起来的关键
写完文档只是开始。让文档真正被用起来,才是目的。
关键1:文档要放在人们会找的地方
不要把文档放在一个"正确的"但没有人知道的地方。要放在工程师日常工作流中自然会接触到的地方:代码仓库的 README、Confluence、团队 Wiki、Notion……哪里有流量就放哪里。
关键2:文档要有入口
把重要文档的入口放在明显的位置:README 里加链接,新人入职时主动介绍,定期在团队内提及。没有入口的文档,等于不存在。
关键3:文档要有"最后更新时间"和负责人
没有更新时间的文档,读者不知道这个信息是不是已经过期了。没有负责人的文档,出了问题没有人会去更新它。这两个信息,每篇文档都必须有。
关键4:宁可文档少而精,不要多而杂
我见过一些团队,有几百篇技术文档,但大多数已经过期了,没有人维护。结果是:工程师对所有文档都失去了信任,遇到问题还是去问人,文档形同虚设。
不如精心维护10篇核心文档,保证它们永远准确,比拥有500篇过期文档更有价值。
关键5:把文档更新纳入工作流
每次改代码或者改流程,对应的文档也要同步更新。把这个要求纳入 PR checklist("是否需要更新文档?"),让文档更新成为开发流程的一部分,而不是事后补的工作。
