文档对于项目开发和维护、学习、重构、以及知识管理非常重要。
和写测试一样、大部分开发人员会觉得写文档是一件痛苦的事情,不过只有时间能够证明它的价值。比如对于人员流动比较大的公司,如果有规范的文档体系,转交工作就会变动非常轻松.
广义的文档不单指‘说明文件’本身,它有很多形式、来源和载体,可以描述一个知识、以及知识形成和迭代的过程。例如版本库代码提交记录、代码注释、决策和讨论记录、CHANGELOG、示例代码、规范、传统文档等等

1. 建立文档中心

我们公司是做IM的,所以之前我们优先使用’自己的’通讯工具来分享文档,这种方式有很大问题:

  1. 如果没有存档习惯(比如后端的API文档,因为由后端维护,一般不会主动去存档), 文档就可能丢失,而且通讯工具是不会永久保存你的文档的。当丢失文件就需要重新和文档维护者索要
  2. 糟糕的是文档维护者也是自己手动在本地存档的,这样导致的问题是: 如果工作转交,其他开发者需要花费一点时间来查找; 丢失了就真的没了
  3. 每一次文档更新要重新发一份, 这很麻烦,而且可能出现漏发的情况, 导致前后不一致.
  4. 关于知识的学习、以及有意义的讨论记录无法归档。

上面介绍的是一种非常原始的文档共享方式,很多小团队就是这么干的。
对于项目本身的文档建议放置在关联项目版本库里面,跟随项目代码进行迭代, 当我们在检索或跟踪文档的历史记录时,这种方式是最方便的
然而很多应用是跨越多个团队的,每个团队都会有自己的文档输出(比如需求文档、系统设计文档、API文档、配置文档等等),而且通常也不会在一个版本库里。这时候文档就比较分散。所以一个统一的文档中心是很有必要。
我们公司现在选择的方案是Git+Markdown,也就是说所有的文档都放置在一个git版本库下。之前也考虑过商业的方案,譬如石墨文档腾讯文档, 但管理层并不信任这些服务。
大概的git项目组织如下:
规范/ A应用/ 产品/ 设计/ API文档/ 测试/ 其他/ B应用/ 复制代码
Git版本库(例如Gitlab)有很多优势,例如历史记录跟踪、版本化、问题讨论(可以关联issue、或者提交)、多人协作、搜索、权限管理(针对不同的版本库或分组为不同人员设置权限)等等
Git+Markdown可以满足开发者的大部分需求。但是Git最擅长的是处理纯文本文件、对于二进制是无能为力的,无法针对这些类型的文档进行在线预览和编辑
所以Git+Markdown并不能满足多样化的文档处理需求,比如思维导图、图表、表格、PPT、白板等需求. 毕竟它不是专业的文档处理工具。所以对于产品、设计人员这些富文档需求场景,通常会按照传统方式或者更专业的工具对文档进行管理.

2. 文档格式

毫无疑问,对于开发者来说,Markdown是最适合的、最通用的文档格式。支持版本库在线预览和变更历史跟踪。
下面这些工具可以提高Markdown的开发效率:

  • 可视化编辑器
    • Visual Code: 大部分代码编辑都支持Markdown编辑和预览
    • Mou: Mac下的老牌编辑器
    • typora: 跨平台的Markdown编辑器,推荐
  • markdownlint: 编码检查器
  • 扩展(Visual Studio Code):
    • Markdown All in One: All you need to write Markdown (keyboard shortcuts, table of contents, auto preview and more)
    • Markdown TOC: markdown 目录生成,我最常用的markdown插件
  • 图表绘制工具:

    • drawio 基于Web的图表绘制工具、也有离线客户端
    • KeyNote/PPT 临时绘图也不错

      3. 定义文档的模板

      关于如何写好文档,很难通过标准或规范来进行约束,因为它的主观性比较强, 好的文档取决于编辑者的逻辑总结能力、表达能力、以及有没有站在读者的角度去思考问题。
      所以大部分情况下,我们可以为不同类型的文档提供一个模板,通过模板来说明一个文档需要包含哪些内容, 对文档的编写者进行引导.
      例如一个API文档可能需要这些内容:
  • 接口的索引

  • 接口的版本、变更记录
  • 用法和整体描述, 认证鉴权等等
  • 描述具体的接口
    • 功能说明
    • 方法名称或者URI
    • 参数和返回值定义
    • 调用示例
    • 注意事项等等

