6章 需求 之 系统用例规约

那许多简单情节,那许多复杂表情

《岁月》;词:沈庆,曲:沈庆,唱:沈庆;1995

 

6.1 【需求步骤2-3】书写系统用例规约

用例图表达了用例的目标,但是对于完整的需求来说,这是远远不够的。用例的背后封装了不同级别的相关需求,我们需要通过书写用例规约把这些需求表达出来。用例规约就是以用例方式组织的需求规约。用例的各项内容用类图展示如下:

6-1 用例所封装的需求

6-1中的内容就是系统的各种需求,可以以图形、文本表示,也可以保存在数据库。目前UML并未包含这些内容的表示法,常见的做法是用Word等文本处理器来书写用例规约,不过扁平文本形式的缺点是难以高效建立、修改和维护用例各项内容之间的关系。现在已经有厂商提供专门用于编写用例规约的工具,例如Case CompleteVisual Use Case……,越来越多的UML建模工具(如EAVisual Paradigm for UML)也开始提供编写用例规约的功能,使得需求人员能够以“立体”的方式来书写和保存用例规约,并以文本、图形、表格等各种视图查看或输出,如图6-2

6-2 制作用例规约的工具

6-1的各项内容中,执行者和用例在用例图已经存在,照搬到用例规约中就可以。剩下的内容,用例图上是没有的,需要我们添加上去。我们逐个看看其他各项内容的要点。

6.1.1 前置条件和后置条件

用例通过前置条件(precondition)、后置条件(postcondition)以契约的形式表达需求。用例相当于系统的一个承诺:在满足前置条件时开始,按照里面的路径步骤走,系统就能到达后置条件。

前置条件:用例开始前,系统需要满足的约束。

后置条件:用例成功结束后,系统需要满足的约束。

后置条件不再像有的方法一样分为最小后置和成功后置。用例怎样才算成功,只写出最像的那个答案。这样就避免掉入“从实现角度看这样可以那样也可以”的陷阱。

前置条件、后置条件必须是系统能检测的。

6-3 系统必须能检测前置、后置条件

6-3中“录入保单”用例的前置条件是错误的。业务代表是否已经把保单交给内勤,系统无法检测,不能作为前置条件;同样,“收银”用例的后置条件也是不对的。顾客是否已经带着货物离开商店,系统也无法检测,不能作为后置条件。

前置条件必须是用例开始前系统能检测到的。

6-4 前置条件必须是用例开始前系统能检测到的

储户开始取款的交互前,系统不知道储户是谁,要取多少钱,所以“储户账户里有足够的金额”这个条件是无法检测的。

前置后置条件是约束,不是动作。

例如,“系统记录鉴定结果”是一个动作,不是条件。条件应该是“系统已记录鉴定结果”。

前置后置条件要有系统的味道。

“系统正常运行”、“网络连接正常”等放之四海而皆准的约束,和所研究系统没有特定关系,不能作为前置后置条件,否则又将是一大堆正确而无用的废话。

登录可以作为前置条件吗

一些用例规约会有这样的前置条件:××已经登录。这样做是否合适?下面花一些篇幅来讨论。

以购物网站为研究对象,登录不是用例。这一点在第5章已经阐述过了。如何处理登录?在过去的不少书和文章里可以看到如图6-5的做法:

6-5 登录的第一种处理,错误

会员登录以后可以下单,也可以查看以往订单,还可以退货……,所以图6-5下单查看以往订单画成登录的扩展。这是错的。并不是先做A然后做BB就成了A的扩展。例如,张三先吃饭,然后可能看电视,也可能上厕所,也可能散步。如果把看电视、上厕所、散步看作吃饭的扩展,意思就成了“张三可能会以上厕所的方式吃饭”或 “上厕所是张三达到吃饭目标的一条路径”。

第二种做法如图6-6,把登录变成被其他用例包含(Include)的被包含用例(Included Use Case)。这样做是正确的。登录用例本来不存在,后来在写用例规约的时候,发现下单查看以往订单等用例里都有以下步骤集合:

