Contents

文档系统_程序员如何写好文档 (The documentation system)

Contents

背景

文档是日常开发过程中非常重要的记录和交流的工具,也是学习新技术必然要阅读的材料.学习技术的时候,都会建议直接看官方文档,不同的技术网站,会看到 Guide,Tutorial,Wiki,Reference 等分类(也可能只包含其中一个或者几个). 我之前就一直对这几个英文单词有疑问,尤其是我在看 Android 开发者官网的时候,不明白每个分类的依据,间接导致,自己也没有学会如何写文档.后来发现了这篇文章,读完觉得很有道理. The documentation system,窃以为非常好,值得我进行模仿学习.

以下的内容会进行自我理解的翻译,有意无意的删除一些冗余的修辞,如有幸被网上邻居搜到,建议看原文,非常简单.

Summary

为了编写良好的软件文档,需要说一个秘密: 没有一个名为文档的东西,文档应该是四样东西的集合.

这四样分别是是:tutorials(教程),how-to guides(如何做的引导),technical reference (技术参考),explanation(解释). 它们代表四种不同的目的或职能,并且这四种的写作方式都有差异.了解了这些差异,通常能巨大的提高文档的质量.

关于即将描述的文档系统

https://documentation.divio.com/_images/overview.png 这里的文档系统是非常简单的,近乎于全面适用行业内的方案.行文有个承诺: 如果将这些原则在实践中进行应用,将极大的提高写作文档的质量.

有很多公司/组织/开源项目采用了本文所述的方案,详细见链接采用本方案的项目

Introduction

问题和解决方案

需要解决的问题

如果文档不够好,产品再好,人们也不会使用它.即使人们必须使用它,那也是因为他们别无选择,没有良好的文档,人们无法如你期望的那样使用你开发的产品.

当然了,每个人都知道文档的重要性,每个人也都尝试去写好文档,最终也都失败了.

这也不是写作的人不够努力,通常是他们没有按照正确的方式去做而已.

本文介绍的文档系统,不是为了让你更加努力的工作,而是让你写作的文档更好,使用正确的方式进行写作,让文档更加易懂,更加容易维护: The right way is the easier way.

文档系统的秘密

有一个不应该是秘密的秘密: 文档应该围绕四种不能的功能目的进行构造: tutorials(教程),how-to guides(如何做的引导),technical reference (技术参考),explanation(解释).每一种都需要有独立的写作模式. 软件的使用者在不同的情况下,需要不同的文档,故而,大部分的软件,对于这四种文档,都需要包含.

文档将围绕这四种进行构建,并且四种文档需要独立的创建.

Tutorials(教程) How-to guides(如何做的引导) Reference(技术参考) Explanation(解释)
oriented to(面向的/目的/导向) 学习 有一个固定的目标 传达信息 为了更深的理解
must (必须做到) 让一个初学者上手 演示如何解决一个特定的问题 描述技术的内部参数等 深层次的解释
its form(形式) 一节课 一些列的步骤 纯粹的描述 用文字进行阐述说明
analogy(类比) 教一个孩子如何进行烹饪 烹饪中的食谱 百科全书里的文章 关于烹饪的历史书

如上这种划分,可以让作者清楚写什么内容,写在哪儿,如何写; 读者清楚去哪找想要的内容.这种划分,可以让作者从原先的一股脑的将一堆信息进行拼凑的状态中解脱,因为这种划分,按照职责划分,不同类型的文章只需要完成一样职责,写作时目的很明确,不再出现拼凑信息的情况.

坦白讲,那些不符合该方案的文档还是非常难以维护的.因为我们列出的 4 种类型针对的是 4 种不同的需求,一旦将这些需求对应的内容糅合在一个文档里的时候,文档的内容为了兼顾,肯定有相互之间的牵扯,读者就会被牵扯.

一旦理解了上述的方案,就会极大地提高文档的结构性,我们也就能知晓接下来采取什么方式提高我们的文档质量.

接下里的章节中,将会针对这四种类型的文档,分别进行详细的描述.

让文档自己工作

对于作者而言

