如何写好技术文档 - 来自Google十多年的文档经验

news2024/9/20 0:40:50

[导读]本文大部分内容翻译总结自《Software Engineering at Google》第10章节 Documentation。另外,该书电子版近日已经可以免费阅读了https://qiangmzsx.github.io/Software-Engineering-at-Google/#/?id=software-engineering-at-google,有兴趣的同学可以翻阅。


- 1 -

文档的重要性

高质量的文档对于一个组织或团队来说有非常多的益处,比如让代码和API更容易理解、错误更少;让团队成员更专注于目标;也可以让一些手工操作更容易;另外如果有新成员加入的话有文档也会让他们更快融入。

写文档有比较严重的收益滞后性,不像测试,你跑一个测试case,它能立即告诉你是对还是错,它的价值马上就体现出来了。而写一份文档,随着时间的推移,它的价值才会逐渐体现出来。你可能只写一次文档,将来它会被阅读上百次、上千次,因为一份好的文档可以在未来替你向别人回答类似下面这些问题。

  1. 为什么当时是这么决策的?

  2. 为什么代码是这样实现的?

  3. 这个项目里都有哪些概念?

  4. 等等

写文档同样对于写作者也有非常大的收益:

  • 帮你构思规范化API:写文档的过程也是你审视你API的过程,写文档时会让你思考你API设计是否合理,考虑是否周全。如果你没法用语言将API描述出来,那么说明你当前的API设计是不合理的。

  • 文档也是代码的另一种展现:比如你两年后回过头来看你写过的代码,如果有注释和文档,你可以很快速理解代码。

  • 让你的代码看起来更专业:我们都有个感觉,只要文档齐全的API都是设计良好的API,虽然这个感觉并不完全正确,但这两者确实是强相关的,所以在很多人眼里,文档的完善度也成为衡量一个产品专业度的指标。

  • 避免被重复的问题打扰:有些问题你只需要写在文档里,这样有人来问你的时候你就可以让他直接去看文档了,而不是又给他解释一遍。

- 2 -

为什么大多数人都不喜欢写文档?

关于文档的重要性,每个技术人或多或少都知道一些,但很多人还是没有写文档的习惯,为什么?除了上文中提到的文档的收益滞后性外,还有以下几点原因:

  • 很多工程师习惯将写代码和写作割裂开,不仅仅是在工作上,而且在思想上就认为它们是完全不相关的两项工作,这就导致好多人重代码不重文档。

  • 也有很多工程师认为自己不善写作,索性就不写了。这实际是个偷懒的借口,写文档不需要华丽的辞藻、生动的语言,你只需要将问题讲清楚即可。

  • 有时候工具不好用也会影响文档写作。如果没有一个很好的写作工具将写文档嵌入到开发工作流程中的话,写作确实会增加工作的负担。

  • 大多数人将写文档看作是工作的额外负担。我代码都没时间写,哪有时间写文档!,这其实是错误的观念,文档虽然前期有投入,但能让你代码的后期维护成本大幅降低,磨刀不误砍柴工这个道理相信大家都还是能理解的。

- 3 -

如何产出高质量文档

既然理解了好文档的重要性,我们如何保证在时间的长河中维护好一份文档,这里有些相关的方法论,大家可以参考下。

3.1 像管理代码一样管理文档

对于如何写出好代码,整个技术圈已经有好多经验的总结了,比如书籍《重构》《代码简洁之道》…… 针对各种编程语言,也有相关的规范,比如国外的Google C++规范,国内的阿里Java开发规范等…… 但对于文档 似乎相关的资料却很少。但实际上,不应该把文档和代码割裂开来,你可以简单粗暴地认为文档其实就是用一种特殊语言书写的代码,这种语言就是人类的语言。这么想的话,实际上我们很多在代码和工程中总结出来的经验,也可以直接用在文档中,比如:

  • 有统一的规范

  • 有版本控制

  • 有明确的责任人维护

  • 有变更Review机制

  • 有问题的反馈和更新机制

  • 定期更新

  • 有衡量的指标(比如准确性、时效性)

3.2 明确你的读者是谁

