如何写好技术文档?-程序员宅基地

技术标签: DevOps  如何写好  技术文档  

在大多数软件工程师对编写、使用和维护代码的抱怨中,一个常见的问题是缺乏高质量的文档。缺乏文档有什么副作用呢?当遇到一个bug时,这个缩写是什么意思?这份文件是最新的吗?在整个职业生涯中,每个软件工程师都抱怨过文档的质量、数量或者完全缺乏文档。

01

为什么需要写文档?

高质量文档对工程组织有巨大的好处。代码和api变得更容易理解。当他们的设计目标和团队目标被清楚地陈述时,项目团队会更加专注。当步骤被清晰地列出时,手动流程更容易遵循。如果过程被清楚地记录下来,那么让新成员进入团队或代码库所花费的精力就会少得多。

但是,由于文档的好处有一定的滞后性,通常不会给作者带来直接的好处。不像测试,编写完测试用例,跑一遍就有结果。毕竟,你可能只编写了一个文档,但之后它将被阅读数百次,甚至数千次;它的初始成本将摊销给所有未来的读者。文档不仅可以随着时间的推移而扩展,而且它对组织的其他部分的扩展也很关键。它有助于回答以下的问题:

  • 为什么会做出这些设计决策?
  • 为什么要以这种方式实现这段代码?
  • 为什么大多数工程师不喜欢写文档?

虽然文档可以带来不少好处,为什么工程师通常认为它是糟糕的?其中一个原因,正如我们提到的,是好处不是立竿见影的,特别是对作者来说。另外还有以下几点:

  • 很多工程师习惯将写代码和写作割裂开,不仅仅是在工作上,而且在思想上就认为它们是完全不相关的两项工作,这就导致好多人重代码不重文档。
  • 也有很多工程师认为自己不善写作,索性就不写了。这实际是个偷懒的借口,写文档不需要华丽的辞藻、生动的语言,你只需要将问题讲清楚即可。
  • 有时候工具不好用也会影响的文档写作。如果没有一个很好的写作工具将写文档嵌入到开发工作流程中的话,写作确实会增加工作的负担。
  • 大多数人将写文档看做是工作的额外负担。我代码都没时间写,哪有时间写文档!,这其实是错误的观念,文档虽然前期有投入,但能让你代码的后期维护成本大幅降低,磨刀不误砍柴工这个道理相信大家都还是能理解的。

02

写文档的重要性

另外一个原因是文档被视为需要维护的额外负担,而不是使现有代码的维护更容易的东西。

写文档同样对作者也有非常大的好处:

  • 它有助于审视API。编写文档是确定API是否有意义的最可靠的方法之一。通常,编写文档本身会使工程师重新评估设计决策。如果你不能解释它,不能定义它,那你可能还没有设计好它。
  • 它提供了维护的历史记录。在任何情况下,代码中的技巧都应该避免,但是当你盯着两年前编写的代码,试图找出错误所在时,好的注释将提供很大的帮助。
  • 它使你的代码看起来更专业。开发人员自然会认为文档完备的API就是设计得更好的API。虽然情况并非总是如此,但它们通常是高度相关的。虽然这个好处听起来像是表面文章,但事实并非如此:一个产品是否有良好的文档通常是一个很好的指标。

这将减少其他用户提出的问题。对于编写文档的人来说,随着时间的推移这可能是最大的好处。如果你必须向某人解释某件事不止一次,那么记录该过程通常是有意义的。

03

像管理代码一样管理文档

软件工程师使用单一的、主要的编程语言来编写程序,他们仍然经常使用不同的语言来解决特定的问题。工程师可能会编写shell脚本或Python来运行命令行任务,或者他们可能会用c++编写大部分后端代码,但用Java编写一些中间件代码,等等。每种语言都是工具箱中的一种工具。

文档也应该如此:它是一种工具,用不同的语言编写,以完成特定的任务。编写文档与编写代码没有多大区别。与编程语言一样,它有规则、特定的语法和样式决定,通常是为了实现与代码中类似的目的:加强一致性、提高清晰度和避免理解错误。

文档通常与代码紧密耦合,因此应该尽可能地将其视为代码。也就是说,文档也应具有如下的属性:

  • 有明确的责任人维护;
  • 有统一的内部规范;
  • 定期更新;
  • 有变更和评审机制;
  • 有问题反馈和更新机制;
  • 明确文档的读者是谁

工程师在编写文档时犯的一个最重要的错误是只为自己编写文档。这样做是很自然的,并且为自己编写代码并非没有价值:毕竟,你可能需要在几年后查看这些代码,并试图弄清楚你曾经的想法。或者说在团队较小的时候,大家的工作交集很大,因此也能看懂你的文档,但是随着组织的发展,问题就逐渐凸显,新人会有这不同背景,团队大了以后,工作内容开始细化,交集减少,这时候之前写的文档对他们来说可能就很难理解了。

