UML软件工程组织

独孤木专栏:漫谈UML OOAD and RUP (下)
(2003.06.06)   来自:Java周刊  
**使用者或者是客户的信息人员,看不懂相关的文件**

开发项目到底会遇到什么样的客户?其实就像是跟网友见面差不多,还没有看到真人,你永远不知道哪个每天跟你聊天分享心事的超级美女,其实是一个中年男子。就算你运气好,以前已经跟这个使用者接触过,彼此混的很熟,还是有可能会发生变化。

如果以前的项目做得好,这个人有可能升官,所以他就不会做这个专案了;如果以前的项目做得不好,有可能这个人就被列入下次裁员的黑名单里,所以他也不会做这个项目。更不要提有些时候,你是跟一些从来都没有打过交道的人一起开始做一个新的项目。

既然我们在描述的对象是项目,大部分的项目,都是从需求分析开始。使用者便会提出他们的需求,系统分析师听到使用者的需求以后,就会开始把他所收集到的需求写成文件,接着会去跟使用者确认需求是否便是如此。

采用use case drivenOOA(object oriented analysis),你会请使用者确认的文件,当然就是use case

接着你会依据use case,开始进行OOD(object oriented design)。当你画好sequence diagram, class diagram,你可能会希望客户的信息人员,可以帮忙确认,这些文件所描述的系统,是否正确。

问题是,大部分的使用者,以及客户的信息人员,其实并没有足够的能力,来确认这些文件的正确性与完整性。因为你所提供的文件,他们看不懂。通常需要你的带领,才看得懂。当他们需要靠你解释才看得懂时,这时候通常会有一些问题随之产生。他们通常可以挑出专业领域上的错误,可是他们通常会忽略掉整个系统的完整性。因为他们会觉得,你所没有描述的东西,可能写在另外的文件中。所以如果你提供的文件有错,通常是你所提供的文件可能不完整,其实要到蛮后期的时候才会发现。这时候修改的成本就会变得非常高了。

为什么采用use case来描述一个系统,通常会发生遗漏呢?或许我们应该先看看use case是什么。

根据我的一知半解呢,use case就是尝试着用文字来描述系统与外界之间的交互作用。对于没有看过use case的人来说,我在此举一个例子来说明。书上最常看到的例子呢,就是一个人用提款机在领钱。虽然我没有写过类似的程序,我可以想象一下,这个use case应该包含的内容。

1.Brief Description

这个use case说明,怎么样透过提款机来领钱。

2.Flow of Events

这个use case,开始于客户把卡片插入提款机后,完成身分认证,并且已经选择要提款。

2.1 Basic Flow

1.
客户输入要领取的金额。

2.
系统检查客户的金额与次数,是否超过系统中所定义每次提领金额与提领次数的上限。

3.
系统从客户的存款余额文件中扣去存款金额的资料。并产生一笔提领纪录在客户的交易文件中。

4.
如果是跨行客户,系统应该产生一笔扣除手续费的资料到信息交换中心。并且更新本行对于清算中心的应收帐款--手续费资料。

5.
进入吐钞use case

2.2   Alternative Flows

2.2.1
超过每次允许的提领金额

1.
如果超过每次允许的金额,系统应显示错误讯息:『你不识字吗?   一次只能领两万!』。

2.
系统应该回到功能选择画面。

3.
回到功能选择use case

2.2.2 
超过提领次数

1.
如果超过提领次数,系统应显示错误讯息:『你这张卡片已经刷爆了!   赶快去补刷存折吧!』。

2.
系统应该回到功能选择画面。

3.
回到功能选择use case

2.2.3 
客户选择取消

1.
如果客户在输入金额时,没有按下确定,却是按下取消,系统应显示   错误讯息:『不要玩我!快滚吧!』。

2.
系统应该把卡片吐出来。

3.
回到吐卡片use case

3. Special Requirements



4.  Preconditions

客户要正确插入卡片,输入正确的密码,通过身分认证,提款机还有足够的钞票在里面。

5.  Postconditions

进入吐钞use case

6.  Extension Points



通常会被找到的遗漏:

1.
为什么没有检查金额是否正确?台湾的提款机,只能够输入100的倍数。
 
你要领512元是不行的。

2.
怎么没有显示要不要换百元钞?

3.
怎么没有检查,机器里面的钞票是否足够?有可能没有小面额的钞票啊。