1. 会员提交身份信息

2. 系统验证身份信息

3. 系统保存会员登录信息

4. 系统反馈会员定制界面

为了节省书写用例规约的工作量,考虑把这些形成一个小目标的步骤集合(不是单个步骤)分离出来,作为一个被包含用例单独编写规约。这个用例只被其他用例包含,不由主执行者指向。被包含用例的这个特点和类的私有操作很相似。

6-6 登录的第二种处理,较正确

按照图6-6的做法,下单用例规约的步骤集合里,应该有表示包含登录用例的步骤集合:会员【登录】(“登录”二字加了粗括号表示这是一个被包含用例,它的步骤和约束在另外的地方描述,不喜欢括号可以用加下划线等其他方法以示区分)。有些人觉得这样的话,好些用例里会出现会员【登录】,看起来有些碍眼,就想能不能把它提到前置条件里,那就得到了第三种:把登录作为一个用例,会员已经登录作为其他用例的前置条件,如图6-7。这样用例的步骤看起来更清爽,但是严格来说这也是不对的,登录不是购物网站的用例。

6-7 登录的第三种处理,错误

可能有的人会觉得第三种处理更好,理由是从最终实现上看,会员登录以后可以下单,可以查看以往订单,不用再重新登录,看起来是不是第三种更合理?其实还是第二种更合理。第5章说过,考虑复用时,已经陷入了设计的思维。能够在多个用例中复用登录的状态,这是设计人员的本事,他甚至还可以做到10个用例的界面都从一个模板生成,但不能因此就把10个用例合并成一个。

认为第三种更好的另一个理由也和“复用”有关:当几个执行者在使用某些用例时都会有登录的步骤集合,把登录单独分离出来,可以抽象出一个用户执行者,指向登录,如图6-8

6-8 想通过泛化执行者复用用例,错误

这个看起来正确,实际上也是不对的。不同的涉众利益会带来不同的需求。这样做,潜意识里就有着一种追求“需求复用”的思想,会诱导需求人员对不同用例之间的微妙差别视而不见,这对于做需求来说是危险的。

会员登录需要验证码,货管员登录时不需要。系统反馈给会员的是未完成的订单,反馈给货管员的则是最近货品的动态。会员登录可能要求反馈速度很快,而且允许百万会员同时在线,货管员没有那么严格。这些需求差异不能视而不见。

更合理的做法如图6-9,分成几个不同的被包含用例。

6-9 分成不同的被包含用例,较正确

被包含用例(以及扩展用例)严格来说不能算用例,应该有更好的名字,例如“交互片段”,否则名称中带的”用例“二字容易误导开发人员从实现的角度定义用例,而不是从对外提供价值的角度。

6.1.2 涉众利益

前置条件是起点,后置条件是终点,中间的路该怎么走?这就要谈到用例规约里最重要也最容易被忽略的部分——涉众利益,即:某类人担心什么,希望什么。只有目标,没有涉众利益,很难得到正确的需求。

假设我需要1000元现金去买东西,我可以拉开家里的抽屉,如果里面有超过1000元的现金,我就从中拿1000元。如果抽屉里没有现金或者现金不够,我就拿上银行卡,到楼下取款机去取。问题来了:同样的目标,为什么家里的抽屉拉开就可以拿,而楼下的取款机却找我要卡要密码?

6-10 目标一样,抽屉和取款机的交互却大不相同

背后的原因就是:虽然目标相同,但涉众利益不同。家里的抽屉,只涉及到我和家人的利益,如果我和家人和睦相处,拉开抽屉就可以拿(反之,如果我和家人的利益冲突得非常厉害,那么可能需要买一种长得很像取款机的抽屉才符合我家的需要),对于银行取款机来说,就不是这样了。储户在取款机取款时,涉及的涉众利益如下:

储户希望操作方便;希望24小时服务;担心权益受损。

银行负责人希望安全;希望节约运营成本。

正是在这些涉众利益的交锋之下,目前我们日常生活中所看到的取款机的用例片断大概如下:

基本路径

