如何写好设计文档

https://www.yuque.com/dataflux/master/how-to-write-design-doc
注意:本文由原始Markdown文件自动生成同步,请勿在语雀中直接编辑本文档
本文主要为需要编写软件设计/开发文档的读者提供一些经验和建议。

阅读前提

  • 了解 Markdown 语法
  • 了解 TyporaSublime TextVS Code 等方便编辑Markdown的编辑器

    面向读者

  • 需要编写产品/功能描述文档的产品经理项目经理

  • 需要针对待开发功能编写基本设计、详细设计的软件工程师

    1. 软件和文档格式选择

    一般来说,软件开发相关的设计文档大多都具有以下特点:

  • 不需要特别花哨的样式

  • 经常需要修改
  • 除UI设计外,以纯文本为主
  • 基本结构、格式大体相同
  • 经常有代码、数据出现,需要方便复制

因此,一般建议此类文档使用纯文本的 Markdown 格式编写。
Markdown 使用一些简单的标记语法,即可展现最常用的标题、列表、重点、引用、代码块、链接等功能。后期也能方便地导出为HTML、PDF等格式。
有关 Markdown 语法可参考:https://www.runoob.com/markdown

2. 设计文档的基本结构

编写设计文档时,必须以「公司新人」的视角去编写,不能对读者实现所了解的内容做任何假设。
因此,一份设计文档,一般来说至少需要包含以下几块内容:

  1. “一句话描述”的标题
  2. 目录
  3. 业务流程
  4. 数据定义

    2.1 「一句话描述」的标题

    不要直接使用「文档」、「设计文档」作为文件名或标题。
    文件名或标题最好使用「一句话描述」,如:
  • DataFlux 新Event数据结构及处理逻辑设计
  • DataFlux 云关联处理逻辑设计

这样,一来不容易有文件重名问题,二来读者能够在不打开文件的情况下,大致了解文档内容。

2.2 目录

任何文档都要添加目录,这样可以方便读者在首次阅读时了解文档大致内容,也能方便快速查阅、跳转到特定内容。
使用 Typora 可以选择「段落 - 内容目录」插入目录
使用 Sublime Text、VS Code 可以使用 MarkdownTOC 等插件生成目录
注意:不同软件的目录实现方式不同,互相之间可能不兼容

2.3 业务流程

任何设计文档都要对业务流程进行描述,具体写明「用户做了什么操作,系统进行了什么处理,最后发生了什么」。
对于简单的业务流程,可以直接使用列表进行描述,如:

  1. 用户输入用户名、密码,点击登录
  2. 系统根据输入内容查找匹配的用户
  3. 匹配成功,跳转到 Dashboard 页面
  4. 匹配失败,提示「用户名或密码错误」

对于复杂的业务流程,可以使用流程图方式描述,如:
如何写好设计文档 - 图1
提示:流程图可以使用ASCII Art、专业流程图工具、PowerPoint、Keynote 等软件进行绘制

2.4 数据定义

业务流程中产生的业务实体,必须明确所有的字段、字段类型、取值范围、数据来源等信息。
假设存在业务实体「课程」,数据定义表格如下:

字段 类型 是否必须 默认值 说明
code String 必须 课程编号,全局唯一
name String 必须 课程名称
type Enum 必须 课程类型,可选值:文科=liberal、理科=science
seatCount Integer 必须 位置数量,取值范围:0 ~ 100
userId String 必须 课程创建人ID。创建时自动填入
teachers Array 必须 教师列表
teachers[#] Array 必须 教师列表元素
teachers[#].userId String 必须 教师的用户ID
teachers[#].position Enum 必须 教师职位,可选值:主讲人=speaker、助教=assistant
tags Array null 课程标签列表
tags[#] String 必须 课程标签元素
extraInfo Dict null 额外信息
extraInfo.computerRequired Boolean false 是否需要自带计算机
extraInfo.outdoorActivityIncluded Boolean false 是否包含户外活动

注意:表格中说明不宜过长,对于某些需要复杂说明的字段,应当为其单独开设下级标题进行详细描述
使用表格展示字段列表,结构更为清晰,对阅读者负担也更低。此外,在因为在编写时也不容易遗漏字段的某些描述。
对于JSON数据,也可以直接使用JSON格式展现,如:
{
// [必须] 课程编号,全局唯一
“code”: “CLASS-001”,
// [必须] 课程名称
“name”: “语文1”,
// [必须] 课程类型,可选值:文科=liberal、理科=science
“type”: “liberal”,
// [必须] 位置数量,取值范围:0 ~ 100
“seatCount”: 100,
// [必须] 课程创建人ID。创建时自动填入
“userId”: “user-001”,
// [必须] 教师列表
“teachers”: [
{
// [必须] 教师的用户ID
“userId”: “user-002”,
// [必须] 教师职位,可选值:主讲人=speaker、助教=assistant
“position”: “speaker”
},
{
“userId”: “user-003”,
“position”: “assistant”
}
],
// 课程标签,元素为String
“tags”: [ “基础”, “必修”, “特级教师主讲” ],
// 额外信息
“extraInfo”: {
// 是否需要自带计算机
“computerRequired”: false,
// 是否包含户外活动
“outdoorActivityIncluded”: true
}
}
注意:使用JSON格式展现时,应当整理为容易阅读的缩进格式
推荐优先使用表格方式描述,JSON方式次之,同时提供表格和JSON方式则为最佳!

3. 更复杂的设计文档

对于小型系统、单个功能模块的设计文档,提供上述4个基本内容基本可以满足需要。
如果是针对整个系统的描述,或者多个、复杂功能模块的设计文档,那么就有必要增加更多的内容来进行说明。

3.1 拆分大型系统的设计文档

对于大型系统的设计文档,应当将文档划分为层级:

  1. 基本设计:描述系统整体架构,但不用涉及到具体功能内部的细节
  2. 详细设计:描述具体功能模块、具体功能所涉及的业务实体、处理流程、字段定义等

    3.2 概念解释

    文档中出现的的概念、业务实体需要明确的定义,避免误解。如:
  • 课程class:指的是包含课件、教材的「课程内容」,如:「云计算入门」
  • 场次activity:指的是某一个课程在特定时间地点进行的活动,如:「云计算入门2021年上海第一场」

并配合示例示例进行说明。如:

  1. 后台管理员创建并录入「云计算入门」课程(这里操作的是「课程class」)
  2. 讲师根据排课表,选择「云计算入门」开课,并指定开课时间(这里操作的是「场次activity」)
  3. 学生根据已经开设的课程,选择城市和时间进行报名(这里操作的是「场次activity」)
  4. 优于疫情,取消了2020年所有的培训(这里操作的是「场次activity」)
  5. 云计算已经深入人心,没有继续开课的必要,「云计算入门」下架(这里操作的是「课程class」)

    3.3 架构图

    无论是系统整体设计,还是单个功能模块的设计,都可以附带架构图方便读者理解。
    如:DataFlux Func 的架构图
    如何写好设计文档 - 图2
    如:DataFlux Func 中「订阅器」的架构图
    如何写好设计文档 - 图3

    3.4 项目文件目录

    已经成型的项目,一方面为了让新人能够快速掌握项目整体情况,另一方面为了规范后续开发工作,可以添加项目文件目录进行说明。
    如:DataFlux Func 项目目录说明
目录/文件 说明
client/ 前端代码(Vue.js)
client/public/ 前端静态文件
client/src/ 前端源代码
client/src/common.js 前端通用业务处理
client/src/const.js 前端常量定义
client/src/toolkit.js 前端非业务通用工具包
server/ 后端代码(Node.js + Express)
server/controllers/ 后端接口处理模块
server/models/ 后端业务实体对象模块
server/routers/ 后端路由模块
server/utils/ 后端非业务通用代码
server/app.js 后端入口文件
server/setup.js 后端安装程序
server/sub.js 后端订阅器
server/route.yaml 后端接口定义
server/const.yaml 后端常量定义
worker/ 工作单元代码(Python3 + Celery)
worker/tasks/ 工作单元任务模块
worker/utils/ 工作单元非业务通用代码
func-pkg/ 内置脚本包,项目启动后自动读取并导入
db/ 数据库导出文件
sdk/ 调用本系统的SDK文件
test/ 自动化测试
tool/ 项目实用小工具
run-server.sh 后端服务启动脚本
run-worker.sh 工作单元启动脚本(监听所有队列)
run-worker-by-queue.sh 工作单元启动脚本(监听指定队列)
run-beat.sh 定时器启动脚本
admin-tool.py 管理员工具
config.yaml 配置文件(所有服务共用)

3.5 参考链接

对于文档中出现的关联、参考文档,应当罗列出来,方便快速参考。如:

  • 阿里云ECS列表API参考文档:https://help.aliyun.com/document_detail/25506.html
  • 腾讯云CVM列表API参考文档:https://cloud.tencent.com/document/product/213/15728
  • AWS EC2列表API参考文档:https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ec2.html

    4. 合理使用格式

    合理使用格式,可以帮助读者更快地理解内容,降低阅读负担。

    4.1 标题

    为每个标题加上分级编号,会使得目录更清晰,同时也能方便读者随时确定当前的阅读位置。
    如本文使用了1.1.11.1.1方式编排大小标题
    但需要注意的是,标题层级不易过深,一般以不超过4层为佳。最小一层的标题可以考虑不添加分级编号,如:
    1. 云计算概述
    2. 云厂商现状
    2.1 国内
    阿里云
    腾讯云
    华为云
    2.2 国外
    AWS
    Azure
    Oracle

    4.2 注意点、提示点

    需要读者注意的地方,应当使用统一的强调格式,如:
    注意:所有的注意点都以「注意:XXX」格式呈现
    同理,一些“顺便一提”的提示内容,也应当使用统一的格式,如:
    提示:所有的提示都以「提示:XXX」格式呈现

    4.3 列表

    罗列内容时,应当使用列表方式展示,如:

  • 阿里云

  • 腾讯云
  • AWS

也可以附上简要说明,如:

  • 阿里云:国内市场份额最大
  • 腾讯云:游戏行业用的比较多
  • AWS:国外市场份额最大

    4.4 链接

    附加官网、入口链接时,可以直接展示为可以点击的URL地址,如:
    https://help.dataflux.cn/
    如果所附带的链接为特定内容,数个链接罗列,URL地址很长等,应当为链接标注文字说明,如:
    DataFlux 产品介绍
    DataFlux 产品优势

    5. 文档编写过程中的注意事项

    在文档编写过程中,对一些细节的把控,可以显著提高文档质量,减少阅读者负担。

    5.1 用词和描述的一致性

    前后一致的用词,不仅可以方便搜索,也能提高阅读效率。
    正确示范:
    阿里云是国内份额最大的云厂商,绝大多数企业用户都选择在阿里云上开展业务。
    与此同时,阿里云的产品也是国内云厂商中最为丰富的一家。
    姓名:字符串,必须,长度范围 2~4
    学校:字符串,必须,长度范围 1~10
    年龄:正整数,必须,取值范围 1~99
    身高:正整数,可选,取值范围 1~200
    错误示范:
    aliyun是国内份额最大的云厂商,绝大多数企业用户都选择在阿里云上开展业务。
    与此同时,Alibaba Cloud 的产品也是国内云平台中最为丰富的一家。
    姓名:字符串,必须,最短2个字符,最长4个字符
    学校:必须,str,长度范围 1~10
    年龄:正整数,取值范围 1~99,必须
    身高:可选,大于0的整数,最大200

    5.2 中英混排时的处理

    中英混排时,在英文前后添加空格会更容易阅读。

  • [推荐]英文前后有空格:阿里云的 ECS 是最核心的产品之一

  • 英文前后未有空格:阿里云的ECS是最核心的产品之一

当中英混排的应为为字段名时,使用代码格式展示。

  • [推荐]字段名使用代码格式:接口返回的InstanceId字段是全局唯一的
  • 字段名未使用代码格式:接口返回的 InstanceId 字段是全局唯一的

当涉及按键时,使用按键格式展示

  • [推荐]使用按键格式:按 + 快捷键保存
  • 未使用按键格式:按 CTRL + S 快捷键保存

    5.3 必要时附上代码示例

    有时,长篇大论不如一个完整的示例更加直观,如:
    在 DataFlux Func 中编写如下代码,即可实现一个加法函数
    @DFF.API(‘两数相加’)
    def plus(x, y):
    ‘’’
    x, y 自动转换为浮点数
    ‘’’
    return float(x) + float(y)

    5.4 涉及与外部系统对接的文档

    当处理涉及到外部系统时,进行简要说明并附带外部系统的文档链接,如:
    DataFlux 云关联处理逻辑
    1. 查询所有当前系统内已有的主机列表
    2. 调用 KODO API 获取本工作空间的 AK 列表
    2. 根据主机列表调用云平台 API 获取 Meta 信息
    3. 根据字段映射,更新方式写回主机对象
    KODO 获取 AK 列表接口文档
    DataWay 更新对象数据 API 文档

    5. 文档的管理和分发

    文档完成后,有条件的可以选择使用 git 管理,也可以使用普通网盘管理。
    当需要使用钉钉群发文档时,可以使用 Typora 的导出为 PDF 功能。方便没有 Markdown 编辑器的人直接在钉钉内预览方式阅读。