技术文档的失败方式非常具体,也非常好预测。有人在两周清闲的时间里写下一大堆,接着系统变了,没有人回头更新,一年之内那份文档就开始信心十足地讲着错误的内容。到了那个时候,它比什么都没有还要糟,因为相信它的读者会依据早已不成立的信息去动手。
常见的反应是号召大家多写一些,而这只会让同样的失败来得更快。有用的反应是少写,并且认真挑选写什么,因为真正的瓶颈不是写作的工夫,而是维护的工夫。文档从写完那一刻起,就开始被现实甩在后面。
判断一份文档该不该存在,唯一经得起时间的检验是: 当它变错的时候,会不会有人察觉?部署指南天天有人用,错误立刻就会浮出来。一份二十页的子系统说明只会被读一次,它的错误要等到十八个月后,有人照着它动手时才浮出来。没有人真正使用的文档只会悄无声息地腐烂,而恰恰是这一类文档应该一开始就不要写。
文档为什么会过期
有三种机制,其中只有一种可以叫做懒惰。
文档住在它所描述的东西之外。 改代码并不等于改一个维基页面,所以两者要保持一致,全靠有人记得。那份记性会稳定地失效,而且文档离代码越远,失效得越快。它在另一个工具里、另一套权限后面、另一个界面上,仅仅是这点距离就已经足够。
它写的是实现而不是意图。 一份解释某个组件当前如何运作的文档,每一次重构都会让它失效。而一份解释这个组件为什么存在、满足了什么约束的文档能活下来,因为原因变化的频率远低于代码。
没有人是它的主人。 属于所有人的文档其实不属于任何人,它的准确性从来不会在某个时刻变成某个具体的人的问题。
对策直接从原因推出来:把它放在代码旁边,写意图而不是机制,并且给每一份文档指定一个有名有姓的负责人,再给它一个真正会被拿出来使用的场合。
值得维护的技术文档
四份文档覆盖了大部分价值。其余的都必须自己证明存在的理由。
一份能让你把系统跑起来的 README。 这是什么、怎么配置、怎么跑测试、怎么发布。它一直在被使用,所以错误很快就会暴露。这是任何仓库里回报最高的一份文档,同时也是最常被原封不动留成项目模板、谁都没有编辑过的那一份。
一份架构概览。 主要的几块是什么、它们之间如何通信、为什么被分开。一页文字加一张图,描述形状而不是细节。它很少变动,却能回答那个问题:如果没有它,每一位新同事都得自己把所有代码读一遍再重新拼出答案。
决策记录。 简短的笔记,记下一个决定、考虑过的替代方案,以及做出选择的理由。业内通常称之为架构决策记录,简称 ADR。它们只增不改,永远不需要更新,并且能防止最昂贵的一类返工:把已经有结论的问题重新拿出来草率地争一遍,只因为没有人还记得当初拍板的那个约束。
针对会坏的东西的运维手册。 运维手册也就是 runbook,是故障处理的操作步骤:怎么诊断、怎么修复那些你真的遇到过的故障。它写于事故刚刚过去、记忆还新鲜的时候,并在下一次事故中接受检验。一份还没有人照着走过的运维手册,只是草稿。
请注意,这四份文档没有一份是在描述代码如何运作。那是代码自己的职责,任何用文字复述代码的段落都会变成第二个事实来源,迟早会和第一个互相矛盾。
为又累又赶时间的人写
大部分技术文档是在压力下被读到的,读者带着一个非常具体的问题,而且常常是在下班之后。请为这样的读者写,而不是为一个悠闲的读者写。
先给答案,再讲解释。 凌晨两点读你运维手册的人,需要的是命令,理由排在后面。把背景放在答案前面,这种结构只对作者方便,对其他任何人都不方便。
写得具体。 真实的命令、真实的路径、真实的示例值。“请配置合适的环境变量”不是一条指令,它只是对一条指令的描述。读者打开这一页,恰恰就是想知道合适指的是什么。
写清楚哪里会出错。 失败的形态以及它们看起来是什么样子,往往是整页里最有价值的内容,因为那正是读者此刻正在经历的东西。
短到足以保持正确。 每多一句话,就多一笔维护债务。一页只覆盖常见情况、并且坦白承认自己边界的文档,胜过一份覆盖了所有情况却在三处出错的文档。
让一个页面容易被检索系统引用的那套纪律,同样能让它对一位精疲力尽的同事好用,这正是我们那篇讲为什么你的内容有排名却从不被引用的文章在公开写作上想说的意思。
如何让它保持存活
把它放进仓库。 与代码一起移动的文档,会在与代码同一次评审里被改动,这是唯一能可靠让两者保持一致的机制。
在代码评审里一并检查。 如果某次改动让一份文档变错了,那就是一条和其他意见没有区别的评审意见。这是所有可用习惯里杠杆最大的一个,而且不花一分钱。
能测的就测。 能在流水线里真正跑起来的安装步骤,就不再是一厢情愿。如果你的 README 声称三条命令就能得到一个可运行的系统,那就让一个任务去证明它。
该删就删。 一份错误的文档比一份缺失的文档更糟,因为人们会信任它。当某样东西过时了而且没有人会去修,就把它移走,并记下丢掉了什么。
给会过期的东西标上日期。 任何带着版本号、价格或外部依赖的内容都应该带上日期,好让读者自己判断还能不能相信它。
这件事到底为了什么
文档是让知识不再依赖某几个人的机制。全部好处就在这里,所以主张写文档是一件生意上的事,而不是审美上的事。
一个只有一个人会部署的系统,它的恢复时间等于那个人的可用时间。一个没有人能说清理由的组件,要么被重建,要么被当作迷信保留下来。两者都会出现在技术尽职调查的问题清单里,两者都会拉长开发者入职的时间,而且两者其实是同一个问题换了身衣服。
Mecanik 在每一个项目的交接环节都会写下这些文档,这是我们软件开发工作的一部分。而最终真正被用起来的那份文档,几乎总是比当初要求的那份更短。
常见问题
技术文档为什么会过期? 因为它住在代码之外,两者是否一致全靠有人记得;因为它写的是实现而不是意图,每一次重构都会让它失效;也因为没有人是它的主人,它的准确性从来不是某个具体的人的问题。把它放进仓库,并在代码变更的同一次评审里检查,可以同时解决这三个原因。
软件团队应该维护哪些文档? 四样东西覆盖了大部分价值:一份能把系统跑起来的 README,一页说明形状与理由的架构概览,只增不改、记录当初为什么这么选的决策记录,以及针对你们真的遇到过的故障的运维手册。至于描述代码如何运作的内容,不在这份清单上。
什么是决策记录? 一段简短的笔记,记下一个决定、考虑过的替代方案,以及做出选择的理由。因为它记录的是某个时刻而不是当前状态,所以永远不需要更新,也能防止已经有结论的问题被那些不再记得当初约束的人草率地重新争论一遍。
技术文档应该怎么写? 为一个疲惫、有压力、只想找到某一件具体事情的人而写。先给答案再作解释,用真实的命令和真实的路径而不是对它们的描述,写清楚哪里会出错以及它看起来是什么样,并且短到足以保持正确。
过期的文档应该删掉吗? 如果没有人会去修,就应该删。一份错误的文档比一份缺失的文档更糟,因为读者会信任它并照着行动。删掉它,记下丢掉了什么,同时给任何包含版本号、价格或外部依赖的内容标上日期,让读者自己判断。
评论