《需求设计:构建用户想要和需要的产品》——2.2 情境设计

简介:

本节书摘来自华章计算机《需求设计:构建用户想要和需要的产品》一书中的第2章,第2.2节,作者: [英] 克里斯·布里顿(Chris Britton) 更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.2 情境设计

情境设计需要解释IT开发所面对的业务需求。情境设计之中的元素是任务、用户组、数据表及任务之间的消息。本章用4个小节分别讲述这4种元素,然后再用3个小节来讲解任务之间的依赖关系、元素之间的综合以及对情境设计所做的分析。
2.2.1 任务
笔者在前面说过,业务需要分割成多项任务。那么,什么是任务?
如果你在公司逛一圈,并且想象一下:当办公室里的人用IT应用程序收发信息时,有红色光环从头顶冒出来,那你就会发现,这些光环每次出现的时间很短。它们就好比任务。大多数任务的持续时间都很短,一般是几分钟甚至更少,而两项任务之间的间隔时间,则比我们花在单项任务上面的时间要长。即便是像银行柜员这样的工作,也依然如此。尽管会有很多人在排队等候服务,但银行柜员使用IT程序的时间却很短,剩下的时间基本都用来点钞、等候客户填表或签字,以及等某位客户离开并接待下一位客户。下面所列的这些事情,可以视为任务:

  • 为顾客办理酒店入住手续。
  • 从ATM取钱。
  • 对交付情况进行记录。
  • 为警方出警安排车辆。
  • 提交订单。