1. 储户提交账户号码

2. 系统验证账户号码合法

3. 系统提示输入密码

4. 储户输入密码

5. 系统验证密码合法、正确

6. 系统提示输入取款金额

7. 储户输入取款金额

8. 系统验证取款金额合法

9. 系统记录取款信息,更新账户余额

……

业务规则

5. 密码为6位数字

8. 取款金额应为100元的倍数;取款金额应少于账户余额;单次取款金额不超过3000元;当日取款金额不超过20000

设计约束

1. 通过磁条卡或芯片卡提交账户号码

我们来看看涉众利益的交锋如何影响了需求。步骤1有设计约束通过磁条卡或芯片卡提交账户号码,这是为了照顾储户“方便”的涉众利益。

既然为了储户方便,还验密码干什么?银行不是口口声声说储户是上帝吗?为什么不在储户提交账户号码后,把钱箱弹出来让储户随便取?这是为了照顾银行“安全”的利益。

既然设密码是为了安全,密码长度怎么只要6位呢?何不设10位或更长的密码?这又是“安全”和“方便”交锋后的妥协。可以想像,如果有一天,“取款机黑客”魔高一丈,6位密码很容易攻破,这条规则可能就会变成密码为8位数字

系统记录取款信息,更新账户余额。这是储户看不见摸不着的,为什么要写出来?因为要是系统不做这件事,银行就吃亏了。

业务规则取款金额应为100元的倍数……。如果能有12元的取款机,储户会非常高兴(没有零钱坐公交车?到取款机那里取去!),但银行不高兴――成本太高了。

业务规则单次取款金额不超过3000元;当日取款金额不超过20000。这主要是维护银行降低运营成本的利益,当然,银行的解释会是为了保护储户的利益,防止被冒领等等。

认识到需求由涉众利益的平衡和冲突决定,可以帮助我们单刀直入需求的核心,也使我们的需求过程因充满了“人”的味道而变得乐趣横生。扩展开来看,我们为什么在现在的公司工作,为什么选择现在的配偶,甚至午餐吃什么,都是权衡了各种涉众利益的结果。

如何寻找涉众

如何定位用例的涉众?可以这样思考:如果系统的这个用例做得不好,谁会遭殃?我常问的一个问题是:如果执行者“喝醉”了,正在做某个用例,谁看到这个场面会担心自己的直接利益受到侵害(“喝醉”加了引号是因为执行者有可能是非人系统)?如果感觉这样的寻找思路有点漫无目的,我们可以先从这些地方找起:

人类执行者

执行者如果是人类,当然是用例的涉众。执行者如果不是人类,没有利益主张,就不是涉众。例如图6-11仓管员是人类,所以是涉众,而ERP系统不是人类,不是涉众。

6-11 非人类执行者不是涉众

上游

执行者使用系统做某个用例,需要一些资源,这些资源的提供者很可能是涉众。例如图6-12

6-12 考虑上游涉众

保单由业务代表提供给内勤。如果内勤喝醉了酒乱录,信息错得一塌糊涂,业务代表的利益就被损害了。

下游

执行者使用系统做某个用例,产生的后果会影响到别人。受影响的这些人也是涉众。还是图6-12录入保单的例子,如果系统做得不好,没有检测内勤录保单时是否填了必填项就放了过去,后面负责审核的经理工作量增加了。

还有图6-11中,ERP系统虽然不是涉众,但所研究的仓储管理系统的行为(例如不停向ERP系统发垃圾数据包)会影响到ERP系统背后的维护人员,使他们的工作量增加。所以,ERP系统维护人员也是下游的涉众。

6-13 考虑下游涉众

信息的主人

用例会用到一些信息,这些信息可能会涉及到某些人,这些人也许不知道这个系统的存在,但系统的好坏涉及到他们的利益。例如图6-12录入保单的用例,保单的信息涉及到了被保人、投保人、受益人,如果信息出错或泄漏,这些涉众就会遭殃。信息的主人有的时候“远在天边”,在寻找涉众时比较容易被忽略。

6-14 下游和信息的主人