通常不会被找到的遗漏:

1.
跟金资中心如何达成联机的问题。因为这可能被include到另一个use case里面去了。

2.
没有扣除机器的钞票余额档。

3.
吐钞口要开开关关测试是否可以正常吐钱。

4.
如果吐钞成功的话,要扣机器本身的余额档。

5.
如果成功的话,要把客户未登折次数加1

因为我没有写过ATM程序,只能随随便便想象可能会有的问题。

我想,用use case开发比较大的问题在于你其实有可能会遗漏掉一些系统该做的事情。在单一use case中,有可能你会有非常多的alternative flow。每个假设,都有可能不成立。所以你得要定义如果这个假设不成立的时候,系统要响应什么。问题在于一般的使用者,他们提出规则的时候,会把预期系统的反应写在旁边。例如,如果系统没钱,就显示没钱错误讯息。

问题是用了use case以后,很多这样的规则,因为你把系统的整个行为模式全部都展开出来,篇幅就会拉的非常长;如果你把共享的部分抽出来,放在includeuse case中,user又要交叉比对才可以看到对的东西。当你看到长篇大论的时候,眼睛看的久了,很容易就漏掉该写的东西。除非我先把所有的规则都写下来,整个if then else的决策树也画出来,不然哪记得你应该写25alternative flow而不是24个?而这里就会变成是user还要花时间去一个一个比对,他们的requirement是否都被use case cover到了。通常使用者会把这个工作交给SA来做,他们再来看结果。因为user通常都很忙,所以SA整理出来的结果他们通常也没有时间详细地walk through。所以该遗漏的东西还是会遗漏。

另外一个问题,则在于有些东西,是刚好介于use caseuse case之间。因此他会预期在use case A中发现的东西,他没看到,他就会觉得可能是写在use case B之中吧。当他去看use case B的时候,他还是没看到,这时候他不见得会记得,他还想看到什么。因为我们在review文件时,通常都只会看到这份文件描述的scenario对不对,比较少去想到底缺了什么。

所以有时候一少,就是少掉一整组use case。例如关于一些系统在运转时会用到的参数档,应该要有如何去维护这些参数的use case。这就常常被user忽略掉。这在采用传统结构化分析画DFD(数据流程图)的世界里,是不太可能发生的,因为每个data,都要描述它是怎么样去maintain,或是怎么样进入系统中。资料不是来自其它系统,就是来自使用者的输入,或是系统本身运算出来的结果。透过DFD,资料的流向与加工会非常清楚。然而使用use case就没有这个好处。我觉得遗漏是OOA的天性,难怪得要配合iterativeprocess

特别强调要用这样的方法,另外还会衍生出来的问题是,有些客户因为看不懂这些文件,所以会坚持以他们所提供的文件当作是系统的范围。这通常就会产生非常多的事端。

客户使用者甲:布鲁斯,你们写的这个use case我们研究了很久,我们看不懂。这样我们不敢在这份文件上签名。

布鲁斯:你们看不懂,我可以随时来解释啊。你们一定要在这份需求文件上签名啦。我们一定要有一个基准,不然以后发生问题怎么办?

客户信息部门人员乙(帮忙打圆场):布鲁斯,我知道use case这个东西是最新的方法论。可是我们的user就是水准还没有到这边。

客户使用者甲:其实系统的范围,我们一直都写得很清楚啊。我上次寄给你的power point文件就把系统的功能都写的很清楚了。

布鲁斯心想,狗屎,这么不详细的东西也可以拿来算数的喔?:我是觉得那份power point文件是已经把系统的功能大方向都点出来了啦,可是还是有很多细微的地方没有提到。(这应该算是一次成功的防御。)

客户信息部门人员乙(帮忙打圆场):不然,我们请user把他们的想法写的更明确好了,我想可能要把他们的作业流程跟需求写的更清楚一点。

客户使用者甲:好吧,我把以前提供给你们的规则写的更清楚一点,再加上我们以前的会议记录,就是我们系统应该达成的范围。

布鲁斯  :这样不行啦。我们的人都是base on我们这份use case来开发呢?

客户使用者甲:好啦,我辛苦一点,我尽量把你的use case看一看,挑挑看有没有问题。可是你在今天的会议记录上要写清楚喔,系统的功能应该以我以前提供给你们的规则为基准,再加上我们以前的会议记录,就是我们系统应该达成的范围。至于你们的use case,我是不会签名的。