现在笔者要更准确地解释一下任务这个词的定义。首先要澄清的是:在做业务建模的时候,很少有人像笔者这样,用任务(task)一词来表达某种精确的含义。我之所以搬出来任务这个说法,是觉得它与活动(activity)、用例(use case)、事务(transaction)或动作(action)等词相比,含义更加单纯。如果业务流程分析师要表达与任务一词相同的意思,那他们会采用“某人、某地、某时”的格式来解说。然而笔者觉得把地点(place)与其他两项因素并立,会显得有些奇怪,因为同一个人在同一时刻,只能出现在一个地点,不是吗?因此,笔者觉得应该把这个因素换成设备(device),这样我们就可以区分某人在某一时刻操作软件时,到底是用计算机操作的,还是用手机操作的。我们还可以说得再严谨一些:由于Web浏览器能够在同一时刻连接多个应用程序,因此可以考虑把设备因素改称为设备/分页(device/tab)。这样,“某人、某地、某时”就变成“某人、某时、某设备/某分页”,现在应该不会太奇怪了吧?于是,笔者把这个概念称作任务。
但为了给任务下一个更加正规的定义,我们还必须讨论原子性(atomicity)。对业务操作进行建模的时候,必须确定一种最底层的工作单元。这种工作单元必须是原子的,也就是说,该单元要么彻底完工,要么根本就没开工,而不会出现模棱两可的状态。原子性并不意味着本单元只能产生一项结果。一个工作单元可以有多种执行结果,但这些结果必须可以定义,也就是说,我们必须能够把这些结果全都罗列出来,并且要能够针对每一种结果做出精确的定义。这些结果之中,可能包含着对数据库所做的更新。综上所述,我们可以把任务一词更好地定义为:
某人于某时所完成的原子工作单元。
任务是具备原子性的,这意味着如果它在没有给出结果之前就失败了,那么我们必须还原该任务的所有效果,使其看上去好像从来没有执行过一样。同一项任务之所以可能产生不同的结果,通常是因为用户可能会做出不同的决策,然而做情境设计的人,还应该考虑到下面两种状况:
IT应用程序发生故障(例如,服务器断电)。
用户在任务尚未完工时就将其停止了(例如,用户要去吃午饭、要急着回家)。
为了应对上述两种状况,情境设计师可以把已有的更新保存在数据库中,而不是把所有的工作全都复原。如果决定要这么做,那就得定义两项任务,一项任务描述的是X已经启动并且有可能已经做完,而另一项任务描述的则是X已经彻底完工。之所以要将二者分开,是因为X有可能是在启动很久之后,才最终完工的。
你或许觉得任务的原子性与数据库事务的原子性,在概念上有些相似。大家可能知道,数据库事务不仅具备原子性(atomicity),而且还具备一致性(consistency)、隔离性(isolation)以及持久性(durability),这四项特征合起来称为ACID。那么,除了A之外,C、I、D这三项特征,在任务之中是否有所体现呢?它们确实是有所体现的,只不过体现得不像数据库事务那么突出罢了,本书第8章还会讲到这个问题。接下来你可能会问,既然这四项特征都有所体现,那么可不可以把任务与数据库事务等价起来呢?这恐怕不行,因为任务通常还涉及用户与IT应用程序之间来回传递消息的问题,所以我们一般不能直接用数据库的事务处理功能来实现它。但确实有一些任务完全依赖于数据库的事务处理功能,例如,对数据库进行更新的任务,就需要通过一个或多个数据库事务来实现。
为了更好地理解上面这个意思,你可以这样想:业务是以任务为步骤而推进的。
有些读者可能会怀疑:“为什么不把它叫做用例,而要说成任务呢?”用例确实也可以用来描述任务,但麻烦的是,用例这个词,还可以用来指代其他很多事情。第3章会详细讨论这个问题。
还有一些读者可能会问:“任务难道不是业务流程之中的活动吗?”(也就是说,他们认为任务应该像业务流程图之中的活动一样,表示成方框。)笔者觉得,一项活动可以拆解成多个任务。例如,在路上挖洞,可以视为一项活动,该活动之中可以有两个任务,一个任务发生在活动开始的时候,此时领队者命令团队开始挖掘,另一个任务出现在活动结束的时候,此时团队已经完成了挖掘。本书第5章会讨论这个话题。
以前的人在寻找新的技术词汇时,会从拉丁语和古希腊语里面取材。笔者在想,IT界是不是也应该这么做。
2.2.2 用户组
用户界面设计者所要知道的另外一种信息,是用户的分组情况。用户组(user group)是对用户所做的分类,如销售人员、仓库经理、安全人员等。需要注意的是,同一名员工可能会属于多个用户组,例如,某人可以同时属于销售人员、销售经理、雇员与经理这四个组。(作为销售人员,他要提交订单,作为销售经理,他要查看销售报告,作为雇员,他要提交报销单,作为经理,他要进行人事评审。)不同的用户组对应用程序有着不同的访问权,某一个用户组的成员所能看到的数据,可能与其他用户组有所区别,而且其成员所应完成的任务,也与其他用户组有所不同(尽管这些任务之间可能有某种重叠)。用户界面的设计者需要决定:是给每个用户组提供不同的界面,还是给所有的用户组都提供同一套界面,并根据当前用户所在的组,对该界面进行定制。
笔者之所以说用户组而不说角色或用户角色,是因为角色(role)这个词,可能会使某些人一下子就想到实现层面,而且我也不愿意用actor(行动者)这个词,因为用户并不是行动者。
2.2.3 数据表
业务型的应用程序,其主要目标通常是存储数据以供稍后使用。如果对数据没有概念,那就不太可能把应用程序描述出来。银行业会有记入贷方账户这个说法,那么什么是账户呢?账户就是一种数据。做生意的时候,我们要谈到订单处理,那么什么是订单呢?它也是一种数据。我们描述IT业务程序的时候,经常用名词来指代某种数据,因此,在对应用程序进行业务层面的描述时,我们所谈论的基本上就是该程序要对数据执行哪些任务。正因为如此,所以我们才要在做情境设计的时候,对数据有所了解。但同时,我们又不想在情境设计之中掺入太多与数据库模式有关的细节,因为在思考情境设计的时候,我们可能还不确定自己到底需要多少个数据库。
在做情境设计的时候,笔者用数据表(data table)来指代一组数据对象(data object),这种数据对象,用来存放与账户、产品或客户有关的数据。数据对象的结构此时还没有确定下来,我们只是知道应用程序会用到这份数据,于是,就先给它起个名字,并指出创建、读取、更新或删除该数据的那些任务,仅此而已。只有当我们为了给任务制定规则,而必须使用数据的某个属性时,我们才会给表格中的数据对象定义这个属性。等到以后定义数据库模式时,我们不仅要给数据表指定某些属性,而且可能还要把情境设计阶段之中的数据表,分割成很多个数据库表格。
2.2.4 任务之间的消息
任务之间除了会共享数据,还有可能传递消息。
笔者发现,在情境设计阶段,很少有人去指定任务之间的消息传递情况,因为这通常是实现层面的问题。在实现阶段,我们可能会通过网络来调用某项服务(也就是某段应用程序代码),而这种实现细节,不需要出现在功能描述之中(情境设计也是一种功能描述)。
还有一个原因在于:如果某任务需要向其他任务传递数据,那么更好的设计方案,应该是把这份数据放到数据表里面。假如用消息去发送数据,那就需要针对数据的提供者和消费者,分别去制定相关的任务。而且我们通常还发现,同一份数据可能有多个消费者要使用,因此,还是把它放在数据表里面比较好。这样做使得消费者能够以一种与提供者不同的顺序来读取这些数据。
实际工作中所遇到的消息发送或消息接收,基本上都是为了和情境设计之外的其他应用程序传递消息。然而有的时候,也可以考虑在同一个程序内部传递消息,例如,我们可以给某个任务发送一条警示消息,以便告诉其用户,系统之中发生了一件重要的事情。
请注意:某些任务可能完全是由输入的消息来驱动的,这些用来处理消息的任务,可能并没有相应的用户。批处理任务也是如此,有些任务会在每天、每晚、每周、每月或每年的固定时间执行,如银行账户产生利息,就属于一种批次任务。
2.2.5 任务之间的依赖关系
任务这种形式,能够很好地把程序所要做的事情指定出来,但它们并不能完全孤立地运作。为了对情境设计的完备性和一致性进行分析,我们需要把握住其中的各项任务,而要想把握住这些任务,则必须理解它们之间的依赖关系。
在用任务来实现业务流程中的活动时,我们可能就会遇到任务之间的依赖关系问题。流程,谈的是多项活动之间怎样协作,换句话说,流程会产生结果。之所以要对流程进行分析,就是为了理解这种结果是如何产生的。例如,为了报销费用,某人会提出报销申请,这算是一项活动,然后,会有人来审批这个申请,这算是另外一项活动,此外,还会有一个自动运行的活动,该活动有可能每个月会支付一次报销的费用。这个例子之中的三项活动,是按照简单的先后顺序来执行的,整个流程的输出结果,就是对报销费用的支付。如果经理认为某笔费用应该由别的组来报销,那么他会把报销申请转给另外一位经理去审批。在这种情况下,整个流程就不再像原来那么简单了,因为它现在并不是由三个按照先后顺序发生的活动所组成的,若是另外那位经理反对报销,那么流程还会更加复杂。一般来说,如果一切照常,那么整个流程之中的各项活动,会按照简单的先后顺序来执行,但如果需要返回早前的活动以解决某些问题,那么这些活动就会形成一个复杂的网络。在绘制任务层面的视图时,应该把任务之间的数据分享及消息传递情况画出来,这通常有助于我们更好地理解该流程。
任务之间的依赖关系不仅仅是流程而引发的。如果需要分配资源(如要指定送货用的车辆),那么也需要指定一系列任务,以处理车辆的指派、递交、购买及维护等事宜,这些任务可以令车辆的状态变为可用或不可用。有很多任务都是因为要管理同一种资源,而产生了依赖关系。
在上面这两个例子中,各项任务因为流程或资源的分配而发生了依赖,这种任务之间的依赖,通常可以转化为对数据表的依赖。例如,可以通过表示订单的那个数据对象,来得知该订单在处理流程之中的进度;也可以通过表示货车的那个数据对象,来得知该车辆当前所处的状态。于是,这就促使我们思考一个问题:怎样才能确保数据库所描述的状态,与该资源的实际状态相符?为了回答此问题,我们必须要考虑与资源发生交互的人员,以及交互的地点和时机,同时还要想一想,如果资源的真实状态与数据库所记录的状态不符,那么会发生什么现象。
有些数据并不是用来管理流程或资源的,这些数据本身自成一体,而且会在多项任务之间共用。例如,与产品有关的数据,就会在下单、制造、存储、销售、营销以及计费等多个任务之间使用。
2.2.6 把所有元素统合起来
在一家规模中等的企业里面,可能有上百种不同的任务需要执行,因此,我们应该对其分组。笔者把这种分组称为共同目标群(common purpose group)。我们当然希望某个目标群内的任务,尽可能不要与其他目标群内的任务之间发生依赖关系,但实际上,还是有可能出现这样的情况。本书第6章会讨论这个问题。
业务功能是由下列5个方面来描述的:

  • 任务。
  • 用户组。
  • 数据表。
  • 任务之间的消息。
  • 任务之间的依赖。

