假设我们需要开发一个项目进度管理系统,在这个项目进度管理系统之中,我们需要开发一个功能:项目成员的列表。我们具有这样的业务需求:
-
在项目进度管理系统中,我们需要知道参与项目的人员到底有哪些,并且项目的创建者还需要对这些项目的参与人员在项目中的权限进行管理。在这个列表中,项目的成员可以查看其他成员的信息,也可以修改自己在项目中的名称。
这份业务需求实际上是非常简单的,但是我们具体该如何将业务需求转化为数据流图呢?
绘制数据流图的注意事项
在实际的绘制过程中,我们很容易混淆数据流图(又叫“数据流程图”)和流程图。区分二者的一个办法是:数据经过一个处理之后,数据是否发生明显的变化?如果是流程图,那么其大部分操作可能都在进行条件判断和对输入数据的细微处理,出现这样的情况你就需要考虑将这些处理抽象成一个数据流图中的处理,而屏蔽其具体的处理流程。
举个例子,假设我们具有这样一个处理:“查找项目中的所有成员的信息”,其数据输入是“项目ID”,而其数据的输出是“成员列表”。按照数据流图的思路,该处理是不需要具体再进行细分了的。但如果你按照流程图的思路,你可能会继续进行分解:
-
首先,判断该项目是否存在,如果不存在,则直接返回空;如果存在则执行下面的步骤。
-
查找该项目中的所有成员的信息。
-
打包成成员列表返回给前端。
你不应该将这个太过详细的步骤在数据流图中分解并展开来。你只需要在数据流图中描述数据的输入是什么、输出是什么以及这个处理的名称是什么。但如果分解之后,数据流图还是每个处理都导致数据发生明显变化,那么这个分解就是有价值的,可以进行分解的。
对于哪些无法在数据流图中继续分解的处理,我们需要额外描述,这个描述就是“微规格说明”。
这里讨论这个问题的目的在于提醒读者不要混淆数据流图和流程图。否则你绘制数据流图将很痛苦。
数据流图指导软件设计和开发
针对于前面讨论的“项目成员列表”这个功能,我们可以绘制出这样一个数据流图:
如果我们开发的是一个前后端耦合在一起的软件,那么上面这个数据流图实际上是没有问题的,它的确可以指导项目的开发,并且描述的数据的流动。
但如果我们开发的软件是前后端分离的架构,那么上面的这个流程图就不怎么正确了。对于“处理流程1”,它既有从数据存储中获取数据,又写入数据到数据存储中,那么我想问:“处理流程1”是发生在前端还是后端?你没办法分清楚,此时你需要将对于读取数据存储和向数据存储写入的过程独立成一个数据处理,以准确描述这个前后端分离的架构:
在这之中,1.1、1.3、2.1这些直接和数据存储相连接的都是后端应该负责的处理流程,而1.2、2.1这些不直接从数据存储中获取数据的就应该是前端负责的处理流程。
-
后端的处理流程中,数据的流入和流出关系到前后端数据交互的接口的定义;
-
前端的处理流程中,数据的流入代表了用户进行了某个业务操作,才会触发数据的流入,比如用户点击展示成员列表按钮,那么“项目成员->1.1->1.2”这个处理流程才会真正地触发,在点击完成之后,如果用户不进行任何操作,那么1.3和2.1->2.2的数据流动就不会触发。至于流动过程中的数据,前端该如何获取呢?对于一些数据,我们可以让用户自行输入(这就要求前端写好页面来定义这个输入的流程),或者是由程序在运行的过程中悄咪咪地存储起来,等到用户触发某个数据处理时使用。
按照上面的规则来指导软件的开发,我们可以这样子做:
-
根据数据流图定义好前后端的接口。
-
后端实现接口。
-
前端实现前端的数据处理和数据的流动方式,举个例子,假设用户需要查看项目的成员列表,你可能会在页面上设置一个按钮,这个按钮的点击意味着“项目成员->1.1->1.2”这个数据流动过程开始的标志。从"项目成员->1.1"需要项目ID,这个项目ID从哪里来?你既可以让用户直接输入过来,或者你之前的业务功能已经告诉程序当前的项目ID是什么,此时你就不需要询问用户项目的ID是什么。获取完项目ID之后,请求后端的“查找成员列表”接口,最后,拿到后端返回的数据(由于拿到返回数据的过程可能是异步的,此时你可以要求页面进入等待状态),通过前端技术将这些数据以某种可操作的方式展示出来。
那么定义好数据流图,实际上就一定程度上定义好了前端的业务操作流程,这是完成业务需求所必要的内核。在这个基础之上,前端要做的就是尽可能地优化展示的效果和交互的体验,而非是思考如何完成某个业务需求。