布鲁斯想,看来要他们确认是很难的啦:好吧,那就只好辛苦你了。你需要多久的时间?

过了几个月,使用者看到头一个版本后,双方再度开会。

客户使用者甲:我们在文件里面提到的功能,你们都没有做到。

布鲁斯      :那是因为你在review use case时,也没有提出这一点啊。 这样啦,我们在下一个iteration把它纳进来。我会回头改过use case,再让你double check一次。

客户使用者甲:好吧。希望下一个版本就可以看得到。

过了几个月,已经把原有预计要走的几个iteration全部都走完了,功能还是不如预期,所以双方再度开会。

客户使用者甲:我们已经看过多少个版本了,你们一直到这版,都还是问题百出。你们到底有没有认真去看过我们所提供的文件啊?

布鲁斯:我记得上次我们已经应你们的要求,把requirementuse case的对应都做成excel,一条规则一条规则让你们确认了,你们还是没有确认出来,还提出这么多change request。我不管,这些我们得要收费。

客户使用者甲:收钱?你翻翻我们7/5的会议记录。虽然在我们原始文件提出的规则里面没有描述到这条规则,可是我们在会议记录里面有提到这个功能需要检查员工到职不满一年,不适用这个状况啊。这是我们在去年6月底检讨作业办法时修订的啊。

布鲁斯:这应该算是change request。况且你们review use case已经review那么多次了。我记得我们在12/14的会议里面有提到,凡是没有列在use case里面的需求,都应该算是change request

客户使用者甲:那是你单方面的想法,谁同意啊?况且你们改过那么多次版本,我们哪有能力去看你每个版本,记得你每个版本里面到底写什么?我都跟你说我们看不懂use case了,是你说你们的人一定要看,其他的文件看不懂,才帮你检查的。现在问题就都在我身上?

布鲁斯:话不是这样讲

过了不晓得又多少个iteration…

客户使用者甲:我下个礼拜要调到BOS部门去了。

布鲁斯:那我们怎么办?

客户使用者甲:我还在我们公司啊。新的承办人不错啦,我会有空多帮他的忙。

过了一个礼拜

客户使用者丙:这个use case是什么东西啊?

布鲁斯:……

信息人员本身不了解UML, OOAD以及RUP

其实客户不了解UML, OOAD以及RUP是很正常的事情。我除了在看新人的履历表,可以找到精通UML,熟悉OOAD,以及专精RUP的人以外,在现实生活中,大概只有在Rational这家公司出来的顾问中,才找得到自认为他非常熟悉这些东西的人。

大部分听过这些term自认了解的人其实都一知半解。(这不包括我,我是根本不了解。)可是最怕的就是不懂装懂。如果你遇到客户的信息人员不了解这些东西,却在上完短期的课程后,想要给你来些良心的建议,还是卓越的指导,你就完了。

客户IT人员甲:我觉得你这个图这里画错了。这个关系,应该用实心的菱形?

布鲁斯:你误会我们想要描述的关系,其实我们在图上并没有刻意去

过了半小时

客户IT人员甲:我觉得你这个use case这里用『当使用者输入email后,系统应检查email正确性。』这样写不够清楚,你应该还要描述email格式有错时的alternative flow。不然programmer怎么会知道,系统要怎么响应?

布鲁斯:我们针对这些问题

过了一小时

客户IT人员甲:你的文件我们看得差不多了,现在我们来看RUPartifact…

布鲁斯心想,杀了我吧,这种无聊的会还要开多久啊

我遇过最狠的,是在use case的叙述里面挑语句是否通顺。原则上呢,就是在改作文。如果你用英文写,就是抓你第三人称是否记得加s之类的问题;如果你用中文写,就是嫌你作文写得太差。

随笔提到另一个更狠的客户,这位小姐的挑错就跟use case没啥关系。她只是强调我们用html做成的prototyping上面所有error message的标点符号,要统一变成全角中文。这样error message才不会有的比较宽,有的比较窄。尽管我们再三解释prototyping的用途不在于此,她还是坚持要我们把所有的标点符号换成全角,她才愿意继续review下去。我们换了好几次,每次只要一有漏掉,就会被她抱怨,我们低下的作业品质,似乎为她想要找人出气的生活,带来不少乐趣与练功的靶子。

