学习笔记

如何写文档

(from: Software Engineering at Google)

文档就像写测试,回报比较慢。一次投入可以获得无限的回报。

文档有助于回答这些问题:

  1. 为什么是这样设计的?
  2. 我们为什么用这种方式实现代码?

要把文档当成代码来对待

  1. 需要遵循内部的策略和规则
  2. 放在源代码之下
  3. 有清晰的所有权,并维护文档
  4. 代码改变是,对应的文档也需要更新
  5. 像追踪 bug 一样追踪问题
  6. 像测试一样,定期评估

了解受众

常见的错误是只为自己写文档,认为读者跟自己有大致相同的技能。

根据下面标准定位受众:

  1. 经验水平: 有经验的开发、不熟悉语言的初级工程师
  2. 领域知识: 团队成员、其他团队的成员(只想使用 API 而已)

先编写一个简短的文档,通常要编写一个较长的文档,然后尽可能删除重复的信息。通过保持文档的简短和清晰,让专家和新手都满意。

根据受众如何使用文档:

  1. 寻求者:这部分人知道他们想要什么,想知道看到的内容是否符合他们的要求。
  2. 浏览者:不知道想要什么,文档可以提供 TL;DR: 的说明(too long, don’t read),如:”TL;DR:如果你对谷歌的C++编译器不感兴趣,你现在可以停止阅读。”

文档类型

  1. 参考文档,包括代码注释
  2. 设计文档
  3. 教程
  4. 概念文档
  5. 着陆页

参考文档

API 注释和实现注释。

  1. API 注释:不需要讨论实现细节或者设计策略,也不能假设用户像作者一样精通 API
  2. 实现注释:可以假定读者有更多的领域知识,说明为什么这样写代码

参考文档应该从代码库生成的,Java/Python 都有对应工具,C++ 的头文件就是文档。 参考文档跟代码放一起,方便浏览、搜索和维护,

  1. 文件注释

    文件内容的概要,应该确定代码的主要用例和目标受众。

     -----------------------------------------------------------------------------
     // str_cat.h
     // -----------------------------------------------------------------------------
     //
     // This header file contains functions for efficiently concatenating and appending
     // strings: StrCat() and StrAppend(). Most of the work within these routines is
     // actually handled through use of a special AlphaNum type, which was designed
     // to be used as a parameter type that efficiently manages conversion to
     // strings and avoids copies in the above operations.
     ... ...
    
  2. 类注释

    描述该类/结构、该类的重要方法以及该类的目的。类的注释应该是 “名词化 “的,强调其对象方面。

     // -----------------------------------------------------------------------------
     // AlphaNum
     // -----------------------------------------------------------------------------
     //
     // The AlphaNum class acts as the main parameter type for StrCat() and
     // StrAppend(), providing efficient conversion of numeric, boolean, and
     // hexadecimal values (through the Hex type) into strings.
    
  3. 函数注释

    函数注释应该强调其使用的主动性,以一个指示性动词开始,描述函数的作用和返回的内容。

     // StrCat()
     //
     // Merges the given strings or numbers, using no delimiter(s),
     // returning the merged result as a string.
     ... ...
    

设计文档

设计文档模板要求工程师考虑其设计的各个方面,如安全影响、国际化、存储要求和隐私问题等等。 设计文档建议设计目标,涵盖替代设计,指出其优缺点。

教程

大多数项目都应该有一个 “Hello World“ 文档,该文档不做任何假设,并让工程师去做一些 “真实 “的事情。

尽量不要假设任何特定的设置、权限或领域知识。如果需要,请在本教程的开头明确说明这是一组先决条件。

对用户需要执行的每个操作进行编号。不需要操作的步骤,提示等,不能进行编号。

  1. 从我们的服务器下载软件包,网址为 http://example.com:

    $curl -I http://example.com
    
  2. 将shell脚本复制到主目录:

    $cp foobar.sh ~
    
  3. 在主目录中执行shell脚本:

    $cd ~; foobar.sh
    

    foobar系统将首先与身份验证系统通信。经过身份验证后,foobar将引导一个名为“baz”的新数据库并打开一个输入shell。

  4. 通过在命令行上执行SQL命令来测试“baz”:

    baz:$CREATE DATABASE my_foobar_db;
    

概念文档

有些代码需要比阅读参考文档更深入的解释或见解。在这些情况下,我们需要概念文档来提供API或系统的概述。概念文档都是为了补充而不是取代参考文档集。

例如:文件注释,可以对 API 进行“概念性”解释的合理位置。但是 API 和其他模块一起工作,记录这种复杂行为只能通过一个单独的概念文档。(注释是文档的单元测试,那么概念文档就是集成测试。)

概念文档需要对广大受众有用:包括专家和新手。它还需要强调清晰性,因此通常需要牺牲完整性和严格的准确性。

着陆页

着陆页是产品或API用户的“入门”页面或者是团队的主页。不能把两个同时出现,如果需要两部分内容,可以把团队主页,作为“入门”页的二级页面。

文档评审

让不同的人,从不同的方面进行评审。

写文档的哲学

5W

  1. WHO: 受众
  2. WHAT: 确定本文档用途。如果跟用途不一样,需要移到单独的文档中。
  3. WHEN: 文档本身上注明文档的编写日期(或最后一次修订日期)。
  4. WHERE: 要决定该文档应该放在哪里。
  5. WHY: 设定文件的目的。 总结一下你希望别人在阅读后能从文件中得到什么。

一个好的经验法则是在文件的引言中确立 “为什么”。当你写总结的时候,验证你是否达到了你最初的期望(并进行相应的修改)。

开头、中间和结尾

第一部分表示问题,中间部分是推荐的解决方案,结论总结了要点。

文档中,冗余通常是有用的。冗余有助于读者理解所述内容的重要性。

良好文档的衡量标准

完整性、准确性和清晰性。

废弃文档

当文档不再具有任何用途时,请将其删除或将其标识为已过时(如果可用,请指明获取新信息的位置)。

TL;DRs

  1. 随着时间和规模的增长,文档是非常重要的。
  2. 文档的变化应该利用现有的开发人员的工作流程。
  3. 让文档集中在一个职责(用途)上。
  4. 为你的受众而不是你自己而写。