说到这里,也许您已经看出来,业务建模对于识别涉众是非常有帮助的。如果我们在需求之前有业务建模工作流,会更了解一件事情的前因后果,大多数涉众都能够从业务序列图中看出来。如图6-15

6-15 业务建模可以帮助寻找涉众

大多数“变来变去”的需求,其实一开始就存在,只不过之前没有捕获而已。之所以没有捕获,原因多半是某类涉众的利益一开始没有得到尊重,到了后面才发现。如果平时注意观察和积累涉众利益,结合之前讲解的业务建模技能,这些假的需求变更会大大减少。

面对假的需求变更,开发团队明知是假却说是真,以便获得更多话语权,这没问题,如果自己也以为是真的需求变更,问题就大了。

给涉众排位

必须承认,系统不可能照顾到所有涉众的所有利益,只能照顾一部分,所以,对涉众的排位至关重要。涉众排位是否正确,直接影响了需求的内容。开发人员容易犯的错误是只盯住了“用户”,花在前排涉众身上的时间不够。

如何排位,并没有一定的准则。在研究一个餐饮管理系统时,餐厅服务员的排位可能很低,但是这名服务员下班以后玩游戏,针对这款游戏而言,她的排位很高。

开发团队领导和开发人员的“涉众利益”不用写出来。根据第2章所说的智子法,系统是投币得来的,做需求时没有开发团队。这样做有助于抵制开发人员不自觉地从自身角度定义系统需求的诱惑。从卖的角度看问题就知道了,“开发公司老板希望低成本开发”、开发人员希望能学到新的技能以便跳槽涨薪水”这种诉求能在市场上作为好卖的理由存在吗?

亲兄弟,明算帐

描述涉众利益时,要把不同涉众关注的不同利益体现出来,而不是写成一模一样。家里两夫妻对同一件事情都还有不同的立场,更不用说一个组织里面形形色色的各种涉众了。

司机开车进厂装化肥,工作人员通过系统操纵地磅给车称重。针对这件事情,不同的涉众可谓是“各怀鬼胎”:

化肥公司老板――担心公司内部人员贪污;

地磅操作员――希望操作简便;担心承担责任;担心系统坏掉;

仓管人员――担心称不准导致无谓的返工装包;

买主――担心称得轻了导致给少了化肥;

司机――担心等侯时间太长;

虽然这些利益有的时候不能白纸黑字写出来,但至少要心知肚明,不能一团和气了事。列出涉众利益后,在照顾前排涉众利益的同时,也要争取兼顾和平衡其他涉众的利益。

某制造厂,产品在成品之前要经过车间每个工位的加工和处理。每个工位针对产品做完自己的工作后,都需要把一些工作信息记下来。厂领导为了减少缺陷,想搞一个生产管理系统,当需求调研人员访谈一些车间操作工时,这些操作工却很抵触,“搞什么电脑,像现在用手写多省事”。涉众排位,厂领导坐在第一排,系统是一定要搞的,但操作工的利益怎么办呢?如果不管不顾地推行,强令不掌握电脑操作者下岗(大棒政策),或者举行电脑操作大奖赛,学得好的有奖(胡萝卜政策),这不是需求工程师所为。能不能在考虑厂领导“规范”的利益的同时,考虑操作工“像手写一样方便”的利益呢?办法还是有的,例如将需要输入的各种信息变成条码,操作工只需要扫一下条码就可以,这样就比手写还要方便了。

严格来说,涉众利益不是契约,不属于需求规约的内容。但放在用例规约里比放在其他地方有好处,因为不同涉众针对不同用例,利益不同。

6.1.3 基本路径

观众已经一排排坐好,接下来就要演戏了。我们需要写出能够平衡各方涉众利益的路径、步骤和补充约束。

用例有一条基本路径,若干条扩展路径。首先要写的是基本路径。基本路径指能代表用例核心价值的路径。

大街摆着一台取款机,发生在它身上的场景有很多:

1)张三来了,插卡,输密码,输金额,顺顺利利取到钱,高兴地走了;