我年少蒙懂时,遇过另一个活生生的例子。

客户IT人员甲:为什么你们在use case里面没有描述,可以在class diagram里面设计出这个class?这分明是你们分析与设计不连贯。

我:use caseclass diagram没有一对一的关系啊。

客户IT人员甲心想,你分明是在狡辩:你们没有遵照RUP来开发程序

后来经过我引经据典,舌战群儒,终于赢得了这场辩论。比较年少无知的我,以为在辩论上获得胜利,应该获得英雄式的肯定,客户应该要跪拜在真理面前向我膜拜。

后来才发现,我自己需要接受卡内基训练。因为从我在辩论中获胜开始,就种下了一个超级不好的因,让我在后来做这个案子的时候,吃尽了苦头。对于大多数讲求思辩方法的人来说,科学是冰冷的事实;可是对于凡人,通常也就是客户来说,你把我惹毛了,我会让你的日子很难过。所以从我开始说明真理的那一天开始,这些被我惹毛的信徒们,就继续用不符合逻辑的言论,不断地折磨我们。

对信徒来说,要先做OOanalysis才能进行OOdesign,有了OOdesign
,才可以找出design pattern,才可以建立可以被reusecomponent。这几乎是跟先有鸡,才会有蛋一样真实;只是对我来说,我们现在所谓的OOAOOD之间的关系,比较像是狗跟蛋之间的关系。明明就是两个不相同的物种,怎么会有什么关系呢?我记得我小时候学习OOP时,class都是从天上掉下来的礼物,跟use case drivenOOA中间有什么直接的关系呢?在我的那个年代,只要你有眼睛,学过data structurealgorithm,观察现象,就可以想出class出来。只是这种好日子已经过去了。

做苦工做久了,就会想要偷懒,就把共享的东西拉出来。偷懒是所有程式设计师设计出超强component的原动力之一。又懒惰又聪明的人,才会想出一些把戏,让他可以出一张嘴,就叫计算机自己把程序写好。这就是reuse的由来啊。

我认识不少超强的程序设计师,开发共享组件的驱动力在于让他有时间,可以用上班的时间去逛色情网站,还可以在规定的时间内,把该做的事情做完。通常逛色情网站只对男性有诱因,女性总有比较重要的事情要做,例如减肥。所以这些我所认识的超人,清一色都是好色的男性。
这些好色的高手,最喜欢做的事情,当然就是写程序去把所有色情网站的内容抓回家,然后与同好共赏。我个人觉得软件工业有蛮多进步,就在于设立色情网站的人,与好色的超强程序设计师之间相互斗法,所激荡出来的。

认识这些好色的强人以后,我就觉得OOAOOD跟可以被reusecomponent
之间,根本一点因果关系都没有。难道他们是在逛色情网站的时候,在脑袋里面同时多任务去写use case吗?还是同时多任务去画sequence diagram吗?有谁在看着小泽圆、饭岛爱跟白石瞳时,可以同时想这些东西呢?

除了客户不了解UMLOOADRUP以外,另外一个更糟糕的现象就是Project  team里面的人也不懂。我预期这种情况,会随着学校教育洗脑的成功而改善。有些小朋友从来都没听过也没画过DFD,就跟我们拿建构式数学去荼毒下一代是一样的道理。教导比较年轻的一代采用比较笨的方法,可以确保老人的竞争力。

在我刚开始接触UML的这几年,遇到的现象是project team自己都看不懂这些东西是什么。于是彼此之间都在摸索。有经验的老鸟,对于UMLOOAD一点概念也没有。可是被逼上梁山,一定得要用,所以就用自己的经验胡乱使用。没经验的菜鸟,虽然懂得UML,可是缺乏process的实践经验,也不懂任何domain knowledge,所以只能任人宰割。

问题是当菜鸟发现老鸟画出来的图,还是写出来的文件不怎么样的时候,除了要面对年轻人因为梦想幻灭而心生怨怼以外,还得要面对老鸟漫长的学习曲线。通常在这种情况之下呢,会面临成员间永不停止的争辩,大多数都是引经据典关于正统的辩论,无形之中,耗费了相当多开发的时间。

接着就看到原先预设的schedule,像是自由落体一样坠落。每次遇到这种场景,就让我不禁怀念起那个使用结构化分析的年代。一切都是那么简单、直觉与美好。没办法,每个时代都有属于它自己的流行。就像是关系型数据库一样。