写文档有一个很常见的错误,那就是很多人文档都是写给自己看的,这种情况下就会导致你的文档只有自己或者和你有相似知识背景的人才能看懂,团队较小时这种问题还好,你们都做着类似的工作,所以也都能看懂文档。但当团队逐渐壮大后,问题就会凸显出来,新人有时候有着和你不同的工作背景,甚至现在都做着不同的工作内容,这时候你之前写的文档他们就很难读懂了。

所以在写文档之前请明确你文档可能的读者会是哪些人,然后针对他们的特点着重关注如何才能让他们理解当然,文档也不一定要非常严肃和完美,只要能向你潜在的读者说明问题即可。记住文档是写给别人看的,不是给自己看的。

根据专业水平可以大致将读者分为三种:新手、老手和专家,针对不同水平的人写作需要有侧重点。比如针对新手,你需要重点介绍下里面涉及到的术语和概念,然后详细讲解具体的的实现。相反,针对专家 你可以省去这些额外的信息。注意,这里没有严格的标准,因为有些文章新手会看,专家也会看, 这里还是需要具体情况具体分析。

另外一种对读者分类的方式就是根据读者阅读文档的目的来分类,比如有人知道自己遇到了什么问题,就是来找解决方案的。还有一批人只有一个简单的想法,但不知道具体的问题。举个例子,以读数据库慢为例,前者已经知道数据库慢可能是因为数据量巨大且没有加索引,解决方案很简单 加索引,这时候他可能需要知道的是如何正确地加索引。而后者可能着重关注的是为什么读数据库会慢,这时候你可能需要额外重点介绍下数据库相关的原理。

3.3 清晰的分类

文档大致可以分为以下几种类型,每种类型也有自己不同的特点和写作侧重点。

3.3.1 参考文档

参考文档也是大部分开发人员日常会使用和书写的文档,比如我们使用某个框架或者工具,都会有API说明文档,这就属于参考类文档。它并没有太多的要求,只要能向读者展示清楚如何使用即可,但无需向读者讲明具体的实现。

注:参考文档并不仅限于API文档,还包括文件注释、类注释、方法注释,要求都是能准确说明其用法。

3.3.2 设计文档

很多公司或者团队在项目开始前都要求有设计文档,设计是项目实施的第一步,所以在设计文档书写的过程中要求尽可能考虑周全,例如该项目的存储、交互、隐私……

好的设计文档应该包含以下几个部分:

  1. 设计目标

  2. 实现的策略

  3. 各种利弊权衡和具体决策

  4. 替代方案

  5. 各种方案的优缺点

写设计文档的过程也是你对整个项目做规划、思考可能出现问题的过程,设计的越详细、思考的越多,未来遇到问题的可能性就会越小。

3.3.3 引导类文档

引导类文档也很常见,一般都是Step by Step的形式。比如我们在使用某个框架或者工具的时候,一般都会有个引导类的文档一步一步帮助你快速上手。大家写引导类文章大家非常容易犯的一个错误就是预设了很多背景知识一般使用文档都是有开发者写的,他们都非常了解这个工具的相关的知识,所以习惯性的会认为,啊 这个知识点很简单 用户也肯定会吧,实际上用户不一定会。这本质上就是一种认知偏差,这种现象在跨团队协作 尤其是多端协作的时候也非常明显。

这类型的文档写作中,要求写作者尽可能站在用户的视角上思考,极力避免出现和用户的认知偏差,力争每个步骤做到明确无歧义,每两个步骤之间做到紧密衔接。

3.3.4 概念性文档

当参考文档无法解释清楚某些东西的时候,就需要概念性文档了,比如某个API的具体实现原理。其主要是为了扩充参考文档,而不是替代参考文档。有时候这和参考文档会有些内容重复,但主要还是为了更深层次的说明某些问题、解释清楚某个概念。

概念性文档也是所有文档中写作最难的,也是被阅读最少的,所以很多情况下工程师最容易忽视。而且还有另外一个问题,没合适的地方放,参考文档可以写代码里,落地页可以写项目主页里,概念性文档似乎也只能在项目文档里找个不起眼的角落存放了。