对于文档的作者而言,最大的难题是不知道他们该做这些什么. 作者为了让自己想表达的内容以合适的方式排列在一起,不停的写再重写,不停的反复. 通过这种文档系统结构,将会使得写作更加容易,因为该方案将文档进行明确的职责区分,将文档进行明确的隔离,这样使得写作和维护都很容易,也很容易使用和查找. 虽然说文档不能自己完成,但是现在编写文档的时候,可以做到不用操心哪些内容应该包含,哪些内容不应该包含.在职责明确的背景下,我们很容易知道在什么地方,写什么,怎么写.

对于读者而言

对于读者言,可以更好的与软件进行交互了,在试用的不同阶段,可以很快的找到自己需要的资料. 按照上述四个象限进行编写文档,有助于软件吸引和留住用户,他们可以快速接入,更加高效的使用软件.

Tutorials

Tutorials(教程) 是由课程组合而成,内容都是些课程,目的是带领读者通过一系列步骤来完成某种项目.项目的作者需要这些 Tutorials(教程 ),一次向初学者展示他们可以用作者的软件可以获取到的东西.

Tutorials(教程) 是以学习为导向的,具体来说,Tutorials(教程) 是教会学习者如何使用,成为一个使用者,而不是学习项目本身.

你作为作者就是个老师,读者就是个学生.你需要对你教授给学生的东西负责.学生在你的指导下,将会通过一系列的操作在最终获到你想传授的技能.

最终的结局和步骤,都取决于你.但是读者应该是什么样的人,却是无法预测的.结局对于初学者来说,必须有意义,而且必须有所收获.

有一个重要的事情需要说明,当学习者阅读完Tutorial时,他应该对剩下的文档内容心里有数了,对于这个软件本身也做到了心里有数.

大多数软件的Tutorial很差,甚至干脆没有.Tutorial是一个让学习者成为软件用户的契机.如果Tutorial很差,或者没有,获取新用户的难度会大很多.

在介绍四种文档的章节中,这部分是最难写的,因为Tutorial是最难理解,也最难做好的内容.

传授知识的最佳方式是现实中存在一个可以互动的老师.这基本是不可能的,所以我们写的Tutorial就是最好的替代品.这也能说明,我们需要格外的注意Tutorial的部分.

Tutorial 必须对初学者有用,简单有意义,而且紧跟软件的发版节奏,及时保持最新状态.

和烹饪类比

https://documentation.divio.com/_images/anselmo.jpg 可以类比教一个孩子如何烹饪.

你教孩子做什么菜不重要.重要的是,孩子通过你的传授,发现了烹饪的乐趣,获得了自信并且想再次尝试.

孩子通过学习过程中所做的事情,将会学习到烹饪中最重要的事情.他将学会为了做一道鸡丝面,应该放些什么材料,而且知道如何处理这些材料.

这是因为,使用软件,和烹饪一样,是个手艺活.尽管说,他是需要知识,但是这些知识是实用性的,需要实际使用,而不是理论性的.

当我们学一门新的手艺和技巧的时候,总是从使用这个手艺或技巧开始.

如何写好Tutorial (How to write good tutorials)

让学习者在使用中学(Allow the user to learn by doing)

在事情的初期阶段,我们通过实际使用来学.这也是我们学习说话和走路使用的方法.

在软件的Tutorial中,都是软件的初学者需要做的事情.学习者在阅读Tutorial后可以知晓,从一个简单入门的项目向一个更复杂的项目需要使用的工具和步骤.

让学习者开始动起来 (Get the user started)

对于初学者进行手把手式的讲解,是让人更容易接受的.而不是将初学者当作一个经验丰富的用户.有时候,传授的内容可能不是所谓的“正确”方式,因为刚开始的时候,不要传授所谓的最佳实践.

Tutorial 的最核心的点是,让学习者开始行动起来,让他踏上使用的旅程,而不是要一次性将他们带到旅途的终点.

确保Tutorial是可用的 (Make sure that your tutorial works)

作为指导者,还有一个很重要的任务,就是让学习者充满自信,自信于在你的指导下,通过软件,以自己的能力,可以完成Tutorial中要求的内容.

