我去年夏天做的一个仓库浏览器,第一周有八个提交。前四个没碰一行应用代码:是从我的模板初始化,加上三个文档提交。第五个就是整个应用了。
这不是自律。而是在写文档的过程中我发现自己对这个集成的心智模型是错的,而在一个 .md 里改它只要二十分钟,不是两天。
在外部集成里从代码开始的错误
当逻辑是你自己的时候,读代码是最好的文档。当它依赖外部 API 时就不是了:你需要知道的东西既不在你的代码里,也不在他们的代码里。它在那些限制、配额和废弃参数里。
在那个浏览器里,我有一阵子把同一家供应商的两种连接搞混了。登录的 OAuth 和用来读 API 的服务端 token 看起来一样,其实不是。一个是让人进来的,另一个是让服务器读的。它们失败的方式不同。把它写成文档里分开的两节,才让我看清一个公开仓库浏览器只需要第二个。
要是从代码开始,我会在第三个 401 的时候才发现这件事。
在第一行代码之前我具体记录什么
我不记录我应用的设计。我记录我控制不了的东西。具体来说:
- 真实的、测量过的限制,不是引用来的。 从网站上抄一句"每小时 5000 次请求"不够。我去配额端点问了:未认证 60/小时,认证 5000/小时,搜索 30/分钟。而且我测出了
304 Not Modified不消耗配额——带条件请求时是 4972、4972、4972,同一个调用去掉If-None-Match后是 4971。那个重复出现的数字是整份文档的核心论据,不去执行你就拿不到它。 - 无法自动化的东西。 OAuth App 不能用 CLI 创建:既没有创建它的端点,也没有读取 client secret 的端点,后者在浏览器里只显示一次。这是一个手工步骤,而你重新搭环境那天早就忘了。
- 在生产里会让你吃惊的上限。 每小时 2000 次 token 创建,这是登录次数的天花板,不是请求次数的。以及如果一个用户一小时内登录十次会被强制重新授权。读 happy path 的时候这两个都不会出现。
- 这个决定没有解决什么。 我记下了强制登录并不能消除条件缓存的必要性,因为用户的配额桶和他的 PAT 以及其他代表他行事的应用是共享的。如果不写下来,这个决定会给你虚假的安全感。
这些都不是可以有不同意见的东西。它们是事实,你要么去验证,要么去编造。
cookbook:在集成之前单独测每一块
在一个做文档分析的 AI 服务里,我换了种形式做同样的事。在任何一块进入服务之前,每一块都有一个 cookbook:一个单独运行它的脚本,把输出写到一个目录,并注册进 run_all_cookbooks。PDF 解析器、chunker、embedding、数字检测器、可验证抽取。一块一个。
价值不在于测试。而在于当 chunker 的输出形状变了时,你能在一个文本文件里看见,而不是在三层之上的一次报错里。当流水线改成异步时,cookbook 变成了带 asyncio.run 的 runner,迁移是一块一块做的,不是一次性的。
代价是它们失效时必须删掉。几个月后有一个提交移除了已废弃的 cookbook。一个不再对应那一块的 cookbook 比没有更糟。
把文档当作之后审计的真相来源
在一个 UI 概念展示库里,我先写了这套件的设计指南——尺码、间距阶梯、灰阶、什么场景用哪个基础元件——然后对照它审计代码。
有意思的是,审计修正了指南,而不只是代码。.md 少说了三件事:陪衬的灰色分五个层级而不是两个;间距阶梯有四级而不是三级,因为叫它三级会把六处正当用法变成偏离;还有三个对话框其实是同一个对话框,同样的盒子、同样的头部,而正因为没说清楚,修正只被应用到了其中一个。
没有事先的文档,这三个发现就不存在。你没有可对照的东西,你找到的一切都只是"我觉得"。
什么时候这是浪费时间
我用的标准:
- 如果这个集成从头到尾都是你自己的,别先写文档。 代码就是真相,而文档会过期。
- 如果是个要扔掉的原型,也别写。 我用一天写的一个游戏什么文档都没有,这样挺好。
- 如果文档只会重复官方参考说的话,别写它。 它只有在包含你的测量、你的版本和你踩到的坑时才有价值。
还有一个让我付出代价的错误:事先写的文档里带着你的假设。在那个浏览器里,托管那一节描述的是一个 serverless 平台,因为我起草任务时想当然,而不是因为有人做过这个决定。改成长期运行的容器之后,整个结论都变了:在 serverless 上,agent SDK 放不下;在一个请求上限十五分钟的 worker 里,放得下。
所以下一步不是可选的。有一个提交唯一的工作就是对照活的来源验证文档:执行指南里出现的那个查询、发一个无效的 API 版本让 API 自己列举有效的版本、确认 per_page=500 被悄悄截成 100、给那个在严格模式下编译不过的片段加上类型。那个提交发现返回的 20 个 "issue" 里有 18 个其实是 pull request。
未经验证的文档是一个格式漂亮的假设。经过验证的文档是这个集成里唯一在六个月后不会骗你的部分。