这类文档的受众会比较广,专家和新手都会去看。另外,它需要强调概念清晰明了,因此可能会牺牲完整性(可以由参考文档补齐),也有可能会牺牲准确性,这不是说一定要牺牲准确性,只是应当分清主次,不重要的就没必要说了。

3.3.5 Landing pages(落地页)

Landing pages就先简单翻译成落地页了,没想到啥恰当的翻译词。比如一个团队或者项目的导航页,虽然没啥具体的内容,但应该包含其他页面的链接。比如你新入职一个团队,比较成熟的团队都会扔给你一个文档,这个文档里包含常用的工具、文档链接,这就是这个团队的落地页。

落地页的问题就是随着时间的推移,页面可能会变得越来越乱,而且有些内容会失效,不过这些问题都好解决,做好定期的维护和整理就行。

落地页的技术难度不高,但要求内容的有效性、完整性和分类清晰。

3.4. 文档审核

在一个组织内,光靠个人去维护文档是不行的,必须得借助群体的智慧。在一个组织内部,文档的变更也应该像代码的变更一样,需要被其他人Review,以提前发现其中的问题并提升文档的质量。

如何Review文档:

专业的视角来保证准确性:一般由团队里比较资深的人负责,他们关注的核心点是文档写的对不对,专不专业。如果Code Review做得好的话,文档的Review也属于Code Review的一部分。

读者视角保证简洁性:一般由不熟悉这个领域的人来Review,比如团队的新人,或者文档的使用者。这部分主要是关注文档是否容易被看懂。

写作者视角保证一致性:由写作经验丰富或者相关领域比较资深的人承担,主要是为了保证文档前后是否一致,比如对同一个专业术语的使用和理解是否有歧义。

- 4 -

写文档的哲学

上面部分站在组织和团队的视角来看如何提高文档质量,我们接下来看看站在个人写作者的视角上如何写出高质量的文档。

4.1 5W法则

5W法则相信大家已经听的多了,分别是Who、What、When、Where、Why,这是一个广泛被用在各行各业的法则,写文档当然也能用(5W法则堪称万金油,啥地方都能用)。

WHO:前面已经说过了,文档是写给谁看的,读者是谁。

WHAT:明确这篇文档的用途,有时候,仅仅说明文档的用途和目的就能帮你搭建起整个文档的框架。

WHEN:明确文档的创建、Review和更新日期。因为文档也有时效性,明确相关日期可以避免阅读者踩坑。

WHERE:文档应该放在哪!建议一个组织或者团队有统一的永久文档存放地址,并且有版本控制。最好是方便查找、使用和分享。

WHY:为什么要写这篇文档, 你期望读者读完后从文档中获得什么?

4.2 三段式写作

写文章一般都会有三个部分,专业写作者也讲究凤头、猪肚、豹尾,这三个词概括出了好文章三部分应有的特点。

技术文档也算是文章的一种,所以一般也都会有这三部分,每个部分有其自己的作用,比如第一部分阐述问题,中间部分介绍具体的解决方案,第三部分总结要点。

但这也并不以为着文档应该有三个部分,如果文档内容比较多,可以将其做更细致的拆解,可以适当增加一些冗余的信息帮助读者理解文档内容。

虽然很多工程师都讨厌冗余 极力追求简洁,但写文档和写代码不同,适当的冗余反而可以帮助读者理解,很简单,举个例子,比如写作中经常举例子,举的例子本质上就是冗余信息,生动的例子肯定是能帮助读者理解抽象内容的(我想这就是自举吧)。

- 5 -

结语

目前看到比较好的一个现象就是大家越来越重视文档了,但和测试相比重视的程度还不够。

测试已经是工作流程中不可或缺的一部分了,而文档依旧还不是。

当然这可能和文档本身的特性相关,测试很容易被自动化,也有非常多的客观指标来评估。文档却做不到,首先文档的书写需要人手动介入,而文档的质量也没有太多客观的指标评估,提升文档的数量和质量只能从文化和工作流程上去逐渐改变。

最后总结下本文几个关键点:

随着时间的推移和组织规模的壮大,文档会越来越重要。

  • 文档也应该是开发流程的一部分。

  • 一篇文档只专注在一件事上。

  • 文档是写给读者看的,而不是给你自己看的。

转自:xindoo, https://www.cnblogs.com/xindoo/p/15085988.html


c7e85b1d691044fe92288c4f7ff4ab9d.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1952372.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Dockerfile指令详解和Docker操作命令

1.容器的特点:1)自包含(包括应用程序及其运行环境);2)可移植;3)相互隔离;4)轻量级。 2.docker成为容器的事实标准在于:1)在运行环境上…

Unity 资源 之 Pop It 3D 解压玩具与双人AI游戏 Unity 资源包分享

精彩呈现:Pop It 3D 解压玩具与双人AI游戏 Unity 资源包分享 一、Pop It 3D 解压玩具的魅力二、双人游戏的互动乐趣三、Unity 游戏资源包的优势四、如何获取资源包 亲爱的游戏爱好者们,今天为大家带来一款令人兴奋的游戏资源——Pop It 3D 解压玩具双人带…

ubuntu串口重命名助手arm64架构(下)Qt交叉编译arm64

✨✨ Rqtz 个人主页 : 点击✨✨ 🎈PyQt系列专栏:点击🎈 🎈Qt智能车上位机专栏: 点击🎈 🎈Qt串口助手专栏:点击🎈 💫宗旨:共享IT之美,共创机器未来 目录 前言 设备介绍 查询系统架构 下载…

【JVM基础05】——组成-能不能解释一下方法区?

目录 1- 引言:方法区概述1-1 方法区是什么?(What)1-2 为什么用方法区?方法区的作用 (Why) 2- ⭐核心:详解方法区(How)2-1 能不能解释一下方法区?2-2 元空间内存溢出问题2-3 什么是常量池?2-4 运行时常量池 …

Stable Diffusion WebUI本地环境搭建

一、项目代码下载 git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui 二、环境配置 conda create --n stafu python3.10.6 实际上跟自己创建的环境没有关系,项目启动会自动复制这个环境,之后项目根据这个基础环境构建 也可以在自己…

【五】MySql8基于m2芯片arm架构Ubuntu24虚拟机安装

文章目录 1. 更新系统包列表2. 安装 MySQL APT Repository3. 更新系统包列表4. 安装 MySQL Server5. 运行安全安装脚本6. 验证 MySQL 安装7. 配置远程连接7.1 首先要确认 MySQL 配置允许远程连接:7.2 重启 MySQL 服务:7.3 检查 MySQL 用户权限&#xff1…

TensorRT推理时间不稳定的解决方案