2)李四来了,插卡,输密码,密码错,再输,再错,再输,卡被吞掉了;

3)王五来了,插卡,输密码,输金额,今天取得太多不能取了……

只有场景(1)是银行在大街上摆放一台取款机的初衷。让这样的场景出现得越多越好,是所有开发人员努力的目标。把基本路径单独分离出来先写,目的是凸现用例的核心价值。

有些人不理解为什么要这样做。为什么不干脆画一张流程图(流程图又冒出来了)把各种情况列在一起呢?人性的弱点之一是容易忘记自己的初衷,走着走着,在某个分支上投入过多的精力。

书写路径步骤的时候需要注意的一些要点如下。这些要点有重叠的地方,如果违反了其中一个要点,很可能也会违反另外的要点。

1)按照交互四步曲书写。

执行者和系统按照回合交互,回合数不定,直到达成目的。每个回合的步骤分为四类:请求、验证、改变、回应,如图6-16所示。

6-16 交互四步曲

这四类步骤中,除了请求是必须的,在有的回合中,其他三类步骤可以缺少其中一部分。

6-17展示了一个例子。可以看到,第一个回合缺少验证和改变,第二个回合有四类步骤都有。

6-17 回合制的交互示例

缺少回应的例子往往出现在时间作为主执行者,只有一个回合,还不需要和其他辅执行者交互的用例中,例如:

当到达时间周期时,

系统根据当前各因子值计算并保存评分。

2)使用主动语句理清责任。

把动作的责任人放在主语的位置,用Cockburn的话说就是“球在哪里”[Cockburn 2001]。比较下面两句话:

伊布从瓦伦西亚处得到传球,舒梅切尔扑救伊布的射门……

瓦伦西亚传球,伊布射门,舒梅切尔扑救……

虽然上面一句比较文艺,但下面一句把责任理得更清晰。用例步骤也是如此:

系统从会员处获取用户名和密码(错)

会员提交用户名和密码(对)

用户名和密码被验证(错)

系统验证用户名和密码(对)

责任分清楚:会员要是不提交,不要怪系统没有动静;会员要是提交了,系统不动弹,那就要怪系统了。

做到规规矩矩说话,把责任理清楚,其实也不容易。经常有人会写

会员保存订单

会员在哪里保存,存在自己的肚子里?应该是:

会员提交订单信息

系统保存订单

类似的还有:

会员查询商品

会员在自己肚子里面查?应该是:

会员提交查询条件

系统查询商品

系统反馈查询结果

3)主语只能是主执行者或系统

写需求,就是要把系统当作一个黑箱,描述它对外提供的功能和性能。系统如何构造,不属于需求描述的范围,除非是涉众强加的设计约束。所以,步骤里不能出现“执行者请求前端系统做某事,前端系统请求后端系统做某事”、“执行者请求客户端做某事,客户端请求服务器做某事”、“执行者请求A子系统做某事,A子系统请求B子系统做某事”,就算这个系统最终的组成是分解成很多个部分,分布在全球一百多个国家运行,需求里也只有两个字:系统。前文已经说过,系统边界是责任边界,而非物理边界。如果害怕“哎呀,这样会不会丢了东西”,那丢的不是这些东西,而是背后的质量需求。

6-18 需求把系统看作黑箱

可能会有人问如果我要做的就只是客户端,那怎么办?,这时所研究的系统就是你所说的客户端,需求规约里也不会有客户端的字样出现。

4)使用核心域术语

路径步骤是功能需求,应该使用核心域的术语来描述,也就是说,要说“人话”。

以一个零件采购系统为研究对象,比较以下两句话,哪一句是“人话”,哪一句是“鸟语”?

1)系统建立连接,打开连接,执行SQL语句,从“零件”表查询…

2)系统根据查询条件搜索零件

您一眼就能看出来,第一句是“鸟语”,第二句是“人话”。关键在于:为什么说第一句是“鸟语”?可能有的人说,因为第一句涉及到了技术,所以是“鸟语”。这个解释是有问题的。第2章我们说到了,要从开发人员使用的术语中删去“用户”二字,现在我们还要删去“技术”二字。

