前言

我们是如何书写设计文档的呢?
团队的设计文档是什么样的呢
好的设计文档应该是什么样的呢?

以小见大 传统与现状

现代软件工程的过程图(我自己画的)

现代软件工程.png

设计” 一词非常精妙。无论是 “产品设计”,还是 “架构设计”,其实谈的都是 “需求如何被满足” 这件事情的共识。

协同价值表示图:

协同价值.png

换个角度来说,一个企业的使命、愿景与价值观,何尝不是这个企业最高维度的 “设计” 呢?

本质上所有 “设计文档” 的内容组织逻辑,都应该是相通的。它们的内容大体如下:

  • 现状 :我们在哪里,现状是什么样的?
  • 需求:我们的问题或诉求是什么,要做何改进?
  • 需求满足方式:要做成什么样,交付物规格,或者说使用界面(接口)是什么?
  • 怎么做到?交付物的实现原理。

设计文档要素的关键在于以下几点

  • 现状:不要长篇累牍
  • 需求:同样不需要长篇累牍。
  • 需求满足方式:要详写,把我们的设计方案谈清楚。具体来说,它包括 “交付物规格” 和 “实现原理” 两个方面。

实现原理

  • “产品设计”,它谈的是用户需求对应的 UserStory 设计,也就是业务流具体是怎么完成的。
  • “架构设计”,它谈的是 UserStory 具体如何被我们的程序逻辑所实现。

指导思想

程序 = 数据结构 + 算法

“数据结构” 可以是内存数据结构,也可以是外存数据结构,还可以是数据库的 “表结构”。

“算法” 基于 “数据结构”,它描述的是 UserStory 的具体实现,它可以是 UML 时序图(Sequence Diagram),也可以是伪代码(Pseudo Code

多个设计方案的对比

一般的,一篇设计文档有多种设计方案,通常我们会概要地描述清楚两个设计方案的本质差别

维度对比:

  • 方案的易实施性与可维护性。
  • 方案的时间复杂度与空间复杂度。

对于绝大部分业务,我们最关心的是工程效率,所以方案的易实施性与可维护性为先

对于部分对成本与性能非常敏感的业务,则通常在保证方案的时间复杂度与空间复杂度达到业务预期的前提下,再考虑工程效率

确定了设计方案的倾向性后,我们就不会就我们放弃的设计方案做过多的展开,整个设计文档还是以描述一种设计方案为主

但是如果两套设计方案的比较优势没有那么显著时,现实中写两套设计方案确实是存在的,并且应该被鼓励

设计” 是软件工程中的头等大事,我们应该在这里 “多浪费点时间”,这样的 “浪费” 最终会得到十倍甚至百倍以上的回报。

使用界面(接口)

描述交付物的规格上,系统的概要设计,与模块的详细设计很不一样

模块的详细设计

模块的详细设计规格描述比较简单,因为我们关注的面只是模块本身,而非模块之间的关系。

对于模块本身,我们核心关注点是以下两点:

  • 接口是否足够简单,是否自然体现业务需求
  • 尽可能避免进行接口变更,接口要向前兼容

系统的概要设计

第一关心的是模块关系
第二关心的才是各个模块的核心接口
这些接口能够把系统的关键 UserStory 都串起来

表达模块关系在某种程度来说的确非常重要,这可能是许多人喜欢画架构图的原因

我们上传一个文件的业务流程图看起来是这样的:

它从模块关系表达上并不是好的选择,因为根本并没有对模块关系进行抽象。

这类图更多被用在面向客户介绍 API SDK 的背后的实现原理时采用,而非出现在设计文档。

对于 UserStory 业务流程的表达来说,UML 时序图通常是更好的表达方式

怎么表达模块关系呢?

一个方法是对模块的调用接口进行分类:

一个模块对外提供的访问接口无非是:

  • 常规 DOM API,即正常的模块功能调用;
  • 事件(Event)的发送与监听;
  • 插件(Plugin)的注册。

不同类型的访问接口,分别代表了模块间不同的依赖关系

我自己画的mvc 架构图:

mvc 架构图.png

View 监听 Model 层的数据变更事件。View 转发用户交互事件给 Controller。Controller 则负责将用户交互事件转为 Model 层的 DOM API 调用

实现原理

对于模块的详细设计来说,需要先交代清楚 “数据结构” 是什么样的,然后再将一个个 UserStory 的业务流程讲清楚。

对于系统的概要设计来说,核心是交代清楚不同模块的配合关系,所以无需交代数据结构,只需要把一个个 UserStory 的业务流程讲清楚。

无论是否要画 UML 时序图,在表达上伪代码(Pseudo Code)的设计都是必需的。

比如,对于网络请求相关的伪代码


# 请求
post /v1/foo/bar json {...}

# 返回
ret json {...}

类似地,对于 MongoDB,我们可以直接用 MongoDB 的 JavaScript 脚本文法。对于 MySQL,则可以直接基于 SQL 语法

标签: 架构, 接口, 内容, 文档, 设计, 累牍, 现状, 长篇

知识共享许可协议
本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。

发送一条友善的评论

  • 目录