因此在开始写作之前,应该(正式或非正式地)确定文档需要满足的受众。设计文件可能需要说服决策者。教程可能需要为完全不熟悉代码库的人提供非常明确的说明。API可能需要为该API的任何用户(无论是专家还是新手)提供完整和准确的参考信息。

好的文档不需要修饰或完善。工程师在编写文档时所犯的一个错误是认为他们需要成为更好的作者。按照这个标准,很少有软件工程师会写。记住,我们的观众站在你曾经站过的地方,但没有你新的领域知识。所以你不需要成为一个伟大的作家;你只需要找一个像你一样熟悉这个领域的人。

04

文档类型

作为工作的一部分,工程师会编写各种不同类型的文档:设计文档、代码注释、操作文档、项目页面等等。这些都可以算作文档。但重要的是要知道不同的类型,不要混合类型。一般来说,文档应该有一个单一的目的。正如API应该做一件事并且做好一样,避免在一个文档中做几件事。

软件工程师经常需要编写几种主要类型的文档:

  • 参考文档,包括注释
  • 设计文档;
  • 教程;
  • 概念性文档;

1.参考文档

参考文档是工程师最常编写的文档类型;事实上,他们经常需要每天写一些参考文档。代码注释是工程师必须维护的最常见的参考文档形式。这些注释可以分为两个基本阵营:API注释和实现注释。这两种用户之间的区别:API注释不需要讨论实现细节或设计决策,也不要假设用户和作者一样精通API。但是实现注释可以假定读者有更多的领域知识,但是要注意不要假设得太多。

2.设计文档

大多数公司在项目开始之前都需要有设计文档。软件工程师通常使用团队批准的特定设计文档模板来编写建议的设计文档。然后还需要在特定的团队会议上讨论或评论设计的细节。

一个好的设计文档应该涵盖:

  • 设计目标
  • 实现策略
  • 利弊权衡和具体决策
  • 替代方案
  • 各方案的优缺点

一份优秀的设计文件,一旦获得批准,不仅可以作为历史记录,还可以作为项目是否成功实现其目标的衡量标准。大多数团队会将他们的设计文档进行归档,以便在后续的时间查看。在产品发布前检查设计文档通常是很有用的,以确保编写设计文档时所陈述的目标在发布时仍然是所陈述的目标(如果不是,那么文件或产品都可以进行相应的调整)。

3.教程

每个软件工程师,当他们加入一个新的团队时,都会想要尽可能快地跟上进度。拥有一个引导人们完成新项目设置的教程是非常有价值的。

通常情况下,编写教程的最佳时机是你第一次加入一个团队的时候。拿个记事本或其他方法做笔记,写下一路上你需要做的所有事情,假设没有领域知识或特殊的设置限制;完成之后,可能会知道在这个过程中所犯的错误和原因,然后可以编辑你的步骤,以获得更精简的教程。重要的是,写下一路上你需要做的一切;尽量不要假定任何特定的设置、权限或领域知识。

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

4.概念性文档

有些代码需要更深入的解释或见解,而不是仅仅通过阅读参考文档就能得到的。在这些情况下,我们需要概念性文档来提供api或系统的概述。概念性文档处理可能是API的库概述、描述服务器中数据生命周期的文档等。概念性文档是用来扩充而不是替换参考文档集的。有时候这和参考文档会有些内容重复,,但主要还是为了更深层次的说明某些问题、解释清楚某个概念。概念性文档没有必要涵盖所有边缘情况。在这种情况下,为了清晰度而牺牲一些准确性是可以接受的。概念性文件的要点在于传达理解。

概念文档是最难编写的文档形式。因此,它们通常是软件工程师工具箱中最容易被忽视的文档类型。而且还有另外一个问题,没合适的地方放,参考文档可以写代码里,落地页可以写项目主页里,概念性文档似乎也只能在项目文档里找个不起眼的角落存放了。

概念文档需要对广泛的受众有用:无论是专家还是新手。此外,它需要强调清晰性,所以它通常需要牺牲完整性(最好留作参考)和(有时)严格的准确性。这并不是说概念性文件应该故意不准确;这只是意味着它应该关注常见的用法,而将罕见的用法或副作用留作参考文档。

05

文档Review

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

技术文档得益于三种不同类型的review,每种审查都强调不同的方面:

  • 专业的视角来保证准确性:一般由团队里比较资深的人负责,他们关注的核心点是文档写的对不对,专不专业。如果Code Review做的好的话,文档的Review也属于Code Review的一部分。
  • 读者视角保证简洁性:一般由不熟悉这个领域的人来Review,比如团队的新人,或者文档的使用者。这部分主要是关注文档是否容易被看懂。
  • 写作者视角保证一致性:由写作经验丰富或者相关领域比较资深的人承担,主要是为了保证文档前后是否一致,比如对同一个专业术语的使用和理解是否有歧义。