不少开发人员说到“技术”的时候,含义就是“我懂的或感兴趣的那点东西”,不懂且不感兴趣的就称为“业务”,甚至“忽悠”。例如,程序员认为“Java编码是技术,需求人员做的是业务”;需求人员则认为“业务建模、需求也有很多技能,我做的当然是技术,我们的客户——医院的医生做的才是业务”;医院的医生更是嗤之以鼻“老子一个月拿的红包比你一年薪水都多,还说我做的不是技术?”。其实大家做的都是“技术”,只是领域不同而已。所以,应该用“核心域”、“非核心域”来代替“业务”、“技术”。对此,本书第8章会深入讲解。

13的一种姿态是,谦虚地说“哎呀,不好意思我是做技术的,这个不太懂耶!”

如果待开发系统是一个关系数据库的脚本工具,“系统建立连接,打开连接,执行SQL语句”就是正确的功能需求,因为核心域是关系数据库领域,涉众是数据库开发人员,对他们来说,这是吃饭用的家伙,是“人话”,不是“鸟语”。这时,SQL就成了“业务”。

如果仍然是开发零件采购系统,不过老大强制要求,一定要这样实现,那么“系统建立连接,打开连接,执行SQL语句”也是需求,但不能写在步骤里,只能写在用例规约的“设计约束”部分。

5)不要涉及交互设计的细节

这个要点其实是上一个要点的延伸。很多人写需求的时候,会把界面细节带进来,例如:

会员从下拉框中选择类别

会员在文本框中输入查询条件

会员点击“确定”按钮

……

这些界面细节很可能不是需求,只是开发人员选择的解决方案——设计,应该把它们删掉,然后问“为什么”,背后隐藏的才是涉众在意的、真正的需求,也许是质量需求中的可用性需求操作次数不超过5次”,也许是质量需求中的性能需求“反馈速度应该在3秒以内”,也许两者兼有。

如果前排涉众明确要求一定要用下拉框,那么下拉框也是需求,但是依然不能写会员从下拉框中选择类别,必须要分成两条需求:

会员选择类别(这是步骤)

通过下拉框来实现(这是补充约束)

这两条需求的稳定性是不一样的。用例的需求组织方式就是把稳定和不稳定的需求分开,如图6-19,从用例到路径、步骤、约束,稳定性越来越低。平时遇到的大部分“需求变更”发生在补充约束级别,例如加个字段(字段列表变了)、调整计费规则(业务规则变了),越往上越稳定。

6-19 把稳定和不稳定的需求分开

前面说到“建立连接,打开连接,执行SQL语句”不是零件销售系统的需求,可能读者比较好理解,毕竟这是系统“里面”的,看不见摸不着,但是步骤里出现界面细节的时候,有的人就觉得好像可以接受,毕竟是看得见摸得着的。不过,需求判断的标准不是看得见摸得着(盲人怎么办),而是涉众是否在意。

界面组件和数据库组件是平等的,都是系统设计的一部分。藏在人体内部的心脏是人的设计,露在外面的眼睛也同样是设计。“人有眼睛”不是需求,需求是“人能看”。“人能看”就一定需要单独分出“眼睛”这样一个器官吗?未必,如果基因变异出一种新人类,没有眼睛耳朵鼻子,只有头上一个黑窟窿来接收各种声光信号,传到内部芯片处理,没准这样的新人类更适合在这个社会上生存。另外,没有血液循环系统和神经系统的帮忙,光有眼睛这个输入设备,也是无法让大脑感知到外部视觉信息的。

这里就引出需求的判断标准——需求是“不这样不行”,而不是“这样行”。

需求人员画了一张界面方案,拿去问涉众,界面这样做可以吗?涉众说,可以,甚至在上面还签字确认。这个界面方案是需求吗?一款非常受欢迎的游戏,它的源代码是需求吗?

以上两个问题的回答都是否。因为需求人员问的问题都是“这样行吗”,相当于:

需求人员:"界面这样可以吗?"

涉众:(我又不会做界面,问我可不可以我当然说可以了)可以。

需求人员:"代码这样写可以吗?"

涉众:(我又不会写代码,问我可不可以我当然说可以了)可以。

当“不这样不行”的时候,界面方案和代码才成为需求。例如,问涉众票据格式的界面方案“不这样行吗”,涉众明确“不这样不行,这是政府的规定,必须这样,你们不要自己乱发挥啊”,这个时候,这个界面方案就是需求(设计约束)。如果涉众说“这段代码是我小舅子写的,一定要这样,否则不给钱”,这时候,代码就成了需求(同样是设计约束)。

对于需求的一个误解是以为“写的细的就是好需求”。需求确实要细,但是很多时候需求人员写的“细”不是需求(问题)的细,而是设计(解决方案)的细。我看到过不少所谓“需求规约”,篇幅巨大,从数据库每个字段的设计到界面控件详细布局,甚至编码规范,都包含在其中。作者也很得意“我这份需求可谓是无二义了吧!”说到无二义,源代码就更无二义了,但源代码不是需求。

在需求里大量描述设计,相当于医生没有能力去定位患者得的什么病,干脆拍脑袋开药,然后把药的说明书抄一遍,以为这样就可以治好患者了。诊断能力不足,开的药不对症就不对症,说明书抄得再仔细也没用的。

大家可以尝试用“不这样行吗”这个问题去过滤一下以前写的“需求”,也许可以过滤出一大堆假的需求,然后问“为什么”,找出背后真正的需求。

“不要涉及交互设计的细节”不仅局限于界面的布局,还包括交互的细小设计。例如,在实现的时候,执行者输入某个字段时,系统会随着执行者输入每一个字符,不断检测输入是否合法,而不是等待输入完毕,提交后才检测。这些在步骤中不必写出来,应该把焦点放在输入、输出和处理上,验证规则集中写在业务规则里,把交互的目的从交互的细节中分离出来。交互的细节背后隐含的是质量需求,应该放在补充约束的段落表述,而且,交互设计和其他设计一样,它的实现是有一定套路的,和领域无关。

关于用例的交互该怎么写,是一个比较头痛的问题。即使不涉及交互设计细节的问题,也免不了混进交互设计的成分,例如,为什么分两个回合交互而不是一个回合?实际上涉众更希望一个回合就能达到用例的目标。所以在书写交互步骤的时候,也同样要问不这样行吗,尽可能减少不必要的交互步骤。

例如之前提到的取款机的取款用例的步骤:

1. 储户提交账户号码

2. 系统验证账户号码合法

3. 系统提示输入密码

4. 储户输入密码

5. 系统验证密码合法、正确

6. 系统提示输入取款金额

7. 储户输入取款金额

……

可以思考,如果不分多个回合输入和验证,会不会一定损害涉众的利益?如果不一定,那么可以合并为一个回合:

1. 储户提交账户号码、密码和取款金额

2. 系统验证账户号码合法

3. 系统验证密码合法、正确

……

比较极端的做法就是干脆把用例的路径步骤“一剪梅”,只保留前置后置条件、输入输出、涉众利益和补充约束,中间的路径步骤都属于设计。

6)不要写系统不能负责的事情

系统无法检测、不能负责的事情,如果写在用例规约中,会造成误解,让读者以为只要用上了这个系统,这些事情就会发生。这样就模糊了系统的契约,也抹杀了进一步改进的可能。

例如以下规约片断:

……

4. 系统反馈应收总金额

5. 顾客付款

6. 收银员提交付款方式和金额

7. 系统计算找零金额

8. 系统反馈找零金额,打印收据

9. 收银员找零

……

顾客付款收银员找零是系统无法感知和承诺的,写在规约里,会让人认为用了本系统,顾客就会乖乖付款,收银员会乖乖找零——也许忘记收款和找零正是商场要解决的一个头痛问题。

这种错误,牢记四步曲即可避免,四步曲中所写的都是系统能感知的。

====以下内容暂略====