文档不是写给 AI 看的,是写给人看的——一个网易服务端老油条的文档工具实践

产品和代码之间
2025-12-13 07:33
阅读 781

上周五晚上 9 点半,我还在公司加班。
不是因为上线事故(感谢菩萨保佑),而是被产品经理甩过来一份“需求变更说明”——整整 37 页 Word,字体混用、截图模糊、逻辑跳跃得像刚跳完《舞力全开》。我翻了三遍都没搞懂他到底要改哪个接口,最后直接拉群问:“你这个‘玩家状态同步优化’,到底是客户端发还是服务端推?”

群里沉默了两分钟。
然后他回了一句:“文档里写了啊。”

那一刻,我真的想把键盘砸进工位下面的泡面箱里。


我是网易游戏的一名服务端开发,入职快三年了,参与过两款 MMORPG 和一款二次元手游的后端架构。我们组在北京中关村某栋楼的 18 层,通勤一小时起步,日常和 Redis、Kafka、Protobuf 打交道,偶尔还要跟运维抢 CPU 配额。说真的,代码写得好不好,大家都能忍;但文档写得烂,是真的会死人的——尤其是线上出问题时,没人有时间猜你当初是怎么设计的。

去年双11期间,我们一个核心战斗服突然 CPU 飙到 90%,告警刷屏。我翻遍 Git 提交记录和 Confluence,愣是找不到关于“技能冷却校验逻辑”的任何说明。最后靠 grep + 日志硬啃源码,花了三个小时才定位到一个竞态条件 Bug。那晚回去的路上,我在地铁上发了个朋友圈:“求求你们,写点能看的文档吧。”

从此,我开始认真研究:怎么才能让团队写出又快又好、还能长期维护的文档?

文档 ≠ 写作文,而是工程基建

很多人以为文档就是“写点说明”,但在我眼里,好的文档系统 = 可版本控制 + 自动化生成 + 易协作 + 强可读性。它不该是项目快上线时临时抱佛脚的附属品,而应该是和 CI/CD、监控告警一样重要的工程基础设施。

我们组之前用 Confluence,好处是富文本编辑方便,坏处是——根本没法和代码仓库联动。谁改了接口,文档不一定更新;文档更新了,代码不一定同步。更别提历史版本混乱、搜索弱鸡、多人编辑冲突……有一次测试同学按文档调接口,结果发现字段名少了个下划线,直接提了个 P0 Bug。我查了一圈,发现文档是三个月前实习生写的,人早就跑了。

于是,领导拍板:“搞个新方案,年底前落地。”

技术选型:为什么我们最终选了 MkDocs + Material?

一开始,我调研了一堆工具:

  • Confluence:富文本友好,但和代码脱节,权限管理复杂。
  • GitBook:颜值高,但免费版功能阉割严重,私有部署又麻烦。
  • Docusaurus:React 生态,适合前端项目,但我们服务端全是 Go 和 C++。
  • Sphinx:Python 系老牌选手,但配置太重,学习曲线陡峭。

最后锁定了 MkDocs + Material for MkDocs

原因很简单:

  • 基于 Markdown,程序员天然亲和
  • 支持 Git 版本管理,文档和代码同库 or 同组织 repo
  • 主题 Material 极简美观,支持代码高亮、侧边导航、搜索
  • 轻量,一条 mkdocs serve 就能本地预览
  • 支持插件生态(比如自动 API 文档生成)

最重要的是——它符合我们“代码即文档”的哲学

我们现在的做法是:每个微服务项目根目录下建一个 docs/ 文件夹,里面放接口说明、部署流程、压测报告。CI 流程中加一步,每次 push 到 main 分支,就自动构建并发布到内部文档站点(用 GitHub Pages 或自建 Nginx)。

# .github/workflows/docs.yml
name: Publish docs via GitHub Pages
on:
  push:
    branches: [ main ]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Setup Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.10'
      - run: pip install mkdocs-material
      - run: mkdocs build
      - name: Deploy to GitHub Pages
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./site

这样,文档和代码一起 Code Review,一起上线,一起回滚。谁改了逻辑,就必须更新文档——否则 PR 过不了。

从“不想写”到“顺手写”:降低文档成本是关键

但光有工具不够。程序员最怕什么?重复劳动

所以我又搞了几个自动化小 trick:

1. 用 OpenAPI 自动生成接口文档

我们的 HTTP 接口都用 Gin 框架(Go),配合 swaggo/swag 注解,一键生成 OpenAPI spec:

// @Summary 获取玩家背包
// @Description 返回玩家当前背包物品列表
// @Tags player
// @Accept json
// @Produce json
// @Param player_id path int true "玩家ID"
// @Success 200 {object} pb.BagResponse
// @Router /player/{player_id}/bag [get]
func GetBag(c *gin.Context) {
    // ...
}

跑个命令:

swag init --parseDependency

就能生成 docs/swagger.yaml,再通过 MkDocs 插件 mkdocs-swagger-ui 直接嵌入页面。测试同学点开链接就能试调用,再也不用问我“这个字段是 string 还是 int”。

2. Protobuf 自动生成消息体说明

游戏里大量用 Protobuf 做通信。以前新人要理解协议,得翻 .proto 文件 + 问老人。现在我们用 protoc-gen-doc 插件:

protoc --doc_out=./docs/proto --doc_opt=markdown,proto.md *.proto

自动生成带字段说明、默认值、注释的 Markdown 表格。比如:

字段 类型 说明
player_id int64 玩家唯一 ID
items repeated Item 背包物品列表

新人第一天就能看懂协议结构,省了我至少 2 小时口述。

3. 文档模板化:拒绝自由发挥

我们还建立了几类标准模板:

  • 接口文档模板:包含路径、方法、请求/响应示例、错误码、鉴权方式
  • 部署手册模板:环境变量、依赖版本、启动命令、健康检查
  • 事故复盘模板:时间线、根因、影响范围、改进项

新人直接复制模板填空就行,不用纠结“该写啥”。甚至我把自己常被问的面试题整理成《服务端高频问答》,也放进文档站——毕竟,技术分享的本质,就是减少重复解释的成本

说到面试题,上周我帮 HR 筛简历,看到一个人写“精通微服务架构”,结果问他“服务间如何传递 trace ID”,答不上来。其实这个问题的答案,就在我司内部文档的《日志追踪规范》里。要是候选人提前看过,说不定就过了。所以我也在考虑,未来开放部分非敏感文档作为“技术品牌”展示——既能吸引人才,又能倒逼我们写得更清晰。

踩过的坑:文档不是越全越好

当然,过程也不是一帆风顺。

最早我们试图把所有东西都文档化:数据库建表语句、Nginx 配置、甚至 Jenkinsfile 注释……结果文档膨胀到没人敢改,因为“万一删错了呢?”

后来我们定了个原则:只写“别人需要知道的”,不写“我知道的”

比如:

  • ✅ 写:这个接口幂等性怎么保证?
  • ❌ 不写:我用了 sync.Map 而不是 mutex,因为……

另外,文档必须有明确 owner。我们每个服务指定一个“文档负责人”,每周站会 check 一次文档是否同步。离职交接时,文档完整性是硬指标——没写完?不好意思,delay 你的离职流程(笑)。

效果:从“救火”到“预防”

这套搞了半年,效果肉眼可见:

  • 新人上手时间从 2 周缩短到 3 天
  • 因文档不清导致的 Bug 下降 70%
  • 最近一次压测,运维直接按文档搭环境,没找我一次
  • 我自己的简历也更新了:“主导团队文档体系升级,提升协作效率”

对,没错,这些实践也能写进简历。现在大厂面试官越来越看重工程素养,光会 LeetCode 不够,还得证明你能 build 可持续的系统。我上周参加一个技术沙龙,主讲人提到:“一流的工程师写代码,超一流的工程师写文档。” 当时全场鼓掌——因为我们都吃过烂文档的亏。

最后一点真心话

有人说:“代码是最好的文档。”
我说:只有配上好文档的代码,才是最好的代码

工具只是手段,核心是尊重他人的时间。你花 10 分钟写清楚一个接口,可能帮同事省下 2 小时 debug;你整理一篇压测报告,可能避免下个月的线上雪崩。

至于那些总说“没时间写文档”的兄弟——醒醒,你每天花在解释“这玩意儿怎么用”上的时间,早就超过写文档的成本了。

顺便安利一本对我影响很大的书:《程序员修炼之道》(The Pragmatic Programmer)。里面有一章叫“DRY 原则与文档”,讲得特别透:文档不是重复代码,而是解释“为什么这么设计”。这本书我放在办公桌抽屉里,新人来了就借他看。

好了,今天就聊到这儿。
我要去改产品经理的新需求文档了——这次我直接甩给他一个 MkDocs 链接,让他在线编辑。

要是他再发 Word,我就把他加入我的《面试题挑战》黑名单 😏

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