目录 解决方案 第一步 第二步 效果 解除锁频方法 解决方案 锁定GPU时钟频率(实测有效) 第一步 使用 nvidia-smi -q -d SUPPORTED_CLOCKS 查询GPU支持的最高频率,如下图所示为 8001 MHz 第二步 cmd(管理员权限&#xff09…

0719_驱动2 编写编译linux内核模块

一、编写linux内核模块 linux内核模块三要素&#xff1a; 入口&#xff1a;执行insmod 安装命令操作 出口&#xff1a; 执行rmmod 卸载命令操作 许可证&#xff1a;遵循GPL协议&#xff0c;开源&#xff0c;指定入口地址&#xff0c;出口地址 #include <linux/init.h> #i…

JAVA同城圈子达人交友系统源码支持微信小程序+公众号+H5+APP

&#x1f308; 同城圈子达人交友系统&#xff0c;遇见志同道合的TA&#xff01; &#x1f389; 开篇&#xff1a;告别孤单&#xff0c;同城圈子等你来探索&#xff01; 在这个快节奏的城市生活中&#xff0c;你是否常常感到孤独&#xff0c;渴望找到一群志同道合的朋友&#…

SQL labs-SQL注入(三,sqlmap使用)

本文仅作为学习参考使用&#xff0c;本文作者对任何使用本文进行渗透攻击破坏不负任何责任。 引言&#xff1a; 盲注简述&#xff1a;是在没有回显得情况下采用的注入方式&#xff0c;分为布尔盲注和时间盲注。 布尔盲注&#xff1a;布尔仅有两种形式&#xff0c;ture&#…

Django学习(二)

get请求 练习&#xff1a; views.py def test_method(request):if request.method GET:print(request.GET)# 如果链接中没有参数a会报错print(request.GET[a])# 使用这个方法&#xff0c;当查询不到参数时&#xff0c;不会报错而是返回你设置的值print(request.GET.get(c,n…

深入解析Flowable:工作流与业务流程管理引擎

深入解析Flowable&#xff1a;工作流与业务流程管理引擎 引言 在数字化时代&#xff0c;企业对流程自动化的需求日益增长。有效的工作流和业务流程管理系统可以帮助组织提高生产力、优化资源分配以及增强决策支持。Flowable是一款开源的工作流和业务流程管理&#xff08;BPM&a…

Hadoop单机版环境搭建

一 . 案例信息 Hadoop 的安装部署的模式一共有三种&#xff1a; 本地模式&#xff0c;默认的模式&#xff0c;无需运行任何守护进程&#xff08; daemon &#xff09;&#xff0c;所有程序都在单个 JVM 上执行。由 于在本机模式下测试和调试 MapReduce 程序较为方便&#x…

Ghost Buster Pro for Mac:系统优化的得力助手

Ghost Buster Pro for Mac是一款功能强大的系统优化工具&#xff0c;专为Mac用户设计&#xff0c;旨在提供全方位的系统清理、优化和维护服务。 这款软件拥有出色的垃圾清理能力&#xff0c;能够深度扫描并清除Mac上的无效目录、文件、系统日志、下载历史记录、缓存和临时文件…

WARNING: Ignoring invalid distribution -ip警告信息如何去掉?

查看已安装依赖列表的时候&#xff0c;出现了很多警告信息&#xff0c;如何去掉呢&#xff1f; 解决办法 打开这个路径&#xff1a;d:\software\python\python39\lib\site-packages 这种波浪线开头的&#xff0c;我们将它删除掉,就可以了。

使用 leanback 库 GridView 管理AnroidTV的焦点

一、前情提要 我当前需要开发一个TV应用&#xff0c;但是之前处理过的焦点问题的很少&#xff0c;现在空下来了&#xff0c;对过往的工作做一个总结分享。在手机APP开发中常用的 RecycleView 在 TV 中开发时&#xff0c;无法解决大量的焦点问题&#xff0c;所以使用leanback进…

OSPF LSA 格式及字段详解

在 AS 内的每台设备&#xff0c;根据设备的路由器类型产生一种或多种 LSA。 LSA 的集合形成了 LSDB&#xff08;Link-state Database&#xff09;。 OSPF 中对路由信息的描述都是封装在 LSA 中发布出去的。 常用的 LSA 包括&#xff1a; Router-LSANetwork-LSASummary-LSA&…

postgres启动错误

说明&#xff1a;记录一次在Linux上启动postgres数据错误&#xff1b; 问题&#xff1a;安装好postgres数据库后&#xff0c;我使用systemctl启动数据库&#xff0c;报下面的错误 ● postgresql-15.service - PostgreSQL 15 database serverLoaded: loaded (/usr/lib/systemd…

力扣225 | 两个队列实现栈的思想解析 | 详细图解 Java代码实现

做题链接 目录 前言&#xff1a; 一、思想详解 1.push(x) 2.pop() 弹出栈顶元素 3.top() 获取栈顶元素&#xff08;但不弹出&#xff09; 4.empty() 二、编程实战 1.Java前置知识 2.代码实现&#xff1a; 前言&#xff1a; 栈是一种后进先出数据结构。队列是一种先进…

学习大数据DAY22 Linux 基 本 指 令 3与 在 Linux 系 统 中 配 置MySQL 和 Oracle

目录 网络配置类 ps 显示系统执行的进程 kill systemctl 服务管理 配置静态 ip 常见错误---虚拟机重启网卡失败或者网卡丢失 mysql 操作 上机练习 6---安装 mysql---参考《mysql 安装》文档 解锁 scott 重启后的步骤 上机练习 7---安装 oracle---参考《oracle 安装》…