写好项目技术文档 - CH02. 文档标准设计

大家好,时隔两个月,我又来了。

时隔这么久一方面是最近事情比较多,已经到了并行处理的极限;一方面也是因为,文档标准总归是一个比较枯燥的话题,所以拖到了现在。

那么话不多说,我们书接上文 写好项目技术文档 - CH01. Repository 设计,接着聊聊怎么设计文档的标准和规范。

为什么要有标准?

在日常中,其实很少有人喜欢写文档;而愿意写文档的朋友,经常也会忽视如何设计文档的标准这一话题。毕竟能够愿意去持续地为公司内部项目贡献文档,已经弥足珍贵,有得是玩命糊屎山不写文档的人(当然,代码如文档是最好的状态;但是 99% 的从业者无法达到 Linux Kernel Docs 所描述的理想的状态)。

不过我倒是觉得,文档这东西是有传染性的。当你能够以一个比较高的标准去持续输出文档的时候,身边的其他人多多少少也会被你感染,潜移默化地体会到一个有规范的文档所带来的好处。

这里一个比较常见的案例就是,一个工作上的伙伴来问你一个曾经遇到过的 TroubleShooting,而你直接把相关的文档链接/复盘案例直接在 Thread 里甩给了他。原本需要冗长的 DM 或者 Thread 讨论的问题,直接被终结了。可以说,这是与人合作的过程中最爽的事情之一。

另一个场景是,组里来了一个萌新,他正在进行 Onboarding。这个时候他来向你询问一个内部工具的用法,而你粗暴地甩给了他一份事无巨细、Step-by-step、我奶奶来了都能跟着操作的文档的时候,你的潜意识会清晰的告诉你,这些文档为自己和萌新节省了无可计量的时间,这亦是另一种爽快。

如果说文档的有无带来的爽感是第一层级的话,那么文档的标准和规范,就是到达第二层级的爽感的必经之路。

当一个文档逐渐壮大,或者整个团队的文档意识开始提升之后,一定会遇到一个问题:文档的协作

不像代码,无论项目使用什么语言、版本管理工具、开发框架,总归有一系列非常成熟的开发规范和工具链可以使用。这意味着:

  • 作为下限,项目的 OWNER 可以通过一个很低的代价,确保项目代码的基本一致性。
  • 作为上限,通过 Reviewer 的严苛程度以及单元测试的高覆盖,可以让所有贡献者保持高度一致的提交风格。

而文档的协作,却更加复杂:

  • 贡献者的行文风格都大相径庭。
  • 不同语言的遣词造句规范,有很大的差异。
  • 对于长期项目,甚至会被语言本身的变迁所困扰。
  • 同义词和近义词混杂问题。

因此,文档的标准和规范的目的,就是希望在可控的范围内,尽可能地减少这些问题的出现。让多人协作的大型文档,变得更加工业化,从而实现一套囊括了文档新增和更新(以及本地化)的流水线工程,并且和上一篇 写好项目技术文档 - CH01. Repository 设计 中的文档 Repository 设计相结合,充分利用版本控制工具的优势,结合现代的 CI/CD 流水线,实现一个可跟踪、可维护、行文统一、用词标准无歧义的文档贡献系统

文档标准,分哪些部分呢?

这个分类,我更多其实是参考了 Kubernetes 官方文档以及 Jenkins 官方文档的一些内容以后,自己琢磨的。

简单来说我觉得可以分为这么四块:

  • Reference & Concepts —— 名词与概念参考表。
  • Style Conventions —— 行文/i18N 风格指南。
  • Sync Check —— 适用于多语言的 commit 同步检查。
  • Ownership —— 文档/文档分支的所有权管理。

传统意义上的文档规范,其实主要指的就是 ReferencesStyle Conventions。前者是对整个文档中出现的专业术语和概念的标准解释,从而其他贡献者撰写的时候可以用类似于 {{\}} 这样的形式进行快捷引用。

后者是对整个文档的行文风格,遣词造句的规范。举个例子,在 Kubernetes 官方中文文档中,明确描述了,不允许在翻译中使用 “您” 作为读者的指代。这就是一个很明确的行文风格的规范。

当我们说标准化的时候,到底说的是什么

相信多数的读者在阅读各种开源/商用工具的文档的时候,多少遇到过一个问题:

在不同的页面中,同一个概念或者术语,居然有不同的描述

这并不是一个罕见的问题。无论是 Kubernetes,Splunk,Jenkins 这类超级项目的文档,还是说遍布 GitHub 的各种小型开源项目的文档,都会遇到这样的问题。

举个很直接的例子,在 Kubernetes 中 control-plane 是一个非常基础的概念。然而即便是如此基础的概念,在所有中文翻译版本的页面中,其实有 控制面控制平面 两种翻译方法。从提交记录来看,这显然是一个因为早期批量翻译提交和行文风格规范没有完善所导致的问题。

因此这里也引申出了小节标题。当我们说标准化的时候,到底说的是什么?

我认为在这个场景里,标准化代表的就是精确、达意、全局统一术语词典表。这个表应当包含了当前这个项目/软件所有的专业术语和概念。如果有余力,甚至应该对这个术语词典表中的每一项,进行完整的描述和概念边界的限制。

Reference & Concepts,也就是这个术语词典表,我认为是文档规范中一切的基础,是大楼的根基,是巨树的树根。

有了这个形而上的认识,下一个问题就是,如何把 Reference & Concepts 动手做起来。其实很多时候大家都会觉得把一个 PPT 或者概念上很好的东西落地到实际的 Repository 里,很困难。但是很多时候我觉得我们是被自己束缚住了。

我很喜欢一位厨子(高寒)的说法:“按照我说的做,不要按照我做的做。”