有很多的内容可以帮我们达到这个目的.一份措辞温和友好的帮助文档,连续且逻辑清晰的语言,都对此大有裨益.但是其中最重要的一点是,你让阅读者进行的操作案例必须是可用的.阅读学习者必须根据你的步骤能看到跟你说的一样的效果.

如果学习者在学习过程中,进行的操作不顺利,产生错误或者意想不到的结果,即使这个不是你的原因,你的Tutorial就算是失败了.学习者如果跟你面对面交流,那么你可以直接线下指导,但是绝大部分情况,都是直接阅读Tutorial的,那就很难直接指导.所以,在写作Tutorial的时候,就需要想方设法的我避免这个样的事情发生.

确保阅读者的操作能获得及时反馈(Ensure the user sees results immediately)

学习者在过程中执行的所有操作应该是完成一些学习者阅读时已经可理解的操作,无论这个操作有多小,都必须让阅读者明白目的.试想一下,你的一个学生,在看到一个效果之前,需要阅读两页的文档,且执行一些自身都觉得奇怪的操作,这个过程也太长了.学习者进行的每一步操作,应该做到尽快明显且可见.,执行的动作和效果之间的联系也需要清晰明了.

Tutorial整体或者其中的任一章节结束的时候,他的结尾,都必须是个有意义的总结,让学习者一顿操作下来是有意义的.

让你的Tutorial是重复的,可反复操作的(Make your tutorial repeatable)

你的Tutorial必须是非常可靠,可复现的.这点并不容易,原因在于,学习者使用的操作系统可能不一样,经验和使用工具的水平并不一样,更重要的是,学习者使用的软件和资料也与此同时发生了变化.

Tutorial必须适应这么多情况,在这些情况下都能正常工作.

所以 Tutorial 需要定期进行详细的测试,以保证它持续的有效.

聚焦在具体的步骤中,而不是抽象的概念里(Focus on concrete steps, not abstract concepts)

Tutorial 必须是具体的,围绕着规格说明进行开展的,有明确的步骤和步骤对应的结果.

进行抽象概念的介绍的诱惑力太大,毕竟,计算机的强大也是来自于此,然而,大多数的学习都是由具体到抽象,反过来是个比较糟糕的学习方式.

必要的解释要尽量的少(Provide the minimum necessary explanation)

在完成 Tutorial 中不需要了解的知识,不要进行解释.额外的扩展和讨论是可以的,但是不应该出现在 Tutorial 中.在 Tutorial 中,只会令学习者分心,还会干扰学习目的.只有必要的解释才可以放在这部分,其他的可以提供链接导航.

关注于哪些用户需要执行的步骤 (Focus only on the steps the user needs to take)

Tutorial 需要关注的是手头的任务.也许你的命令还有很多的其他的可选项,也许你的API还有很多其他的使用方式,但是对于学习者当前的任务而言,并不需要.

Divio 中的一个 Tutorial 例子(Example from Divio’s documentation)

可以看下这个 Tutorial https://documentation.divio.com/_images/django-tutorial-example.png

可以着重看下关于 Django 的 Tutorial,如图所示,其实就是在承诺,如果学者具备了基本的前提能力,并且按照文档所述的步骤一步一步的执行,当阅读完之后,将会完成一个用 Django 实现的web应用,其中数据库中用的是 Postgress, S3实现的媒体存储等等.为了达成这样的目标,Tutorial 就需要一步一步填充这些内容.

注意,Tutorial 目录都没有指明学习什么,而聚焦在应该做些什么,做什么的顺序.

如何做的指南(How-to guides)

“How-to-guides”是通过指引读者进行一系列的步骤以解决现实中特定的问题。

Guide 是食谱,是为了解决一个特定问题的指导方案。举个例子,如何创建一个web表单;如何启用LDAP权限验证。

guide始终是目标为导向的。

Guide 和 Tutorial完全不同,二者的编写目的和面向的目标都不一样,对此必须有清晰的认识。具体来说,有几下几个差异

  • Tutorial 是你作为一个作者,想让读者作为一个初学者,需要知道的内容。是作者认为初学者应该知道的。
  • Guide 是面向有经验的用户,为的是解决他们的一个实际问题。
  • 在编写 Guide 的时候,作者可以假设读者已经具备了常规的知识和理解。可以假设读者已经具备了操作使用作者的软件所需要的基础能力和基本的工具。
  • 和 Tutorial 不同的是, Guide 是比较容易写好的,这部分内容是比较轻松,比较容易写的。