06

文档写作的哲学

下面的部分更多地是关于技术写作最佳实践的论述。

5W法则相信大家已经听的多了,分别是WHO, WHAT, WHEN, WHERE, WHY,这是一个广泛被用在各行各业的法则,写文档当然也不例外。

WHO:正如前面所说,文档的针对对象是谁,读者是谁。

WHAT:明确文档写作的用途,通常仅需说明文档的用途和目的就能帮你搭建起整个文档的框架。

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

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

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

1.三段式文档

所有文档,文档的所有部分都有开头、中间和结尾。尽管这听起来非常愚蠢,但大多数文件通常都应该有这三个部分。不要害怕在文档中添加章节;它们将流程分解为逻辑部分,并为读者提供文档所涵盖内容的路线图。

通常开头部分代表问题,中间部分介绍推荐的解决方案,结尾部分总结结论。但这也并不以为着文档应该有三个部分,如果文档内容比较多,可以将其做更细致的拆解,可以适当增加一些冗余的信息帮助读者理解文档内容。虽然很多工程师都讨厌冗余 极力追求简洁,但写文档和写代码不同,适当的冗余反而可以帮助读者理解。

2.好文档必备的属性

好的文档通常有三个方面:完整性、准确性和清晰度。很少在同一个文档中同时获得这三种信息;例如,当你试图使文档更完整时,清晰度就会开始受到影响。如果您试图记录API的每个可能的用例,您可能会得到一个难以理解的混乱。对于编程语言来说,在所有情况下都做到完全准确(并记录所有可能的副作用)也会影响清晰度。对于其他文件,试图明确一个复杂的主题可能会微妙地影响文件的准确性;例如,您可能决定忽略概念性文档中的一些罕见的副作用,因为文档的目的是让人们熟悉API的用法,而不是提供对所有预期行为的武断概述。

在每种情况下,一个好的文档都被定义为正在执行其预期工作的文档。因此,您很少希望文档执行一项以上的工作。对于每个文档(以及每个文档类型),确定其重点并适当调整编写,写概念性文档可能不需要涵盖API的每个部分,写一个参考可能想要这个完整,但可能必须牺牲一些清晰度等。所有这些加起来就是质量,不可否认的是,质量很难精确衡量。

07

结论

公平地说,对文档的处理与对测试的处理并不一定相同。对测试来讲可以进行原子测试(单元测试),并遵循规定的形式和功能。在大多数情况下,文件不能。测试可以自动化,但通常缺乏自动化文档的方案。文件必然是主观的;文档的质量不是由作者来衡量的,而是由读者来衡量的,而且通常是异步的。

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

  • 随着时间推移,团队的壮大,文档会越来越重要;
  • 文档应该是开发人员工作流程的一部分;
  • 每篇文档专注于一个目的;
  • 文档是给读者看的,而不是你自己写作。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u012294613/article/details/123892015

智能推荐

class和struct的区别-程序员宅基地

文章浏览阅读101次。4.class可以有⽆参的构造函数,struct不可以,必须是有参的构造函数,⽽且在有参的构造函数必须初始。2.Struct适⽤于作为经常使⽤的⼀些数据组合成的新类型,表示诸如点、矩形等主要⽤来存储数据的轻量。1.Class⽐较适合⼤的和复杂的数据,表现抽象和多级别的对象层次时。2.class允许继承、被继承,struct不允许,只能继承接⼝。3.Struct有性能优势,Class有⾯向对象的扩展优势。3.class可以初始化变量,struct不可以。1.class是引⽤类型,struct是值类型。

android使用json后闪退,应用闪退问题:从json信息的解析开始就会闪退-程序员宅基地