Relational Database

尽管OO的声音喊的震天响,Relational database(关系型数据库)还是在IT产业中扮演一个非常重要的角色。很多人一直在想,要用支持OOdatabase。问题是在这个业界里,有太多人熟悉SQL以及relational database。有太多钱花在买Oracle, Sybase, db2, Informix, MS SQL Server上。这让人relational database退休的机会变得非常小。而relational database的基本精神,跟OO就不太有关了。这让我们想要用Object的方式来思考,遇到RDBMS,就O不下去了。你可以想象一个从悬崖边大声喊着O,然后跳下去的人,当你听到声音越来越小,着地之前那个低沉的o(已经变成小写了喔),这跟你用OO的观念遇到Relational Database差不多。这个无聊的比喻虽然没什么用,可是又让我多赚几个字的稿费。

有些人是用object的观念,把table包起来。然而,在performance不好时,SQL statement还是会直接写在程序里,真要没办法,还要写stored procedure
。如果已经到了要写stored procedure这样子的阶段,还有什么OOD可以对应呢?还有什么object可以用呢?

这个业界有太多熟悉SQLprogrammer。对于这些人来说,SQL的威力这么强大,要去抗拒直接使用SQL statement的诱惑,改用纯粹以Object的观点来解问题,手会变得很痒。遇到有些很容易透过SQL解决的问题时,心会变得更痒。根据研究男性心里的医学报告指出(在此再次感谢灵犬莱西的显灵),忍耐太久是会生病的。所以只要他们一忍不住出手,通常performance就会有钜幅的改善。只是这就跟OO没啥关系了。不过,这对于所有audit这个项目的人来说,这算是瑕不掩瑜。睁一只眼,闭一只眼也就过去了。Project可以结案最重要,谁还管OOAD啊?这多少也算是OOAD面临的问题之一吧。

**
结语**

念过大学,准备过考试的人都知道,文不如表,表不如图。要描述你的观念,用一张适当的图形来表示是最强而有力,也是最容易让人理解的途径。然而为什么在系统分析的这个领域里,我们会希望透过use case来描述这个系统,而不是透过其它的方法呢?

如果你采用结构化分析(Structure Analysis)的方法,而你做的项目规模也比较小,其实使用者会有能力画出他们的作业流程图。有了流程图,其实拿给development team看,大概也知道要做什么了。认真一点的使用者还可以帮你确认你的DFD(data flow diagram数据流程图)

画出DFD以后,就可以让系统的范围用一个图形化的方法加以确认。也可以认清Dataprocess之间的关系与流向,接着只要依据资料的流向,写出function spec,再定义出data dictionary,大部分的SA工作就已经完成了。只剩下如何跟客户确认需求了。

如果你又采用了RAD(快速应用程序开发rapid application development)的工具,你就可以迅速地建立起系统的雏形(prototype)。透过雏形的展示,以及function spec,在大部分的项目中,你可以跟使用者建立起一个共识的基础。系统的范围就可以随之确定下来。

一旦SA有了共识,要求使用者确认相关的文件,接着采用传统的瀑布式开发方式(SDLC, System Development Life Cycle)来开发系统。当你遇到需求变更的时候,透过SA文件的确认,双方也就可以在一套沟通与讨论的基础上继续下去。

接着你再去采用OOD的方法来设计系统,用OOP(Object Oriented Programming)
的方式来开发系统,这不是很好吗?

还有人喜欢写use case吗?或许在超大型的项目,例如要一百万个人做个数百年,有个几万个iteration的项目里,写use case就会是一件很有意义的事情。我想当年盖大金字塔的建筑师,一定写过use case

至于RUP,我个人觉得如果仔细研究RUP,会对于大型项目开发的流程有很清楚的了解。至于对于中小型项目来说,在你进行项目管理的时候,你可以从RUP里面找到许多可以参考的模板。

只是iterative的开发方式,不怎么适用在台湾社会中。尤其是与大多数的项目互斥。如果你是开发自有产品,或许可以考虑采用这样的方式。不过我可不是开发产品的专家。出了问题,除了『你资质比较鲁钝,又缺乏经验,所以没有正确地体悟大师的讲法以及采取正确的做法,才会导致这样的结果』之外,我可是没有其它比较好的理由喔。  () 



版权所有:UML软件工程组织