具体规范内容因团队而异,这里点到为止.
扩展:

  • 中文技术文档的写作规范
  • React RFC模板

    4. 讨论即文档

    一般情况下,对于一个开源项目来说除了官方文档,Issues也是一个很重要的信息来源。在Issue中我们可以获取其他开发者遇到的问题和解决方案、给官方反馈/投票、关注官方的最新动态、和其他开发者头脑风暴唇枪舌战等等
    所以相对于使用IM,笔者更推荐Issue这种沟通模式,因为它方便归档组织,索引和查找。而IM上的讨论就像流水一样,一去不复返。
    当然两种工具的适用场景不一样,你拿IM的使用方式来使用Issue,Issue就会变得很水。Issue适合做有意义的、目的明确的讨论。 所以要谴责一下在Github Issue上灌水的开发者。
    关于Issue有很多妙用,推荐阅读这篇文章<如何使用 Issue 管理软件项目?>
    现在很多开源项目都引入了RFC(请求意见稿)流程(参考React采用新的RFC流程, 以及Vue 最黑暗的一天), 这让开发者有‘翻身农奴、当家做主’的感觉,任何人都可以参与到一个开源项目重大事件的决策之中。每个RFC会说明决策的动机、详细设计、优缺点。除了官方文档之外,这些RFC是很有价值的学习资料
    我觉得如果不涉及机密,团队应该要让更多人参与到项目的设计和决策中,对于新手可以学到很多东西,而对于发起者也可能有考虑不周的情况。
    那对于企业应用开发, Issue有用吗?
    当然有用, 比如我们可以将这类话题从IM转移到Issue:

  • 设计方案

  • 决策/建议
    • 新功能、新技术引入
    • 重构
    • 性能优化
    • 规范
  • 问题讨论
  • 重大事件
  • 计划或进度跟踪

另外Issue通常通过标签来进行分类,方便组织和检索:
文档规范 - 图1

5. 注释即文档

必要和适量的注释对阅读源代码的人来说就是一个路牌, 可以少走很多弯路.
关于注释的一些准则,<阿里巴巴Java开发手册>总结得非常好, 推荐基于这个来建立注释规范。另外通过ESlint是可以对注释进行一定程度的规范。

6. 代码即文档

现在有很多种工具支持从代码中解析和生成文档, 这可以给开发者简化很多文档维护的工作。
举个例子,我们经常会遇到修改了代码,但是文档忘记同步的情况。通过‘代码即文档’的方式至少可以保持文档和代码同步更新;另外很多工具会分析代码的数据类型,自动帮我们生成参数和返回值定义,这也可以减少很多文档编写工作以及出错率。
比如可以通过下面注释方式来生成组件文档

  1. import * as React from 'react';
  2. import { Component } from 'react'; /** * Props注释 */
  3. export interface ColumnProps extends React.HTMLAttributes<any> {
  4. /** prop1 description */
  5. prop1?: string;
  6. /** prop2 description */
  7. prop2: number;
  8. /** prop3 description */
  9. prop3: () => void;
  10. /** prop4 description */
  11. prop4: 'option1' | 'option2' | 'option3'; }
  12. /** * 对组件进行注释 */
  13. export class Column extends Component<ColumnProps, {}> {
  14. render() {
  15. return <div>Column</div>;
  16. }
  17. }

复制代码
相关的工具有:

  • API文档
    • Typescript
      • tsdoc Typescript官方的注释文档标准
      • typedoc 基于tsdoc标准的文档生成器
    • Javascript
      • jsdoc Javascript文档注释标准和生成器
  • 后端接口文档
    • Swagger Restful接口文档规范
    • GraphQL: 这个有很多工具,例如graphiql, 集成了Playground和文档,很先进
    • Easy Mock 一个可视化,并且能快速生成模拟数据的服务
  • 组件文档