文章浏览阅读586次。想实现的功能是点击顶部按钮之后按关键字进行搜索,已经可以从服务器收到反馈的json信息,但从json信息的解析开始就会闪退,加载listview也不知道行不行public abstract class loadlistview{public ListView plv;public String js;public int listlength;public int listvisit;public..._rton转json为什么会闪退

如何使用wordnet词典,得到英文句子的同义句_get_synonyms wordnet-程序员宅基地

文章浏览阅读219次。如何使用wordnet词典,得到英文句子的同义句_get_synonyms wordnet

系统项目报表导出功能开发_积木报表 多线程-程序员宅基地

文章浏览阅读521次。系统项目报表导出 导出任务队列表 + 定时扫描 + 多线程_积木报表 多线程

ajax 如何从服务器上获取数据?_ajax 获取http数据-程序员宅基地

文章浏览阅读1.1k次,点赞9次,收藏9次。使用AJAX技术的好处之一是它能够提供更好的用户体验,因为它允许在不重新加载整个页面的情况下更新网页的某一部分。另外,AJAX还使得开发人员能够创建更复杂、更动态的Web应用程序,因为它们可以在后台与服务器进行通信,而不需要打断用户的浏览体验。在Web开发中,AJAX(Asynchronous JavaScript and XML)是一种常用的技术,用于在不重新加载整个页面的情况下,从服务器获取数据并更新网页的某一部分。使用AJAX,你可以创建异步请求,从而提供更快的响应和更好的用户体验。_ajax 获取http数据

Linux图形终端与字符终端-程序员宅基地

文章浏览阅读2.8k次。登录退出、修改密码、关机重启_字符终端

随便推点

Python与Arduino绘制超声波雷达扫描_超声波扫描建模 python库-程序员宅基地

文章浏览阅读3.8k次,点赞3次,收藏51次。前段时间看到一位发烧友制作的超声波雷达扫描神器,用到了Arduino和Processing,可惜啊,我不会Processing更看不懂人家的程序,咋办呢?嘿嘿,所以我就换了个思路解决,因为我会一点Python啊,那就动手吧!在做这个案例之前先要搞明白一个问题:怎么将Arduino通过超声波检测到的距离反馈到Python端?这个嘛,我首先想到了串行通信接口。没错!就是串口。只要Arduino将数据发送给COM口,然后Python能从COM口读取到这个数据就可以啦!我先写了一个测试程序试了一下,OK!搞定_超声波扫描建模 python库

凯撒加密方法介绍及实例说明-程序员宅基地

文章浏览阅读4.2k次。端—端加密指信息由发送端自动加密,并且由TCP/IP进行数据包封装,然后作为不可阅读和不可识别的数据穿过互联网,当这些信息到达目的地,将被自动重组、解密,而成为可读的数据。不可逆加密算法的特征是加密过程中不需要使用密钥,输入明文后由系统直接经过加密算法处理成密文,这种加密后的数据是无法被解密的,只有重新输入明文,并再次经过同样不可逆的加密算法处理,得到相同的加密密文并被系统重新识别后,才能真正解密。2.使用时,加密者查找明文字母表中需要加密的消息中的每一个字母所在位置,并且写下密文字母表中对应的字母。_凯撒加密

工控协议--cip--协议解析基本记录_cip协议embedded_service_error-程序员宅基地

文章浏览阅读5.7k次。CIP报文解析常用到的几个字段:普通类型服务类型:[0x00], CIP对象:[0x02 Message Router], ioi segments:[XX]PCCC(带cmd和func)服务类型:[0x00], CIP对象:[0x02 Message Router], cmd:[0x101], fnc:[0x101]..._cip协议embedded_service_error

如何在vs2019及以后版本(如vs2022)上添加 添加ActiveX控件中的MFC类_vs添加mfc库-程序员宅基地

文章浏览阅读2.4k次,点赞9次,收藏13次。有时候我们在MFC项目开发过程中,需要用到一些微软已经提供的功能,如VC++使用EXCEL功能,这时候我们就能直接通过VS2019到如EXCEL.EXE方式,生成对应的OLE头文件,然后直接使用功能,那么,我们上篇文章中介绍了vs2017及以前的版本如何来添加。但由于微软某些方面考虑,这种方式已被放弃。从上图中可以看出,这一功能,在从vs2017版本15.9开始,后续版本已经删除了此功能。那么我们如果仍需要此功能,我们如何在新版本中添加呢。_vs添加mfc库

frame_size (1536) was not respected for a non-last frame_frame_size (1024) was not respected for a non-last-程序员宅基地

文章浏览阅读785次。用ac3编码,执行编码函数时报错入如下:[ac3 @ 0x7fed7800f200] frame_size (1536) was not respected for anon-last frame (avcodec_encode_audio2)用ac3编码时每次送入编码器的音频采样数应该是1536个采样,不然就会报上述错误。这个数字并非刻意固定,而是跟ac3内部的编码算法原理相关。全网找不到,国内音视频之路还有很长的路,音视频人一起加油吧~......_frame_size (1024) was not respected for a non-last frame

Android移动应用开发入门_在安卓移动应用开发中要在活动类文件中声迷你一个复选框变量-程序员宅基地

文章浏览阅读230次,点赞2次,收藏2次。创建Android应用程序一个项目里面可以有很多模块,而每一个模块就对应了一个应用程序。项目结构介绍_在安卓移动应用开发中要在活动类文件中声迷你一个复选框变量

推荐文章

热门文章

相关标签