其中的前三项元素,画在了图2-4之中。
图中最上面那一行,画的是用户组。(请记住,同一个人有可能属于多个用户组。)
中间那一行画的是各项任务,这些任务都带有描述文本。我们会在第6章详细讲解任务。笔者并没有把消息发送情况绘制出来,如果任务之间要发送消息,用一个箭头来表示就可以了。
最下面那一行画的是数据表,不是数据库。
如果有必要,我们应该用单独的图表来绘制依赖关系,例如,绘制同一个业务流程中的各项任务之间所形成的依赖关系。这些依赖关系,都应该用文档记录下来,以便我们理解对设计进行修改所引发的后果,此外,我们在分析情境设计的时候,也会用到这些信息。笔者喜欢把每种依赖关系都至少绘制在一张图表里面,因为我要根据这些图表来进行审阅。


<a href=https://yqfile.alicdn.com/1c7ac2b33246eb18558d8ae8bb43afa59029b343.png" >

此外,我们还可以用表格来记录依赖关系,这种表格的各列与各行,写有相应的任务名称,如果两项任务之间有依赖关系,那我们就在行列交汇处的单元格里打勾,若能用字母来标出这条依赖关系的性质,那就更好了。此外,任务与数据表的依赖关系,以及任务与用户组的依赖关系,同样可以用表格来表示。表格便于查询,但对于评审来说,则不太方便。用图来进行评审,会更加便捷一些。
请注意,我们通过流程图等图表,在任务之间所找寻到的绝大多数依赖关系,最后都可以化为任务与数据之间的依赖,或是化为任务之间所传递的消息。因此,对于实现者来说,这些属于可以知道的信息,而不是必须知道的信息。
你可能觉得把这些任务确定下来,是一件很简单的事情,而且你可能认为业务经理应该已经把这件事做好了。没错,有些情况下,任务确实是显而易见的,而且有些任务简单到根本没必要画图表示。但是,在另外一些情况下,任务则没有那么简单。例如,即便是像图2-4这样看上去相当直观的图,也依然会引发一些问题。例如:
  • 拣货与打包是合起来算作一项任务,还是分开算作两项任务?
  • 拣货员如果发现产品缺货,那么应该怎么办?我们还需要一项任务,使得应用程序能够把这一情况回报给客户。
  • 如果未能完成投递,那应该怎么办?