和烹饪类比

https://documentation.divio.com/_images/recipe.jpg

可以想象成某样食物的食谱。

食谱必须清晰明了,有明确的定义。他们描述了一个明确的问题。食谱在向一个有基本烹饪经验的人,如何完成食物的烹饪过程。

从来没有任何烹饪经验的人,只靠食谱,是很难完成一道菜的烹饪的,所以说,食谱本来不是烹饪课的一部份。与此同时,如果有经验的厨师,发现食谱在描述一些他们早就掌握的基础能力,基础的技巧,他们就会很愤怒。

如果编写一份好的guide(How to write good how-to guides)

提供一系列的步骤(Provide a series of steps)

Guide 必须包含一些读者必须操作的步骤(这个在 Tutorial 也有类似的需求)。作者并不需要从头开始描述步骤,以一个相对合理的点进行开始描述即可。Guide 必须是可靠的,但是,Guide 并不需要保证像 Tutorial 一样的可重复性。

聚焦于结果(Focus on results)

Guide 必须聚焦于某个特定的目标。与目标无关的任何其他事情都是分心的。和 Tutorial 一样,详细的解释并不适合放这儿。

解决某个特定的问题(Solve a particular problem)

Guide 必须的标题命名也必须是有明确指向一个问题的,比如: 如何。。。

Guide 和 Tutorial 的另一个不同点是,阅读 Guide 的人知道自己阅读 Guide 需要什么,最终的目的是什么,他们已经知道阅读完 Guide 自己将获得什么,他们只是不知道该怎么做而已。而对于 Tutorial 而言,读者其实并不知道自己将获得什么,读者阅读完获得的内容,完全是由作者说了算。

不要解释概念(Don’t explain concepts)

guide中不需要解释任何东西,guide只适合放些解决问题的步骤,如果有解释的需求,可以进行超链接。

也许允许存在一些弹性变通(Allow for some flexibility)

一份 Guide 针对同一件事应该是允许存在一些不同的处理方式的。Guide中能让读者采取变通的地方应该做到显而易见。不要让guide太过特殊,一点通用型和灵活性都没有。

Leave things out(将事情抛诸脑后)

实用性比完整性更有价值.Tutorial (教程)需要是完整的,有头有尾的指导. Guide 并不需要这样.Guide 可以从作者认为合适的地方开始和结束。Guide 也不需要提及那些仅仅因为它与主题相关,但是并不是关键内容的部分.臃肿的 Guide 并不能帮助用户快速找到解决方案.

名字很重要(Name guides well)

Guide 的标题很重要,标题必须能准确告诉读者,文章的内容具体是干什么的. “How to create a class-based view (如何创建一个基于类的视图)” 就是个很好的标题. 然而像 “(Creating a class-based)创建基于类的视图” 和 “Class-based views (基于类的视图)“就更差劲了.

Divio 中的 Guide 例子(Example from Divio’s documentation)

看一下这个文档our how-to guides. https://documentation.divio.com/_images/django-how-to-example.png

这里的每个标题都是在说明内容是一个问题的答案. “how do I…? (如何解决…如何做到…)”. 这些标题里都是在阐述类似的概念"how to “. 每一个都是一道菜的食谱,都会引导读者完成对应的菜.

虽然我在 Tutorial 和 Guide 都是服务用户的需求.但是,Tutorial 的内容是作者在告诉读者,作者认为读者应该知道的内容. 然而,Guide,是作者在回答读者问的问题.

参考(Reference guides)

Reference是机械的技术说明,说明如何进行操作。

Reference只有一个职责,就是进行描述。Reference是面向代码的。从根本上说,描述了关键的class,函数,API,以及罗列一些字段属性,还有方法,同时呢,说明如何使用它们。

Reference是信息导向的。

无论如何,尽管Reference可以包含一些example来演示使用方式,然而呢,依旧不应该试图解释一些基本概念和如何完成常规的需求。

