何伟潮的《软件方法》读书笔记(用其他工具把书里的图画了一遍)
以下是何伟潮的读书笔记,难得的是,他用其他工具把书中的图自己画了一遍。
1、建模
1.1、业务建模之愿景
重点1:通俗一点讲,一个东西的愿景就是:东西最应该卖个谁,对他有什么好处?
重点2:愿景是需求排序的主要依据。
重点3:老大、愿景、需求都是基于现状寻找最值得的改进。改进过后,又是新的现状了,还是基于现状寻找最值得的改进。进一步说也可以说,需求只有真假对错,没有变化。说需求有变化,那是从一个静止时间点来看的。
1.1.1、愿景
1.2、业务建模之业务用例图
有了愿景,我们知道老大对他所代表的组织的现状的某些指标不满意。接下来就可以研究组织,弄清楚到底是组织的哪些环节造成了这些指标比较差,这就是业务建模(Business modeling)的主要内容。
重点1:软件系统只是组织的一个零件。组织里面还有很多系统,其中最值钱的是千百年来一直在使用,现在依然是最复杂的系统——人脑系统。
重点2:开发团队发现需求“容易变化”。根源之一是需求的来路不正,没有把系统当作一个零件放在组织中来看,靠拍脑袋得出需求,导致得到的系统需求是错的。
1.2.1、业务角色
① 业务执行者
以某组织为研究对象,在组织之外和组织交互的其他组织(人群或机构)就是该组织的执行者。以一家商业银行为研究对象,观察在它边界之外和它打交道的人群或机构,可以看到储户来存钱,企业来贷款,人民银行要它作监督等等,这些就是该商业银行的执行者,如下图所示:
这里要注意的是,作为观察者的建模人员本身是一个人脑系统,所以在观察组织边界时,直觉上观察到的不是组织之间的交互,而是组织派出的系统之间的交互,但是一定要把它理解成组织间的交互,因为谈论业务执行者时,研究对象是组织,所以外部对应物——业务执行者也应该是组织。例如:以某国税局为研究对象,可以观察到企业财务人员到国税局报税,但业务执行者不是企业财务人员,而是企业。也许到后来,企业财务人员和国税系统交互,又或许再后来是企业系统与国税系统交互,从组织的抽象级别来看,都应该理解为企业和国税局这两个机构之间的交互,如下图所示:
② 业务工人
组织内的人称为业务工人,例如某商业银行里面的营业员。业务工人是可以被替换的人脑零件,它可能被其他业务工人替换,但更有可能被业务实体替换。
③ 业务实体
业务实体是组织中的非人智能系统,例如银行的ATM、点钞机、营业系统。
1.2.2、识别业务用例
重点1:业务用例指业务执行者希望通过和所研究组织交互获得的价值。业务用例是组织的价值,不会因为某个人脑系统或电脑系统的存在或消失而改变,好比如300年前的商业银行和当前的银行的业务用例是不变的,因为银行提供价值的本质没有改变。所以“这个系统的业务用例是什么”这样的说法是错误的。
重点2:用好用例,关键在于理解“价值”。价值是期望和承诺的平衡点、买卖的平衡点。例如以“医院”为研究对象,真正的用例是“患者→看病”,而不是“患者→挂号”,患者→挂号”可以是以“挂号室”为研究对象的业务用例(如下图)。所以做任何事情之前,要搞清楚“边界”,没有边界会很容易盲目“拍脑袋”做一些努力但没效果的事情。
1.2.2.1、识别业务用例思路
识别业务用例的思路有两条:
【从外到内】从业务执行者开始考虑,思考业务执行者和组织交互的目的(主要);
【从内到外】通过观察组织的内部活动,一直问为什么,向外推导出组织外部的某个业务执行者(补漏)。
1.2.2.1.1、识别业务用例常犯错误
错误1 :把业务工人的行为当做业务用例。
错误2:业务用例随待引入系统伸缩。
错误3:把害怕遗漏掉的扩展路径片段提升为业务用例。
错误4:管理型业务用例。
总结:错误的根源主要源于:建模人员分不清问题和问题的解决方案。
1.3、业务建模之业务序列图
1.3.1、描述业务流程的手段
本章节主要讨论的是业务建模中最繁重的工作——描述业务用例的实现,即业务流程,然后改进它,推导出待引入系统的用例。目前描述业务流程的可选择手段有文本、活动图和序列图,它们的主要区别如下(以财务部“员工→报销”用例的实现为样例):
● 文本
文本的缺点是不够生动,所以在描述业务流程时很少使用文本方式。不过,描述系统用例(即系统需求)的流程时,文本是常用的,因为此时更注重精确,而且还要表达业务规则、性能等目前尚未被UML标准覆盖的内容。
● 活动图
活动图的前身是流程图,应该是在建模人员中使用频率最高的图形,是随机械工程领域慢慢引入到计算机领域。不过,随着编程语言表达能力越来越强,针对简单的分支或循环逻辑画图在很多情况下已经变得没有必要。
● 序列图
序列图与活动图的比较如下:
1)活动图只关注人,序列图把人当作系统;
在上一章节中已经提到,现在的业务流程中已经有很多领域逻辑是封装在业务实体而不是业务工人中,如果忽略非人智能系统,很多重要信息就丢掉了。
2)活动图表示动作,序列图强迫思考动作背后的目的;
序列图可以更加清晰地表述业务工人或业务实体对外的责任,也就是用例的期望值。期望和承诺是用例和对象技术的关键思想,使用序列图来做业务建模,“对象协作以完成用例”的思想就可以统一地惯窃业务建模和系统建模的始终。
3)活动图“灵活”,序列图“不灵活”;
不少人认为活动图胜过序列图的地方是它灵活,但这灵活是一把双刃剑。活动图很灵活,他的控制箭头可以指向任何地方,就像编码原始时代的“goto”语句,所以活动图很容易画。不过,“很容易画”的活动图也比较容易掩盖建模人员对业务流程认识不足或者业务流程本身存在缺陷的事实。序列图可通过alt、loop等结构化控制片段来描述业务流程,强迫建模人员用这种方式思考。
1.3.2、业务序列图要点
1.3.2.1、消息代表责任分配而不是数据流动
序列图中最重要的要点是消息的含义。A指向B的消息,代表“A请求B做某事”,或者“A调用B做某事的服务”,而“做某事”是B的一个责任。
1.3.2.2、抽象级别是系统之间的协作
业务建模的研究对象是组织,出现在业务序列图生命线上的对象,其最小颗粒是系统,包括人和非人系统,而系统之间最主要突出的是协作。所以“系统粒度”和“协作”是业务序列图的关键要点,如果记住了这两个关键点,就可以避免了对组织对象抽象的错误以及对协作理解的错误。
以上说的两种错误是把需求和分析的工作流的工作带入了业务建模。第一样例图提到的系统内部的组件,应该在分析和设计工作流中描述;第二样例图提到了交互步骤,应该在需求工作流中描述。除了以上两种抽象级别的错误,还有一种是:业务序列图的内容和业务用例图差不多,如下所示:
1.3.2.3、把时间看作特殊的业务实体
业务序列图中,我们把时间看作特殊的业务实体。把时间看作上帝造好挂在天上的一个大钟,向全世界各种系统发送时间消息,这样,就和后面需要工作流中映射系统用例的时间执行者一致了,同时也帮助理清什么情况下使用时间执行者的问题。
值得注意的一点是,时间和定时器不是一个概念,时间是“外系统”,定时器是其他系统用来和时间打交道的“边界类”。世界上只有一个时间系统,但有无数的定时器。如果建模人员在识别系统用例时说“执行者是定时器”,那就错了,执行者是时间。
1.3.2.4、为业务对象分配合适的责任
分配给业务对象的责任必须是该对象有能力承担的,这需要我们自身必须对理解要十分清晰,毕竟我们自己说话有时候的会含糊。例如“工作人员用Word写标书”这样的说法好像可以接受,但如果按照说话的文字不假思索地随便画,会很容易导致对象责任分配不准确。
1.3.3、现状业务序列图
业务序列图描述的是业务流程,建模需要通过在现状的业务序列图基础上找出改进的要点。如果要把现状序列图画出来,就必须让自己站在客观的角度“亲临现场”,“如实”地把所看到的记录下来,尽力描绘出真实的现状。但说起来非常简单,做到却极其困难。总结到这里,忽然让我想起了彼得·德鲁克。下面列出一些描述现状时经常犯的错误。
1)错误:把想象中的改进当成现状
很多时候造成这种错误,背后的原因很可能是根本没有深入到组织流程中去做观察和访谈,对现状没有认识,只好想像一个改进后的场景来应付。
2)错误:把“现状”误解为“纯手工”
有的建模人员以为人做的事情才是本质,所以他画的业务流程中,只有人,没有非人系统,完全忽略了在技术进步下慢慢可以替代人的这些“业务实体”。
3)错误:把“现状”误解为“本开发团队未参与之前”
开发团队很容易会误以为当他们开始参与组织流程完善而开发系统的时候当作“现状”,这就是典型的“技术思维”,很多时候在开发团队在参与组织流程完善前,组织已经经过了许多次“非系统级”的流程改进,这是站在组织角度去看问题的。
4)错误:把“现状”误解为“规范”
建模人员在建模业务流程时,照搬组织制定的规范,没有去观察实际工作中人们是如何做的,或者即使观察到了人们实际没有按照规范做,却依然按照规范建模。这样做,得到的业务流程是不真实的,毕竟上有政策,下有对策。
5)错误:“我是创新,没有现状”
互联网创业公司的建模人员很容易犯的这个错误,动不动就说“我做的是互联网创新,没有现状”,但他们已经忘记了历史上所有的创新都是站在前辈这些巨人的肩膀之上这个事实。
6)错误:“我做产品,没有现状”
非定制系统的开发团队进程拿这句话做接口。A公司的流程和B公司的流程有差异,中国的流程和外国的流程有差异,画谁的现状好的?问这个问题的时候,我想是开始开发团队忘记了“做需求时把产品当项目做”的道理,在第2章节中也提到过“谁比谁更像”的重点。
1.3.4、改进业务序列图
上面提到的现状业务序列图是对组织现状的客观描述,而改进业务序列图是通过信息化手段去思考对业务现状序列图的一些改进。通常,信息化给人类的工作和生活带来的改进有三种模式。
1.3.4.1、改进模式一:物流变成信息流
和信息的光电运输比起来,用其他手段运输的物的流转速度就显得太慢了,而且运输成本会随着距离的增加而明显增加。如果同类物的不同实例之间可以相互取代,那么可以提炼物中包含的部分或全部有价值的信息,在需要发生物流的地方,改为通过软件系统交互信息,需要物的时候再将信息变成物,这样就可以大大增加流转速度和降低流转成本。
1.3.4.2、改进模式二:改善信息流转
软件系统越来越多,而各个软件系统之间沟通不畅,导致一个人为了达到某个目的可能需要和多个软件系统打交道,如果把各软件系统之间的协调工作改为一个软件系统来完成,人只需要和单个软件系统打交道,信息的流转就改进了。
1.3.4.3、改进模式三:封装领域逻辑
在业务流程中,有很多步骤是由人脑来判断和计算的,领域逻辑封装在人脑中。相对于计算机,人脑(业务人才)存在成本高,状态不稳定、会徇私舞弊等问题。如果能够提炼人脑中封装的领域逻辑,改为封装到软件系统中,用软件系统代替人脑,业务流程就得到了改进。换句话说,领域逻辑的封装是对系统“内在”价值的提升,相对于前两个改进模式有更高的要求和更大的困难。
1.3.4.4、改进思考方式:阿布思考法
在软件开发团队中,当有人提出新的想法时,经常会被马上否定“太难了,做不了”,最终得到一个平庸的、毫无竞争力的系统。学会像阿布(俄罗斯大富豪罗曼·阿布拉莫维奇)一样思考,有助于克服普通人因资源受限而不敢展开想象的思维障碍。阿布思考法分两步:
1)假设有充足的资源去解决问题,得到一个完美的方案;
2)用手上现有的资源去山寨这个完美的方案。
其实,阿布思考法的核心思想就是,不要闭门造车,要“接地气”的行动起来,主动去观察,或主动寻找有用的信息去分析和调研,不要被各种局限被迫让步。
2、需求
2.1、需求之系统用例图
在“建模”阶段我们研究和思考的对象是组织,从组织的整体性客观地去发现组织如何可以通过信息化手段去优化流程。有了客观的整体性分析和改进认知,接下来的“需求”阶段需要深入到系统层面去思考了。按正常逻辑,每一步都有“承上启下”的作用,本章节所研究的系统用例就是通过上一步业务序列图中所映射出来的。
执行者和用例的概念在业务建模的学习中已经出现过,现在要研究的执行者和用例与业务建模时研究的执行者和用例相比,不同之处是研究对象,之前研究的是组织,现在研究的是系统。
2.1.1、系统执行者要点
系统执行者的定义:在所研究系统外,与该系统发生功能性交互的其他系统。
2.1.1.1、系统是能独立对外提供服务的整体
封装了自身的数据和行为,能独立对外提供服务的东西才能称为系统。不了解这点,建模人员很容易把“添加一些功能”当作“研发新系统”。
2.1.1.2、系统边界是责任的边界
系统执行者不是所研究系统的一部分,是该系统边界外的另一个系统。这里的系统边界不是物理的边界,而是责任的边界。
2.1.1.3、系统执行者和系统有交互
外系统必须和系统有交互,否则不能算是系统的执行者。如一名旅客来到火车站售票窗口,告诉售票员目的地和车次,售票员使用售票系统帮助旅客购买火车票,这个场景中,和火车票系统交互的是售票员,他是售票系统的执行者。
如果火车售票系统现在已经提供了旅客自行购票的接口,例如互联网购票、售票机等,这种情况下,旅客也是售票系统的执行者。不过“售票员→售票”和“旅客→购票”是两个不同的用例。
2.1.1.4、交互是功能性交互
上面说的交互还引出一个问题:假设售票员使用鼠标和售票系统交互,按道理,比起销售员,鼠标里售票系统更近,为什么不把鼠标作为售票系统的执行者呢?还有,假设售票系统运行在Windows操作系统之上,那么Windows是不是售票系统的执行者?其实吧,辨别这些问题的要点就是:执行者和系统发生的交互是系统的功能需求。鼠标和操作系统跟售票系统的交互都不是售票系统的核心域概念。售票员和售票系统之间的交互才是,所以售票员才是售票系统的执行者。
2.1.1.5、系统执行者可以是人或非人系统
系统执行者可以是一个人脑系统,也可以是一个非人智能系统,甚至是一个特别的系统——时间。在软件业的早期,一个系统的执行者往往全部都是人。随着时间的推移,系统的执行者中非人执行者所占的比例越来越多。用例的优势在于“执行者”和“涉众”的概念,把演员和观众分开。演员(执行者)在台上表演,观众(涉众)在台下看,演员表演什么是由观众的口味决定的,演员可以不是人,但观众肯定是人。演员如果是人类,那么在观众席上也会有一个位置,不过在第几排就不知道了(权重等级)。用例使用“执行者”和“涉众”代替了原来的“用户”是一个非常大的突破,建模人员如果过多地关注“用户”,混淆了真正真正重要的前排“涉众”的需求,把操作人员当前重要的调研对象(非关键人员),那么花在重要的前排涉众(关键人)身上的时间可能就不够了。越来越多的系统执行者不是人类,也就是说没有“用户”。
2.1.1、识别系统执行者
2.1.2.1、从业务序列图映射系统执行者
如果没有做业务建模,识别系统执行者只能靠头脑风暴。例如:什么人会使用系统来工作?什么人负责维护系统?系统需要和哪些其他智能系统交互?有没有定时引发的事件?等等问题。有了业务建模,可以直接从业务序列图映射即可。业务序列图上,和所研究系统有实线相连的对象映射为所研究系统的执行者。
2.1.3、系统用例要点
2.1.3.1、价值的买卖的平衡点
系统用例的定义:系统能够为执行者提供的、涉众可以接受的价值。和业务用例相比,研究对象从组织变成了系统,要理解好系统用例,重点依然是之前所强调的买卖平衡点、期望和承诺平衡点。
用例之前的许多需求方法学,把需求定义为思考系统“做什么”,用例把需求提升到思考系统“卖什么”的高度。这种思考是非常艰难的,因为它没有标准答案,只有最佳答案。要得到这个答案,不能靠拍脑袋,必须揣摩涉众。要得到合适的用例,需要有一颗善于体察他人的心。
2.1.3.2、价值不等于可以这样做
有些人会较真,还是以ATM为例子,有些人会因为“难道ATM放在那里我就不能登录一下就离开吗?我今晚下班就去ATM那里登录一下给你看,然后走人。”ATM确实能登录,但登录功能并非ATM的卖点,如果以一个“门禁系统”为研究对象,登录就可以作为它的用例。
还有一种情况,例如科员可以有A和B用例,科长因为比科员的权力大,所以就能拥有科员的用例。用例的执行者只是表明这个用例是为这一类执行者而做的。但不代表系统一定要有权限控制以防止其他的人或电脑系统使用该用例。即时系统确实需要有权限控制,而且角色的划分和执行者相近,也要把这两者分开,更不可以因为系统不设权限控制,所以把执行者的名字合并为“用户”。
有些书中会给出“最佳粒度原则”。例如:一个系统的用例最好控制在XXX个之内,一个用例的基本路径最好控制在X步到X步之间……这些是没有根据的。市场需要各种各样的系统,有功能众多的,也有功能单一的,也有交付复杂的,应该把屁股坐到涉众那边去,揣摩涉众的心里,实事求是地写下来。如果建模人员在粒度问题上激烈争吵以及纠缠不清,有可能已经犯了错误,最常犯的错误是把步骤当作用例。
2.1.3.3、增删改查用例的根源是从设计映射需求
有一些用例图,映入眼帘的用例是四个四个一组的,仔细一看,刚好对应看数据库的四种操作。相当于把数据库的各个表名加上新增、删除、修改、查询,就得到了用例的名字。有些建模人员确实也知道这个错误,但他们学乖了,干脆把每四个用例合并,改名叫“管理XX”或(“XX管理”),然后新增、删除、修改、查询等用例再扩展它,可惜依然是换汤不换药。
2.1.3.4、从设计映射需求错误二:“复用”用例
增删改查用例实际上就是从设计映射需求,导致“复用”用例的一种情况。在看看以下例子:
从不同的业务序列图分别映射得到系统有右边四个用例,但有的建模人员会动起心思:这些实现起来不都是针对“缺陷”表来“select X X X from缺陷表where X X X”吗,合并成一个用例“查询缺陷”多好!于是得到左边的结果。实际上,右边这四个用例面对的执行者不同,背后的涉众利益也有差别。
当然,如果真的像这位建模人员讲的,把“数据库”,买回去就好,想怎么折腾这信息都可以那不是更加简单。其实,用例是涉众愿意“购买”的、对系统的一种“用法”,只要涉众愿意“购买”,当然越多越好。讲到这里,就要来说一个需求的基本要点:需求不考虑“复用”,如果考虑“复用”,要警惕自己是不是已经转换到了设计视角来思考问题。
2.1.3.5、系统用例不存在层次问题
系统用例的研究对象就是某特定系统,不是组织,也不是系统内部的组件。如果存在“层次”上的疑惑,背后的原因是研究对象不知不觉改变了。
像医院信息系统的用例,有人会画成如下图所示,原因可能是前面没有画业务用例图和业务序列图,所以建模人员头脑里不知不觉把医院信息系统的价值和医院的价值混在一起了。
还有以下的防汛系统用例图,把系统的愿景当成了“高层”用例:
以下更为常见的错误,为系统的“模块”或“子系统”画用例图:
2.1.3.6、用例的命名是动宾结构
用例的命名是动宾结构,例如“取现金”。动词前面可以加状语,宾语前面可以加定语,把一句话的主语砍掉,剩下的可以用作用例的名字。
给用例起名时不要使用弱动词。用例之前的需求技术,可能是以“名词+动词”的形式命名系统的功能,例如“发票作废”,后来要改成用例的动宾结构了,有的建模人员就在前面加一个弱动词“进行”,就变成了“进行发票作废”,这个也是不合适的。
如果“名词+动词”已经成为行业中的一个术语,也未必要严格的动宾结构,例如“成果分析”是某行业的一个术语,也就不必硬要倒过来变成“分析成果”了。
2.1.4、识别系统用例
2.1.4.1、从业务序列图映射系统用例
其实,只要认真做好业务建模,从业务序列图上映射系统用例,得到的结果自然就会符合上面说的这些要点。
从业务序列图中,从外部指向所研究系统的消息,可以映射为该系统的用例。现在我们继续从“识别系统执行者”的用例中结合执行者和系统用例一起识别。
在以上业务序列图中,有一处消息是“外呼人员”指向“线索管理系统”的消息为“提供本人当天名单”,但在以上系统用例图中,用例名改为了“查看本人当天名单”。因为序列图上的消息代表“请求某系统做某事”,用例代表“用某系统来做某事”,一定要理解两种图的要点,所以有的地方需要调整。
在以上系统用例图中,有的箭头是从执行者指向用例,这样的执行者称为用例的主执行者,有的箭头是从用例指向执行者,这样的执行者称为用例的辅执行者。主执行者主动发起用例的交互,辅执行者在交互的过程中被动参与进来。
值得注意一下,辅执行者这个概念是被误用的比较多。最常见的错误是把信息的接收者或者将来可能使用信息的人当成辅执行者。另一种辅执行者的误用刚好相反,把信息的来源当作辅执行者。
以上错误的原因很多是因为前面没有画业务序列图,导致建模人员在画系统用例图的时候产生焦虑,总是希望在图上多放一些信息,以免自己忘记了。一般来说,辅执行者是非人智能系统的情况较多,人脑系统作为辅执行者的情况比较少,所以碰到辅执行者是人的时候,要多留心。
2.2、需求之系统用例规约
用例图表达了用例的目标,但是对于完整的需求来说,这是远远不够的。用例的背后封装了不同级别的相关需求,我们需要通过书写用例规约把这些需求表达出来。用例规约就是以用例为核心来组织需求内容的需求规约。用例规约的各项内容可以通过以下类图来展示:
2.2.1、前置条件和后置条件
用例通过前置条件(precondition)、后置条件(postcondition)以契约的形式表达需求。用例相当于系统的一个承诺:在满足前置条件时开始,按照里面的路径步骤走,系统就能达到后置条件。为了避免掉入“从实现角度看这样可以那样也可以”的陷阱,后置条件只需要写出最想要的那个状态即可。
● 前置条件:用例开始前,系统需要满足的约束。
● 后置条件:用例成功结束后,系统需要满足的约束。
2.2.1.1、前置条件、后置条件必须是系统能检测的
以上图为例,“录入保单”用例的前置条件是错误的。业务代表是否已经把保单交给内勤,系统无法检测,不能作为前置条件;同样,“收银”用例的后置条件也是不对的。顾客是否已经带着货物离开商店,系统也无法检测,不能作为后置条件。
2.2.1.2、前置条件必须是用例开始前系统能检测的
以上图所示,储户开始取现金的交互前,系统不知道储户是谁,要去多少钱,所以无法检测“储户账户里有足够的金额”这个条件。如果把前置条件设置为类似于“存在大于最低限额的现金”这样的背景条件作为前提条件是可以的。就算很长时间没人来ATM取现金,这个条件是否成立就摆在那里。
2.2.1.3、前置后置条件是状态,不是动作
例如,“经理→批假”的前置条件不能写“员工提交请假单”,因为是一个动作不是状态,应改为“存在待审批的请假单”。特别要注意的是,写成“员工已经提交请假单”很可能也是不对的,因为状态和导致达到某个状态的行为不是一一对应的,请假单未必是员工自己提交的,也可以组长负责帮本组人员请假,也可能是从另外的系统批量导入。
如果分不清状态和行为的区别,建模就会遇到很大的麻烦。后面的建模工作中,还会不断讨论状态和行为的问题。
2.2.1.4、前置后置条件要用核心域词汇描述
“系统正常运行”、“网络连接正常”等放之四海而皆准的约束,和所研究系统没有特定关系,不需要在前置条件中写出来,否则会得到一堆没有任何增值作用的废话。
后置条件也不能简单地把用例的名字加上“成功”二字变成“XXX成功”。例如“顾客→下单”的后置条件写成“顾客已经成功下单”,这不是废话吗?更合适的后置条件是“订单信息已保存”。
2.2.1.5、“已登录”不应作为前置条件
“已登录”是一个比较有争议的情况,以购物网站为研究对象,登录不是用例。这一点已经在前面的已经学习过,那如何处理登录?
1)画法一:把其他用例作为“登录”的扩展
会员登录后可以下单,也可以查看以往订单,还可以退货……所以上图这个方法把下单、查看以往订单画出登录的扩展。这是错的。并不是先做A然后做B或C,B和C就成了A的扩展。
2)画法二:把“登录”作为被包含用例
2.1.3.5、系统用例不存在层次问题
把“登录”变成被其他用例包含(Include)的被包含用例(Include Use Case)。这样做是正确的。登录用例本来不存在,后来在写用例规约的时候,发现“下单”、“查看以往订单”等用例都有以下步骤:
为了节省书写用例规约的工作量,考虑把这些形成一个小目标的步骤集合(不是单个步骤)分离出来,作为一个被包含用例单独编写规约。这个用例只被其他用例包含,不由主执行者指向。所以,如果按照这个做法的话,“下单”用例规约的步骤里,应该有表示包含“登录”用例的步骤集合:会员【登录】。这里的“登录”二字加了粗括号表示这是一个被包含用例。它的步骤和约束在另外的地方描述。当然,不喜欢用粗括号可以用下划线等其他方法以示区分。
3)画法三:其他用例以“已登录”作为前置条件
有些人觉得画法二会让好些用例会出现会员【登录】,看起来有些碍眼,就想能不能把它提到前置条件里,那就得到了画法三。把“登录”作为一个用例,“会员已经登录”作为其他用例的前置条件。这样用例的步骤看起来更清爽,但是严格来说这也是不对的,“登录”不能作为购物网站的用例。
以上章节学习过,如果在做需求时考虑复用,可能已经陷入了设计的思维。能够在多个用例中复用登录的状态,这是设计人员的本事,他甚至可以做到10个用例的界面都从一个模板生成,但不能因此就把这10个用例合并成一个。
2.2.2、涉众利益
前提条件是起点,后置条件是终点,中间的路该怎么走?这就要由涉众决定了。也就是我们需要对关键人按重要程度排序(从前排到后排)去考虑他们的利益,根据这些利益去梳理正确的需求。以银行ATM为例子,储户在ATM取现金的时,涉及的涉众利益如如下:
● 储户:希望方便;担心权益受损。
● 银行负责人:希望安全;希望节约运营成本。
正是这些涉众利益的交锋之下,目前我们日常生活中所看到的ATM的用例片段如下:
从步骤1有设计约束“通过磁条卡或芯片卡提交账户号码”看,这是为了照顾储户“方便”的利益。在银行角度,虽然储户是上帝,为了储户更加方便,不用密码更方便的。但从银行角度要考虑安全问题,不可能不设置密码,但为什么只设置6位而不是8位或者更多呢?这又是“安全”和“方便”交锋后的妥协……
2.2.2.1、涉众的来源
1)涉众来源一:人类执行者
用例的执行者如果是人类,当然是用例的涉众。执行者如果不是人类,就不是涉众,因为它没有利益主张。
上图保险系统的“内勤→录入保单”用例中,内勤是人类,是涉众,而OA系统不是人类,不是涉众。
2)涉众来源二:上游
执行者要使用系统做某个用例,可能会需要一些资源,这些资源的提供者可能就是用例的涉众。还是以“内勤→录入保单”为例,保单由业务人员代表提供给内勤。如果内勤喝醉了酒乱录,信息错得一塌糊涂,业务代表的利益就被损害了。所以,考虑到上游之后,“内勤→录入保单”用例的涉众有内勤和业务代表了。
3)涉众来源三:下游
执行者使用系统做某个用例,产生的后果会影响到其他人。这些受影响的人也是涉众。还是以“内勤→录入保单”为例,如果系统做得不好,没有检测内勤录保单时是否填了必填项就放了过去,后面负责审核的经理工作量增加了。还有,OA系统虽然不是该用例的涉众,但假如保险系统不停地向OA系统发送垃圾数据包,导致OA瘫痪,那么OA系统维护人员的工作量就增加了。所以,OA系统维护人员也是下游的涉众。考虑下游之后,“内勤→录入保单”用例的涉众如下图所示:
4)涉众来源四:信息的主人
用例会用到一些信息,这些信息会涉及某些人,虽然这些人也许并不知道这个系统的存在,但他们是用例的涉众。还是以“内勤→录入保单”为例,保单的信息涉及被保人,投保人和受益人,如果信息出错或泄露,这些人就会遭殃,所以他们是涉众。因为这类涉众可能和系统没什么接口,比较容易被忽略,所以要特别需要注意。
其实,前面的业务建模对识别涉众起到了非常大的帮助,如果做需求前做了业务建模,会更加了解一件事情的前因后果,大多数涉众都能够从业务序列图中看出来。如下图所示:
2.2.2.2、寻找涉众利益
查理·芒格说过:说服别人要诉诸利益,而非诉诸理性。所以要学会思考涉众的利益点是一门非常大的学问。寻找涉众利益时,要“亲兄弟,明算账”,把不同涉众各自关注的利益体现出来,而不是写成一模一样的。家里两夫妻对同一件事情都还有不同立场,更不用说一个组织里面形形色色的涉众了。例如,司机开车进厂装化肥,工作人员通过地磅系统操纵地磅给车称重。针对这件事,不同的涉众可谓是“各怀鬼胎”:
● 化肥公司老板——担心公司内部人员贪污;
● 地磅操作员——希望操作简便;担心承担责任;担心系统坏掉影响工作量;
● 仓管人员——担心称不准导致无谓的返工装包;
● 买主——担心进去时称得轻了,出来时称得重了,导致给少了化肥;
● 司机——担心等候时间太长导致每天拉货次数减少;
即使有些利益有时不方便白纸黑字写出来共享,但至少建模人员要心知肚明,不能一团和气了事。建模人员要仔细观察和揣摩涉众的痛苦,才能找到真正的涉众利益,否则写出来的“涉众利益”往往很苍白。例如以下例子:
● 护士——担心出错
这都是正确的无用废话,谁都担心出错,但为什么还是出错?仔细调研过之后写出来就生动多了:
● 护士——担心自己的药理学知识记错,对药物名称相近的药物计算错剂量,导致给药错误;
2.2.2.3、善于积累涉众利益
需求是不断变化的,我想这都是共识了,新系统肯定在功能或性能上和旧系统有所不同,否则还做什么新系统呢。但是,背后的涉众利益要稳定得多。看看之前ATM的例子出现的涉众利益:
储户——希望方便;担心权益受损;
银行负责人——希望安全;希望节约运营成本;
其实这些涉众利益不止适用于ATM,也适用于清朝的钱庄柜台、现在的银行柜台、网上银行和手机银行。换句话说,越本质越稳定。
2.2.3、基本路径
一个用例会有多个场景,其中有一个场景描述了最成功的情况,执行者和系统的交互非常顺利,一路绿灯直抵用例的后置条件。这个场景称为基本路径。用例把基本路径分离出来,目的是凸显用例的核心价值。还是以ATM为例,发生在ATM上的场景有很多:
1)张三来了,插卡,输入密码,输入金额,顺顺利利取到钱,高兴地走了;
2)李四来了,插卡,输密码,密码错,在输,再错,再输,卡被吞掉了;
3)王五来了,插卡,输密码,输金额,今天取得太多不能取了……
以上三个场景,只有场景(1)是银行在大街上摆放一台ATM的初衷。虽然场景(2)和(3)是难以避免,但场景(1)出现得越多越好,这是涉众对ATM的期望。
书写路径步骤的时候需要注意以下一些要点。这些要点有重叠的地方,如果违反了其中一个要点,很可能会违反另外的要点。
2.2.3.1、按照交互四步曲书写
执行者和系统按回合交互,直到达成目的。需要的回合数是不定的,可能一个回合足够,也可能需要多个回合。一个回合中的步骤分为四类:请求、验证、改变、回应。如下图所示:
在一个回合中,请求是必须的,同时还需要其他三类步骤中的至少一类。看看以下例子,可以看到,第一个回合只需要请求和响应,第二个回合则四类步骤都有。
当时间作为主执行者而且不需要和其他辅执行者交互的用例中,可能会出现不需要回应的情况,而且只有一个回合,如下所示:
在书写步骤时要注意以下一些形式上的问题:
1)对于时间为主执行者的用例,回合中的请求步骤不写“时间告知时间周期到了”,而是写“当到达时间周期时”。
2)验证步骤不写“是否”。例如以上例子中,第4步写“系统验证注册信息充分”,不写“系统验证注册信息是否充分”,目的是要表达“充分”是基本路径期望的验证结果。
3)系统和辅执行者之间的交互可以看作是一种回应步骤,写成“系统请求辅助执行者做某事”,例如“系统请求邮件列表系统群发邮件”。
2.2.3.2、只写系统能感知和承诺的内容
看看以下例子:
……
4、系统反馈应收总金额
5、顾客付款
6、收银员提交付款方式和金额
7、系统计算找零金额
8、系统反馈找零金额,打印收据
9、收银员找零
……
顾客付款和收银员找零是系统无法感知和承诺的。如果写在步骤里,会让人产生误解:只要用了本系统,顾客就会乖乖付款,收银员会乖乖找零——也许顾客忘记付款和收银员忘记找零正式商场要解决的一个头痛问题。
2.2.3.3、使用主动语句理清责任
把动作的责任人放在主语的位置,看看以下两句话:
1)伊布从瓦伦西亚处得到传球,舒梅切尔扑救伊布的射门。
2)瓦伦西亚传球,伊布射门,舒梅切尔扑救。
虽然上面一句比较文艺,但下面一句把责任理得更清晰。用例步骤也是如此:
系统从会员处获得用户名和密码(错)
会员提交用户名和密码(对)
用户名和密码被验证(错)
系统验证用户名和密码(对)
会员要是不提交,就不要怪系统没有动静;会员要是提交了,系统不动弹,那就要怪系统了。做到规规矩矩说话,把责任理清楚,其实不容易。再列举一些常见的“胡说八道”,如下所示:
2.2.3.4、主语只能是主执行者或系统
写需求,就是要把系统当作一个黑箱,描述它对外提供的功能以及功能附带的质量需求。系统如何构造,不属于需求描述的范围,除非是涉众强加的设计约束。所以步骤里不能出现“执行者请求前端系统做某事,前端系统请求后端系统做某事”“执行者请求客户端做某事,客户端请求服务端做某事”“执行者请求A子系统做某事,A子系统请求B子系统做某事”,就算这个系统最终的组成是分解成很多个部分,分布在一百多个国家运行,需求里也只有两个字:系统。前面已经学习过了,系统边界是责任边界,而非物理边界,如下所示:
2.2.3.5、使用核心域术语描述
路径步骤应该使用核心域的术语来描述,也就是说,要说“人话”。以下以一个零件采购系统为研究对象,比较以下两句话,哪一句是“人话”,哪一句是“鸟语”?
1)系统建立连接,打开连接,执行SQL语句,从“零件”表查询……
2)系统根据查询条件搜索零件
其实,一眼就能看出,第一句是“鸟语”,第二句是“人话”了。不同职能多少会有主观意识,做Java开发的觉得自己做的才是技术,需求属于业务。但需求人员却觉得自己做的也是技术,他们所研究的客户才是业务。但客户觉得自己做的才是技术……,这咋看起来有点像一个鄙视链。其实,大家做的都是“技术”,这是领域不同而已。应该用“核心域”和“非核心域”来代替“业务”和“技术”。
如果所研究系统是一个关系数据库的脚本工具,核心域是关系数据库领域,上面提到的“系统建立连接,打开连接,执行SQL语句”就成了合适的需求。
2.2.3.6、不要涉及界面细节
很多人写需求的时候,会把界面的细节带进来,例如:
● 会员从下拉框中选择类别
● 会员从文本框中输入查询条件
● 会员单击“确定”按钮
这些界面细节很可能不是需求,更多是设计方案,背后可能隐藏更多的真正需求,也许是可用性需求“操作次数不超过5次”。但毕竟我们面对的客户各种各样的喜好都有,可能有些前排涉众明确要求“一定要用下拉框”,那么“下拉框”也是需求,但依然不能写“会员从下拉框框中选择类别”。因为这里涉及两类需求,她们的稳定性和变化趋势不同,应该分开描述:
● 会员选择类别(这是步骤)
● 通过下拉框来实现(这是设计约束)
用例的需求组织方式是分层的,从用例的路径、步骤、约束,稳定性会越来越低,如下所示:
用例规约的需求层级
把需求分层级了,稳定和不稳定的需求就分开了,更有利于了解事情的核心本质。平时遇到的大部分“需求变更”发生在补充约束级别,例如输入会员信息时加个微信字段(字段列表变了),调整结账时的打折规则(业务规则变了)。级别越高的需求,内容越稳定。
很多时候做需求会把看得见和需求混为一谈,真正的需求不见得是显而易见的。需求判断的标准不是涉众是否看得见,而是涉众是否在意。第一章已经学习过,需求和设计不是一一对应的,而是多对多的。
2.2.3.7、不要涉及交互细节
在步骤中,除了避免描述页面细节,还要避免描述交互细节。例如有人会这样写:
● 会员每输入账户名称的一个字符
● 系统在界面中验证当前输入信息合法
写的人有他的道理:系统不是等待提交后才验证输入信息是否合法,而是随时验证立即反馈,这样使用户体验更好。其实,这只是交互设计的一些技能。忍不住要在需求规约里描述界面和交互的细节,背后的原因和忍不住要思考内部代码如何实现的原因是一样的,都是对自己的设计技能没有信心,害怕“现在想到了如果不忘记记下来以后就忘记了”。这些都是人性的弱点。
用例的步骤应该把焦点放在系统必须接收什么输入、系统必须输出什么信息以及系统必须做什么处理这三个重点上,加上字段列表、业务规则、可用性需求等约束,足以表达各种需求。
关于用例的交互怎么写,是一个比较头疼的问题。即使不涉及交互设计细节的问题,也免不了混进交互设计的成分,例如,为什么要分两个回合而不是一个回合?实际上涉众更希望一个回合就能达到用例的目标。所以,建议观点是在用例规约中把路径步骤删掉,只保留输入输出、涉众利益和补充约束,交互的路径步骤由交互设计人员决定。
2.2.3.8、需求是“不这样不行”
许多需求人员之所以在需求岗位上,并不是因为他掌握了该掌握的需求技能,可能只是因为他工作年限足够长该换到需求岗位了——和许多年龄到了就上岗的夫妻和父母相似。这样的需求人员硬着头皮做需求时,最常用的一招就是托着脑袋想“这个东西是什么样子”,然后画一个界面原型拿去和涉众确认。一旦涉众说“差不多就这样吧”,就把这个界面原型作为需求交给分析设计人员。在这一点上,互联网公司的产品经理表现得尤为明显。如果侥幸成功,就拼命鼓吹“原型大法好”,因为他只会这个。
当需求人员问问题时都是“这样可以吗”,相当于:
● 需求人员:界面这样布局可以吗?
● 涉 众:(好用就行,我又不会做界面,问我可不可以我当然说可以了)可以。
● 需求人员:代码这样写可以吗?
● 涉 众:(好用就行,我又不会写代码,问我可不可以我当然说可以了)可以。
如果问的问题改为“不这样可以吗?”,像下面这样:
● 需求人员:界面不这样布局可以吗?
● 涉 众:不可以,这是政府的规定,你们不要自己乱发挥啊!
● 需求人员:代码不这样写可以吗?
● 涉 众:不可以,这段代码是我小舅子写的,一定要这样,否则不给钱。
这时,界面和代码就成为了需求,当然,只是补充约束级别的需求。说到这里,我们归纳出需求的判断标准:需求是“不这样不行”,而不是“这样也行”。
2.2.4、扩展路径
基本路径上的每个步骤都有可能发生很多意外,其实某些意外是系统要负责处理的,处理意外的路径就是扩展路径。因为一个步骤上出现的意外及其处理可能有多种,所以同一步骤上的扩展路径可能有多条。
扩展路径和步骤
对于扩展路径及其步骤的标号,本书采用的是Cockburn推荐的方法。扩展路径的标号方法是在扩展步骤的数字序号后面加上字符序号,例如2a表示步骤2的第a条扩展路径,2b表示步骤2的第b条扩展路径。扩展路径条件的最后加上冒号,接下来是该扩展路径的步骤,标号方法是在扩展路径编号后面加上数字序号,例如2a1。也就是说,步骤的编号以数字结尾,扩展路径编号以字母结尾。如果多重扩展,那就继续按此形式标注。还是以之前ATM“储户→取现金”用例为例。该用例规约加上扩展路径之后如下所示:
基本路径:
1. 储户提交账户号码
2. 系统验证账户号码合法
3. 系统提示输入密码
4. 储户输入密码
5. 系统验证密码合法、正确
6. 系统提示输入取现金额
7. 储户输入取现金额
8. 系统验证取现金额合法
9. 系统记录取现信息,更新账户余额
……
2a. 账户号码不合法:
2a1.系统反馈账户号码不合法
2a2.返回1
5a. 密码不合法:
5a1.返回3
5b. 密码合法但不正确:
5b1.系统验证当日取款累计输错密码次数不超过3次
5b1a.当日取款累计输错密码次数超过3次:
5b1a1.系统关闭账户
5b1a2.用例结束
5b2.系统反馈密码不正确
5b3.返回3
8a. 取现金额不合法:
8a1.返回6
有一点需要注意,和辅执行者交互的步骤很有可能会出现扩展。例如:
4. 系统请求短信平台发布信息
……
扩展
……
4a. 短信平台无响应:
4a1.系统反馈短信平台无响应
……
但,如果系统不需要从外部系统那里得到任何结果,这个外系统就不是辅执行者,所以它出现故障会不会导致扩展的讨论是没有意义的。例如:
5. 系统向经理的电子邮箱通知有新的待审批申请
除了以上步骤之外,从其他步骤产生扩展路径一定要非常谨慎,否则容易让不属于需求的内容混进用例规约中。特别要注意下面几点。
1)能感知和要处理的意外才是扩展
2)设计技能不足导致的错误不是扩展
3)不引起交互行为变化的选择不是扩展
4)界面跳转不是扩展
2.2.5、补充约束
路径步骤里描述的需求是不完整的。例如:
用例名:发布讲座消息
……
1. 工作人员输入讲座信息,请求发布
2. 系统验证讲座信息充分
3. 系统生成发布内容
4. 系统请求短信平台发布消息
5. 系统保存讲座信息和发布情况
6. 系统反馈信息已经保存并发布
……
步骤1中的“讲座信息”包括哪些内容?需要添加字段列表。步骤2中“充分”指什么,需要添加业务规则。从步骤1到步骤6有没有速度上的要求?需要质量需求。
如果补充约束的内容只和单个用例相关,可以直接放在该用例的规约中;如果补充约束适用于多个用例,可以单独集中到另外的地方,从用例规约引用。
补充约束前面的编号不代表顺序,而是表示该约束绑定的步骤编号,如果某条补充约束不是针对某一步骤,而是针对多个步骤甚至整个用例,前面的编号可以是“*”,如下所示:
5. 发布情况=发布时间+工作人员
补充约束的类型可用类图表示:
用例的补充约束
2.2.5.1、字段列表
字段列表用来描述步骤里某个领域概念的细节。例如上面“发布讲座消息”用例的步骤中,步骤1、3、5都需要分别添加字段列表。
字段列表可以用自然语言表达,例如:
字段列表
1. 讲座信息包括:举办时间、地点、专家信息、主题、简介。专家信息包括:姓名、单位、头衔。
也可以用符号表达,例如:
字段列表
1. 讲座信息=举办时间+地点+专家+主题+简介
1. 专家=姓名+单位+头衔
表示的符号可以采用过去数据字典常用的符号。例如:“+”表示数据序列,“()”表示可选项,“{}”表示多个,“[|||]”表示可能的取值。例如:
注册信息=公司名+联系人+电话+{联系地址}
联系地=州+城市+街道+(邮编)
保存信息=注册信息+注册时间
客房状态=[空闲|已预定|占用|维修中]
很多时候,做需求会把设计的细节带上,例如“电话号码varchar(255)”或把数据模型图附上,这是不准确的。数据模型是设计,设计应该来源于需求,而非空想一个设计,然后把他当成需求。
2.2.5.2、业务规则
业务规则描述步骤中系统运算的一些规则,例如上面“发布讲座消息”用例的步骤2中的“充分”没有说清楚,需要添加业务规则,例如:
业务规则:
2. 必须有的项包括:时间、地点、专家、主题
其实,主要涉众能理解,行业上适用的任何方式(例如数学、物理公式)都可以用来表达业务规则。描述业务规则时要注意:业务规则不等于实现算法。因为业务规则也是一种需求,也是从涉众的角度看“不这样不行”的。例如,研究一款为盲人或残疾人而做的语音输入软件,用例规约有如下片段:
3. 系统将语音输入翻译为文字
业务规则
3. 采用XX识别算法
这样的业务规则可能是有问题的,如果前排是盲人或残疾人,他们是不懂什么叫“XX算法”,也不在意你是否用了这个算法,他们在意的需求是:“背景噪音强度为XX的情况下,识别率应该在XX以上”。当然也不排除前排涉众是有意推广某厂家的识别技术,那么“采用XX识别算法”也可以成为需求。
2.2.5.3、质量需求
系统满足功能需求,说明系统能把事情做正确。在做正确的基础上,系统还需要在做的过程中满足一些指标,这些指标就是质量需求,也被称为“非功能需求”。
1)可用性
可用性需求是对人类执行者和系统之间交互质量的度量。如果系统仅能正确达到用例目标,但交互太频繁,人类执行者是不喜欢用的。在表达可用性需求时,仅仅说“系统容易使用”是不行的。这是无法量化的目标,合适的可用性需求应该是可以度量的,例如:
可用性度量
2)性能
性能包括速度、容量、能力等,例如:
① 系统应在0.5秒之内拍摄超速车的照片(速度)
② 应允许1000个执行者同时使用此用例(容量)
③ 在标准工作负荷下,系统的CPU占用率应少于50%(能力)
在寻找质量需求时,性能类型的质量需求往往是最多的。
3)可靠性
可靠性表示系统的安全性和完整性,通常用平均无故障时间(MTBF,Mean Time Between Failures)和平均修复时间(MTTR, Mean Time To Repair)表示。可靠性需求往往不是针对单个用例,而是针对整个系统,可以在所有用例规约的最后,单独用小篇幅描述。
4)可支持性
可支持性表示系统升级和修复的能力。例如:
① 95%的紧急错误应能在30个工作时内修复
② 在修复故障时,未修复的相关缺陷平均数应小于0.5
③ 升级新版本时,应保存所有系统设置和个人设置
和可靠性一样,可支持性需求往往不是针对单个用例,而是针对整个系统,可以在所有用例规约的最后,单独用小篇幅描述。
以上介绍了质量需求的种类,很多时候质量需求不用可以去寻找,按照前面说过的“不这样行吗”的标准,把混入需求的设计删掉,然后问为什么,背后往往隐含的就是质量需求,如下所示:
质量需求
2.2.5.4、设计约束
设计约束是在实现系统时必须要遵守的一些约束,包括界面样式、报表格式、平台、语言等。
设计约束既不是功能需求,也不是质量需求。例如,“用Oracle数据库保存数据”,其实用DB2也可以满足同样的功能需求和质量需求,但必须要用Oracle,因为客户已经采购了许多Oracle数据库软件,如果不用,成本就会增加。
设计约束是需求的一种,也一样要从涉众的视角描述。在很多需求规约中,不少来自开发人员视角的设计伪装成设计约束,混进了需求的队伍。例如“系统应采用三层架构方式搭建”,涉众并不了解“三层”好在哪里,为什么不是四层、五层等,然后问“为什么”,背后的真正需求可能还是性能需求。
需求是问题,设计是解决方案,二者的稳定性不同。
2.3、需求启发
2.3.1、需求启发要点
需求人员要能够像猎人一样,用锐利的眼睛发现隐藏在丛林中的猎物,像侦探一样,用缜密的思维判断出伪装成好人的凶手。但需求人员会有许多的障碍:如
1)需求的一个启发障碍是知识的诅咒,意思是:一旦知道某个东西,就很难相像不知道它会是什么样子;
2)知识的诅咒在需求启发中体现为沟通的困难;
3)需求启发的另一个障碍是做和定义的不同;
但理解了以下两个要点,有助于克服需求启发中的障碍:
1)和涉众交流的形式应该采用视图,而不是模型;
2)和涉众交流的内容应该聚焦涉众利益,而不是需求;
2.3.2、需求启发手段
需求启发手段
2.3.3、需求人员的素质培养