事实上在项目文档里推进标准化也是一个道理。不要在一开始想着就和 Kubernetes 文档一样,设计一个非常成熟而夸张的目录树,用来承载多如繁星的各种概念和术语。这没有必要,因为你根本做不到,并且你的所有热情会在这个过程中燃烧殆尽:


很多时候,作为一个好的开始,一张 MarkDown 写的术语表或个 CSV 文件可能就完全够用了。你完全可以写一个检查工具,放在 CI/CD 管道中用来对文档的术语进行初步的检查。这样的工具只要稍微利用正则就很容易制作。

...
namespace, 命名空间
control-pane, 控制平面
ingress, 入口
...

文档和业务代码最大的不同是,文档更像是一种活的东西,一种随着贡献者的来来去去自由生长的东西。Reference & Concepts 作为保证其符合要求生长的最底层的规则,很多时候最大的意义在于其存在本身

如何让无数人,按一个风格说话

说实话,这个副标题让人绝望。

莫说让无数人按照同样的行文标准来说话;哪怕让我这个月和上个月用完全一样风格的说话,恐怕都不太容易。

所以这里就产生了一个问题,语言、或者说文章的标准化生产方法是什么。对了,就是车轱辘话。不管什么人说出来的车轱辘话,基本味道都是差不太多的。那么怎么说车轱辘话呢?

答案就是堆砌简单陈述句

- A 是 B
- A 有 B
- A 可以 B
- A 用于 B
- A 用 B 来 C

其中 B 和 C 这样的名词或者动词,至多再加一个简单的修饰词。这样的句子,不仅简单,而且容易理解,也容易记忆。好的文档是消除歧义的,而简单句就是消除歧义最好的办法。

但是规定是规定,人是人。所以我一直认为(当然很多人不这么觉得),文档的 Reviewer 团队对于文档长期的风格一致性,至关重要。人类其实是非常善于模仿的,甚至在自身是新参与者的情况下,会主动对集体的行为进行无意识的模仿。引申到文档文风上,历史已经存在的文档的风格,对后来的贡献者影响会非常巨大。因此有一个稳定的 Reviewer 团队的文档,往往能够在比较长的时间线上,保持了很好的风格一致性。这里可以参考 Splunk,RedHat,Microsoft 这些商业公司的文档。且不论文档内容纰漏的多少,但是它们确实相较于大量开源项目,有着更加工业化的统一文风。

另外有一个非常好的例子是 Linux Kernel Docs。你会发现在内核文档中,随处可见夸张的谩骂和对糟糕提交行为的批评。按照普适的技术文档的眼光来看,这样的文档是让人皱眉的;因为 Linus Torvalds 以及他早期的小伙伴们的个人印记实在太过于强烈。但是即便如此,由于 Linux Kernel 直至今日依然有着这颗星球上最成熟老练的维护团队,面对五万人级别的贡献者团队,仍然可以将文档和 Code as Document 理念贯彻到底。

聊到这里其实大家估计也品出来了,关于行文风格,真正的规范可能只有一条:尽量使用简单陈述句。剩下都是关于 的问题。

再缩小点范围,是一个关于 维护团队 成员稳定性的问题。他(她)/他(她)像破冰船的船头一样,带领整个项目的文档贡献者,一起向着一个方向前进,撰写一页又一页得到用户和社区认可的文档,那么这个文档的文风本身也会像一棵被妥善照料和修剪得到树木一样,长期维持一个不变的风格。

正所谓,不要尝试去教成年人如何说话,好的文档本身就是最好的老师。

而维护者要做的,就是照料好最初得种子和幼苗。

多语言,我们怎么跟踪母语言版本的修改?

几年前其实思考过这个问题,当时我觉得容易想不容易做。原理是利用 git diffgit log

多语言内容无论是放在不同分支,还是在同一个分支的不同目录内,都可以用这个方法进行跟踪,但是需要一些巧思设计。当时写了一个简单的 demo,用了一下勉强可以用。直到有一天,我看到了一个终结问题的答案:

Kubernetes i18n sync check

这个脚本稍作修改,可以迁移到几乎任何形式的文档中,用来跟踪多语言翻译的变更。无需多言,大家直接看代码就行。

没必要重复造轮子。

维护者,亦是苦行僧

聊到这里,本文也快到尾声了。我想说的最后一点,是关于维护者的话题。

正如上面提到的,行文风格的核心是维护者团队的稳定性。无论是文档刚刚开始产生的时候,还是后期有越来越多贡献者参与的阶段,稳定的维护团队是保证文档不发生锈化的核心要素。很多商业公司,甚至开源基金会的团队建设过程,都忽视了这点。

大家往往很重视项目业务代码仓库的核心团队的组建和发展,但是到了文档这个环节,由于没有直观的业务价值,往往被降级。要么是由开发团队的人员兼任,要么由团队的萌新来做。萌新连项目本身都看不明白,就要来写文档,这不是在扯淡么?

这也是为什么国内好几个规模很大的厂子,文档却一泡浆糊的原因。

说实话,我一直坚信技术文档是任何开源/商业项目的第一个门面,而不是他们的官网。FFmpegVIM 的官网一点都不酷炫,但是不影响他们成为伟大的软件。他们的文档写的都很清爽和开发者友好,对这些工具真正的用户来说,这实在是太重要了。

如果鄙人有幸,真有开源项目的创始者或者技术行业的大佬看到这篇文章,我真心希望大家,少去评几个没用的奖项,少去在官网弄一堆酷炫的合作友商和优秀客户采访;一份出色项目文档,能为项目带来巨大的潜在声誉,长期价值远远超过那些虚浮的东西。


最后祝大家,身体健康。