Reference应该是简单直切主题的。

请注意,Reference的描述应该是包含一些机理的基本描述。如:如何初始化一个类,如何调用一个方法,例子,以及调用方法时,参数的限制等等。

对于一些开发者而言,Reference是他们唯一能想到的文档了。他们已经对软件非常熟悉了,也知晓了如何使用了。他们认为学习者就需要这些文档。

Reference比较容易写好,甚至在某种程度上来说,都可以自动生成。但是这还远远不够。

和烹饪进行类比(Analogy from cooking)

https://documentation.divio.com/_images/ginger.jpg

想象一下百科全书上有一篇关于生姜作为原材料的文章。

当你在Reference中查询生姜时,你想要获取的信息都是些像起源,表现,化学机理,以及如何进行烹饪。

你希望你检索的任何食材都以类似的方式展示信息。而且你希望获取一些基本扩展信息,比如生姜家族还有姜粉,还有豆蔻等等。

还有一些潜在问题风险也是我们想获取的。比如。生姜可能会导致胃灼热,与一些抗凝血的药一起食用会有副作用。

如何写一篇好的 Reference(How to write good reference guides)

Reference是围绕代码进行结构的组织(Structure the documentation around the code)

将reference的结构和代码的结构保持一致,这样使用者看代码的同时,可以同时看到reference。这种方式也有利于开发维护文档,及时知晓哪块缺少文档,哪块需要更新。

保持连贯性(Be consistent)

在书写Reference的过程中,结构,语气和格式都需要保持一致。就像一本百科全书和字典那样。

只做内容描述(Do nothing but describe)

技术Reference只需要尽可能的描述完整,描述清楚就行。其他的像解释,讨论,指导,命令,猜测,观点等等,不仅会让读者分心,也会让Reference难以使用,维护困难。可以在适当的时候,在Reference中提供简单的example进行演示。

不要在Reference中忍不住指引读者,使用超出基本操作之外的操作来完成某项完整的需求.更不要在 reference 中试图对一些概念进行解释或者进行一些主题讨论.相反,如果有类似的需求,可以放一个链接,导航到 Guide,Explanation 和 Tutorial 部分.

一定要精确 (Be accurate)

Reference 这部分的内容必须时刻保持最新,紧跟软件的更新和发展,但凡 reference 和软件有一丝的不一致,就可能将读者或者用户带入沟里.

以Divio的文档作为例子(Example from Divio’s documentation)

可以看下这个链接里的例子

https://documentation.divio.com/_images/django-reference-example.png

这是个典型的 Reference 文档,这里是展示的命令行工具的解释.

这里的描述就是如本文上述的内容一样,完整而精确地展示了这个工具的的功能,命令以及命令的参数.

这部分的内容的易读性可能没那么好,但是这部分的目的是为了尽快无干扰的找到相关功能的信息.

Explanation

Explanation(解释) 或者 discussion(讨论)是要阐明一个特定的主题. 这其实扩大了文档对主题的覆盖范围.

Explanation(解释) 是面向理解的.

Explanation(解释) 本质上也可以等价于 discussions(讨论) ,他们其实都比较散漫.Explanation(解释) 是在跳出了软件本身,从更高的视野和不同的角度在解释和阐明软件.你可以想象,你的用户在闲暇时间,希望阅读的是文档,而不是源码.

很少有人明确的创建Explanation(解释) 这一章节.而是本该属于这章节的内容分散在了其他的章节里.有时,文档里有对应Explanation(解释) 应有内容的章节,但是这些章节都命名成了"背景”,或者其他主题形式的记录,这就导致这些命名不能很好的表征内容.

Discussions (讨论)并没有看上去的那么容易,想象一下,你手里有张白纸,这时候,有人问了一个问题,该如何进行回答和讨论?

一个topic (主题)不是像 Guide(指南) 一样,解决一个特定的问题,传授一些特有的步骤; 也不是像tutorial(教程)一样,在向读者传授你认为读者他们应该掌握的内容.也不是由机器来决定的 reference . 这部分的内容完全是有作者自己来界定讨论的内容,以及覆盖的范围.所以这部分的内容看上是比较随意的.