早前我们也说过,如果流程之中发生了错误,那么情况就会变得复杂起来。
2.2.7 对情境设计做分析
我们可以就情境设计方案提出下列问题:

  • 对于每张数据表来说,有没有哪些任务会在表格中创建数据?有没有哪些任务会使用其中的数据?有没有哪些任务会删除其中的数据?
  • 如果某份数据用于追踪现实世界中的实体(例如,某份数据是用来表示顾客的),那么该数据准确吗?若是现实发生了变化(例如,客户修改了名称或地址),那么会怎样?如果数据不准确,会不会带来什么问题?
    每项任务是否都拥有完成其工作所需的信息?
  • 任务与数据是否能很好地支持业务流程?例如,在处理订单的过程中,有一条规则:发票是针对投递给客户的产品而开具的,不是针对客户所下订单之中的产品而开具的。我们在做分析的时候,要看看这条规则是否得到了遵守。
  • IT应用程序若发生故障,会对业务流程造成什么影响?
  • 用户是否承担了过多的数据收集工作?
  • 如果有人看到这些数据,那么会不会产生安全方面(甚至是法律方面)的影响?

从这些问题里面,我们可以发现,情境设计是可以进行分析的,这进而意味着,我们可以通过这种分析,来为工程化的设计提供支持。这种分析并不是单纯地进行计算,它更多地是对数据流与依赖关系进行研究。即便只做简单的分析,也依然可以帮你避免犯一些代价很高的错误。
有些公司并没有对情境设计之类的方案做分析,但它们似乎运作得还不错,你应该见过这种公司吧?既然如此,那笔者为什么还要强调分析的重要性呢?实际上,就我自身的经历来看,几乎没有哪个公司在研发情境模型的时候会做通透的分析。这样它们为了实现某些业务功能,就会把情境设计做成许多散布在模糊海洋之中的小岛,并且要艰难地维护其一致性,于是,公司只能靠手工的流程与猜测,来把这些小岛粘连起来。正因为如此,所以:

  • 我们不得不给同一个公司反复发送同一份数据。
  • 两位乘客会买到写有同一个座位号的机票。
  • 某些公司会把已经停产的产品卖给你。
  • 某个公共事业公司会把邻家的账单一直往我女儿家寄,直到明白这个错误之后才停止。

早前我们说过,有计划的设计与工程化的设计相比,其中一项缺陷就是设计者会因为怕失败而陷入过度设计的境地,这对于IT应用程序来说也是如此。由于应用程序没办法保证数据库里的信息一定准确,因此它必须再次检查数据,或是强迫用户必须再输入一遍。此外,由于应用程序并不知道有谁会需要数据,因此它会把数据发给每一个人。在大多数情况下,这并不会造成人身伤害,顶多就是效率低一些罢了,可我们最好还是不要做出这样的设计来。

相关文章