类比烹饪(Analogy from cooking)

https://documentation.divio.com/_images/mcgee.jpg

考虑下,在进行历史,科技和科学的上下文和背景下,进行烹饪的讨论. 讨论的内容会是烹饪和厨房.

这部分讨论的内容并不是传授如何烹饪,也不是食谱的集合. 这部分内容只是在进行描述.

相反的,这部分内容是在从多个角度进行阐述分析问题. 可能是在解释为什么我们今天会如此处理事情,或者事情的处理如何糟糕,甚至会描述替代的方案.

这部分内容会加深我们对知识的理解,即使这部分内容并不是立马可应用于实际的业务场景中,但是这部分内容的价值并不是靠在实际的生产应用中体现.

当我们需要闲暇事件,离开厨房的时候,从更高的层次上,来加深对烹饪的理解时,了解更多关厨房的主题时,我们就会选择阅读这部分内容.

如何写好一份 explanation(How to write a good explanation)

提供上下文环境(Provide context)

Explanations 可以用来提供上下文和背景. 例如,在 Django或者 CMS 中如何处理 Web 表单.

在这部分,可以解释为什么是如此处理,相关的设计决策,历史原因,技术限制等等.

讨论替代方案和建议意见(Discuss alternatives and opinions)

Explanation 可以考虑进行替代方案,或者同一问题的多种不同解决方案.举个例子,在一篇关于 Django 部署的文章中,可以讨论和评估不同的服务器部署.

Discussions 也可以用来讨论两种相反的意见和选择. 举个例子,是否需要将测试模块放入源码工程的包下面.

不要进行指导,也不要提供技术支持(Don’t instruct, or provide technical reference)

Explanation 应该做一些其他部分的文档没有做的事情. Explanation 不适合对读者进行指导如何进行操作,也不适合提供技术解决方案.这些内容都是其他文档的职责.

Example from Divio’s documentation

Divio 文档中的一个例子

https://documentation.divio.com/_images/divio-explanation-example.png 看一眼这个文档, our explanation section (名称是“Background” -名字并不重要,阐释的主题和内容更加重要).

这些文章没有教任何东西. 他们不会告诉读者该做什么.它们不是 reference . 他们只是讨论特定的话题.举个例子, 读者不需要知道 缓存 或 CDN 亦或是如何管理环境变量来使用平台或完成任何特定任务,但是阅读完这些内容之后,读者的经验和平台的使用能力都会更加清晰,理解也会更加深刻.

这些文章的内容提供了一个更加广阔的图景,更加清晰地上下文. 读者作为一个用户,作为一个使用方,也许他们并不需要知道处理一个问题的方式为何如此.但是当他们知道这些背景和缘由之后,他们会对产品更加满足,自身也会更加的快乐.

关于文档的结构(About the structure)

为什么这个不明显(Why isn’t this obvious?)

这个结构是非常清晰的,而且是能其效果的. 但是为什么让人觉得这个结构没那么明显呢?原因是,这四个类型的文档,处在四个象限,每个象限的和其相邻的象限在特征上是有重叠.

https://documentation.divio.com/_images/overview.png 从上图中可以看到,每个象限都和邻居有重叠.

Tutorials 和 Guides 都有描述操作步骤; Guides 和 Reference 都有关于我们在工作时应该做的内容. Reference 和 Explanation 都有理论知识的内容. Tutorials 和 Explanation 相较于实际的工作内容,对学习有莫大的帮助.

坍塌的趋势(The tendency to collapse)

考虑到这些文档之间的重叠部分,不同类型的文档相互之间变得混淆并相互混合也就不足为奇了.事实上,这些不同类型的文档彼此之间存在一种难以抗拒的力量,让他们之间纠缠不清.它的作用是坍塌式的结构,这就是为什么这么多文档看起来像这样. https://documentation.divio.com/_images/collapse.png

省略的内容

后面有一些使用本结构的文档链接和介绍,就不再翻译了.

总结

文章中最后也有说明,不是所有的文档都需要具备齐全这四种类型,最重要的是,知道有这四种类型,注意阅读者的分级分层,内容的重点和意图.