一、导言
为什么要写这个系列
“OO都是一个已经被讨论烂的话题了,还有什么可写的!”
不知当你看到文章标题时,是不是有这种疑问,或者鄙夷。不错,OO从诞生到现在经历了不短的岁月,与其相关的理论、技术、原则、实践、模式、语言已经出了一大堆。可是,你真的了解OO的本质吗?真的能挥洒自如的将OO应用于软件开发中吗?真的能发挥OO的能量,从而提高软件质量吗?如果对这三个问题,你不能很干脆的点头说:“是的,当然!”那么也许你可以抽一点时间,往下看一看。
这个系列文章不打算大篇幅重述各种OO理论,也不打算谈各种OO心法。这系列文章着重于通过实践澄清一些对OO的误会,帮助朋友们更好的使用正确的方法将OO应用于实际开发中。同时,在必要的地方简要叙述一下OO相关知识。
所以,这个系列不是关于OO理论的天书或OO参考大全,而是告诉你“你对OO可能存在哪些误会与认识上的偏差”以及“如何走出误会更好的OO应用于实践”。
OO是技术,不是理论
OO,我认为全称应该叫做“面向对象技术”。其实,OO自诞生那天起其全部目的就是应用于软件开发实践中,提高软件开发质量。这也是OO存在的全部意义。所以,搞OO和搞数论、搞理论物理不一样,不能脱离应用。搞OO的人应该算是工程师,而不是科学家。两者最大的区别是:科学家可以不考虑自己研究的成果有没有什么应用价值。而工程师不一样,他们要更“势利”,要时刻关心自己研究出的东西有什么应用价值。所以一切OO的研究要以可应用性为向导,不能天马行空夸夸其谈。
当然,OO需要理论支撑,但是一定要是有现实意义的理论,而不能像数学家那样为了理论而研究理论,更不能将已有理论当做教条机械性使用。
因此,在学习和实践OO的过程中,要时刻注意和应用性联系起来,才能避免走入理论OO和教条OO的歧途。
到底什么是OO
“什么是OO?”对于这个问题,很难一言以蔽之。但正是由于对这个概念的误解和偏差,才使得某些朋友一直不能正确使用OO,不能让OO真正服务于软件开发,到最后开始怀疑OO、鄙视OO甚至唾弃OO。
在所有对OO的偏差性认识中,最普遍的一点就是“金锤”式理论,即“XX就是OO。”例如,“把所有东西看成对象就是OO”,“遵循封装、继承、多态就是OO”,“应用良好的OO原则进行设计就是OO”,“使用UML就是OO”。显然,这种“一锤子敲定”的方式会让人割裂的看问题,从而无法从全局角度正确把握OO。
在这里,我斗胆给OO下一个定义:OO,即面向对象技术,是一种旨在提高软件质量的综合性技术,其贯穿于软件系统的调研、分析、设计、开发、测试、维护、扩展、升级等整个生命周期,它包含一系列概念、思想、理论、目标、原则、实践、模式、工具、语言等要素,这些要素既相互区别又相互联系,同时从宏观和微观两个角度共同协作,指导和引导开发人员开发出高质量软件,并指导与开发有关的一切过程。
从上面可以看出,OO并不是孤立的概念或技术,而是一系列要素的复合体,并贯穿于整个软件开发周期。所以,仅仅从某个时间或控件切面切入而应用OO,这样的OO是不完整的,也不可能发挥出其应有的作用。打个比方:如果使用OO的方法和工具进行分析、设计,但是编码过程不能做到OO,就好比制造了一辆豪华的轿车却找头驴拉着走,是不能提高你出行效率的。反过来,如果你是一个C#或Java高手,但分析设计过程不遵循OO,直到编码时才用C#或Java试图OO,这无异于你听说开车能提高出行速度,于是你苦学驾驶技术,并掌握了高超的驾驶本领,但最终却坐在一头驴子上,于是你开始大喊:驾驶技术是骗人的!根本没法用!是啊,驴子上连方向盘、离合器都没有,空有一身驾驶本领又如何发挥出来呢。
这个系列的文章概要和内容组织
这系列文章的大体写作方式,是通过一个实际案例《XX食品公司连锁店在线定料系统》的调研、分析、设计、开发等一系列过程,帮助大家更好的认清OO如何实践,同时澄清一些误会。这个系统是我曾经参与过的实际案例,为了文章需要,将进行一定程度的修改,但一些很关键的东西都会原汁原味保留下来。在整个过程中,请各位不拘泥于具体技术相关问题,而要一直保持一个较高的视端,一睹OO的全貌。
文章的大概组织方式:
第一部分:需求分析之前的故事
很多人认为就软件开发来说,第一步是需求分析,其实非也。如果想更好实践OO,需求分析之前还有很多工作,如特性调研、降低风险等环节,这一部分我们讲讲需求分析之前的故事。
第二部分:分析步步高
这一部分开始对系统进行真正的分析,让我们来看看OO是如何引导和指导我们分析的。
第三部分:设计的方方面面
设计是一个繁杂的过程,诸多OO原则与模式都会应用于其中,这一部分不会细讲各种原则及模式,而是看看正确应用原则与模式的方式是怎么样的。
第四部分:让所有努力开花结果
这一部分,我们将前面的成果付诸实践。通过这一部分,可以清楚的看到前面做的一切工作都不是飘在云里的空中楼阁,而是开发高质量软件不可缺少的部分。
以上是目前的规划,当然,在整个过程中可能会出现变化,但是大体条理不会打乱。希望本系列文章能给您带来帮助。
二、第一项任务:特性列表
第一份说明
当这个项目开始时,我们得到的关于我们要做的系统的唯一说明是一页Word文档,这是一份简单的不能再简单的说明。文档里只有一行字:我们需要一个系统,使得全国各地的代理加盟商和连锁店能够通过网络订购原料。另外,我们还知道这是一个食品公司,主营面包、麻花、肉夹馍等食品,在全国各地有多家连锁机构。除此之外,我们一无所知。
永远不要和客户谈需求
软件开发的第一步是什么?很多人觉得是需求分析。显然这短短的一句说明无法满足我们的要求,于是很自然的,你希望找客户谈话,详细了解情况,然后做出详细的需求分析。于是,你心里有了这么一个算盘:
和客户谈话 -> 问清所有需求 -> 进行需求分析 -> 生成需求文档
乍看之下,这是很合理的步骤,但是实际上这是不可行的。原因有如下几点。
1.客户不关心系统的所有方面
每个开发人员都希望,客户可以清楚的把自己需要的东西的方方面面清楚无误告诉你,然而,这只是一厢情愿罢了。因为,任何一个客户在需要什么东西的时候,只会大致想想要个什么东西,并不会将所有地方都仔细想清楚。
2.有时客户并不清楚自己到底要什么东西
有时候,客户并不是很清楚自己想要什么。这不是天方夜谭。很多时候,客户仅仅有一个“想要实现某个目的的动机”,而没有“我需要一个什么系统”这么明确的概念。例如,从上文那个“一句话说明”中,可以看出,我们的客户仅仅是有一个动机:希望有一个系统,能使得他们公司的代理商和加盟店在线定料,至于这是一个什么样的系统,他们并没有明确的概念,更不用说这个系统有什么样具体的需求了。
基于以上两点,你是不可能从客户那里问清所有需求的。实际上,就不该和客户谈需求,因为需求从来就不是“客户面”的东西,而是“开发人员面”的东西。需求需要包含方方面面系统需要实现的功能,而客户往往并没有如此精细想过,甚至客户自己对自己想要的东西什么样子都不清晰。面对这种客户,你一本正经往他面前一坐,开发笔记本说:“我们谈谈需求吧”,或说“我们进行需求分析吧”,我想客户会立马崩溃,而你也不可能得到你想要的所有东西。
作为开发人员,不应该一开始就和客户谈需求,而要先谈特性。很多需求并不需要客户告诉你,开发人员应该能通过常识识别出来,就如没有哪一个买汽车的客户会说:我需要一个辆汽车,要有方向盘,还要有四个轮子。他们通常会说:“我要一辆家用车、要省油、舒适,要至少能坐3个人。”这“家用车”、“至少能坐三个人”就是特性。
特性是一些描述,一条特性简要描述了系统的一个客户最关心的核心功能。
最为开发人员,首要任务不是做需求分析,而是帮助用户整理出一份特性列表。这里之所以说“帮助”,是因为很多时候,客户由于自身太关注于某个方面,而漏掉了十分重要的特性,这是你要帮客户想想,并将想到的特性询问客户是否是需要的。如果客户很高兴的说“对!对!”,那么这就是大功一件。所以,在初期阶段,开发人员一定要想客户之所想,急客户之所急,尽快帮客户理清系统有什么特性。
所以,正确的过程应该是:
询问客户系统都有什么功能 -> 写出初期特性列表 -> 想想什么遗漏特性,并询问客户 -> 查漏补缺
生成特性列表
下面回到案例。
虽然客户的说明只有一句话,我们还是整理出一份初期的特性列表,并将其作为我们向客户展示的第一份工作成果。这份特性列表内容如下:
1.可以将各种原料信息发布到系统上
2.加盟商和连锁店可以通过系统在线定料
没错,我们的初期文档只有两项特性。我们把这个给客户看,客户说:“嗯……大约是这个东西吧。”很显然,我们的客户是比较懒的那种,这时,我们有义务引导客户想起更多需要的特性。下面是当时大约对话:
开发人员(简称D),客户(简称C) D:你这个加盟商和连锁店是要如何区分呢? C:我们公司有一个加盟商和连锁店的记录。 D:那么你们是准备将各个加盟商的信息全部录入系统吗? C:不是,我希望他们能自己注册,就和论坛那种。 D:那么你要如何确认他们的身份,总不能任何人都可以在这个系统注册吧。 C:嗯,我们公司有各个加盟商的详细信息,我们希望他们注册时提供足够的信息,我们进行核对。 (于是我们飞快写下一个特性:加盟商和连锁店通过网络进行注册,总店负责人审核后才可以正式使用系统。) D:你们得在后台能发布各种原料的信息吧。 C:嗯,使得。 D:这里有没有什么特别的要求。 C:没有吧…… D:好的,那么你们准备设立几个人负责管理这个系统。 C:就一个人吧,就信息部那个。我们就这一个比较懂计算机的。 D:也就是说不需要有多个人分别管理这个系统? C:不需要。 (写下一个特性:系统需要一个管理员,可以对系统进行管理) D:在你们的加盟商进行定料时,你希望他们怎么操作啊。 C:这个,我没仔细想过…… (看客户对这个地方比较不清晰,我们打开了一个网上书店的网站,给他演示了一下购物车购物的过程) D:你看,你的这个定料过程是不是和这个购物过程很相似,加盟商定料是不是就相当于从总公司购买原料啊。 C:对对!就要这种效果的! (这里要记住,在特性不能直接说清楚时,找相似事物是一个不错的选择。也就是说,说明这个特性像什么,不像什么) (我们又加一条特性:使用购物车功能进行网上定料) D:付钱这一块怎么弄,需要网上支付吗? C:不了,我们一般又财务专门做钱这一块工作。 D:那买完原料后要不要什么凭证呢? C:买完后生成一份定料单吧,打印出来,交给财务,财务清算款项,款到账后通知原料那边发货。 (又一条特性:定料完成后生成定料单,并可以打印) D:那么关于这些交易,你一定希望能查询吧,你希望怎么查询。 C:哦,这些我们财务那边有专门的财务软件。你这个系统只要能让加盟商定料就行了。
到这里谈话基本结束,我们得到如下一张补充过的特性列表:
1.可以将各种原料信息发布到系统上 2.加盟商和连锁店可以通过系统在线定料 3.加盟商和连锁店通过网络进行注册,总店负责人审核后才可以正式使用系统 4.系统需要一个管理员,可以对系统进行管理 5.使用购物车功能进行网上定料 6.定料完成后生成定料单,并可以打印
我们将补充后的特性列表给客户看了看,基本得到了认可。
到了这里,我们第一步就差不多做完了。但是,我们还是不能马上进入需求分析,因为这之前还有很多事情要做。例如,特性整理,风险规避,这都是后面要讨论的话题。
重点总结
1.客户不会想到方方面面。 2.有时客户并不明确自己想要什么东西,而仅仅是有个动机。 3.不要和客户谈需求,要谈特性。 4.开发人员有义务引导和帮助客户挖掘系统的特性。 5.当客户描述不清某个特性时,可以采用找类似事物的方法,说说这个特性像什么,不像什么。 6.在软件开发初期,我们需要首先整理出一张特性列表,而不是做需求分析。
三、降低风险
风险无处不在
在上一篇文章中,我们写出了一张特性列表。然后是不是就可以做需求分析了?很遗憾,还不可以,我们仍有许多工作要做。拿到特性列表后第一件事,就是要尽量降低风险。这里先不长篇大论风险如何如何,我们先做,从做的过程中体会降低风险的涵义。
DRY
这里,首先要引入一个OO原则——DRY。
DRY原则,全称Don't Repeat Yourself,指:在系统中,每一个信息或行为片段应该仅仅存在一份,且存在于合适的地方。
对于这个原则,很多朋友将其理解为“不要出现重复的代码”,这是很片面的理解。其实,OO本身并不是仅仅关于如何写出优秀的代码,而是关于如何开发出优秀的软件。所以,很多OO原则并不是仅仅代码层面的原则,而是可以应用于整个开发过程的。下面来着重看看这个原则的深层意义,以及讨论其在降低风险中的应用。
如何利用DRY降低风险
在所有的开发风险中,有一种风险,是由于同一个信息或行为片段分散于系统的不同地方,从而导致重复劳动,并且给修改和维护造成隐患。
下面,分别通过例子来描述两种不良后果。
1.重复劳动
例如,在特性列表中,如果两个特性本身应该是一个特性,但被误认为是两个不同特性。那么所有基于特性的分析和设计都存在重复劳动,即对同一个特性,做了两遍分析和设计,直到发现重复为止。这个代价是巨大的。
2.修改和维护隐患
例如某一代码段完全相似,但是出现在程序的诸多地方。这些相似的代码段一定是完成完全相同的功能,于是有着“同生同灭”的特点,即如果某段代码要修改,一般来说所有这段代码的重复代码都要修改。这就给维护带来很大隐患。
DRY原则正是针对这种风险的一个解决方案。关于DRY在代码中的应用,暂且放下,这里只看它在特性列表整理中的应用。显然,根据DRY原则,要求特性列表中的特性不能具有重复,那么我们再仔细看看我们的特性列表:
1.可以将各种原料信息发布到系统上 2.加盟商和连锁店可以通过系统在线定料 3.加盟商和连锁店通过网络进行注册,总店负责人审核后才可以正式使用系统 4.系统需要一个管理员,可以对系统进行管理 5.使用购物车功能进行网上定料 6.定料完成后生成定料单,并可以打印
仔细检查,不难发现2和5其实是在描述一个特性,于是我们将2和5合并成一个新的特性:加盟商和连锁店可以使用购物车功能在线定料。另外,可以看出,“总店负责人”和“管理员”其实是一个概念。整理完后,得到如下新特性列表:
1.可以将各种原料信息发布到系统上 2.加盟商和连锁店可以使用购物车功能在线定料 3.加盟商和连锁店通过网络进行注册,管理员审核后才可以正式使用系统 4.系统需要一个管理员,可以对系统进行管理 5.定料完成后生成定料单,并可以打印
再仔细检查,已经没有重复特性。这样,我们就应用DRY原则规避了第一种风险:重复劳动的风险。下面给这种风险下一个定义:
重复劳动风险——指由于重复特性的存在,导致对同一特性进行了一遍以上的分析设计过程。最终导致资源浪费,开发效率降低,可能导致无法按时交付。
知之为知之 不知为不知
在使用DRY整理完特性列表后,下一步就是要规避第二种风险:概念模糊。
概念模糊风险——指由于开发人员对于某一领域知识不熟悉,而将某一个概念想当然,继而根据这个想当然的结果进行分析设计。如果其想法错误,则会导致系统无法正常使用或无法完成业务既定目的,从而导致返工或项目失败。
很明显,一般来说开发人员并不是业务专家。所以对于领域业务不熟悉是很正常的,作为一个合格开发人员,应该谨遵孔老夫子“知之为知之,不知为不知”这一教诲,谨慎负责对待不熟悉的概念,而不能从字面臆想。正确的做法是,首先审视特性列表,对于不熟悉或拿不准的概念,去请教领域专家或客户。下面继续以我们的项目为例。
经过对特性列表的分析,我们找出以下疑问或模糊概念:
1.原料(都是什么原料,需要分类么?)
2.加盟商和连锁店(两者有什么区别?定料业务流程一样么?)
带着着两个疑问,我们再次拜访了客户。具体交谈就不说了,最后我们得到了如下结果。
1.原料主要就是些炸粉、调料之类的配方需要保密的烹饪原料,没有太特别的,不需分类。
2.加盟商和连锁店不是一个概念,加盟商直属总公司,连锁店可能直属总公司也可能直属某加盟商。加盟商和直属总公司的连锁店直接向总公司定料,不直属的的连锁店向相应加盟商领取原料。连锁店按原价定料,加盟商按照等级分为5级,每级折扣不同。
经过以上一番了解,我们基本把模糊概念搞清楚了,并且经过这么一了解,我们的特性列表随之改变:
1.可以将各种原料信息发布到系统上 2.加盟商和连锁店可以使用购物车功能在线定料 3.加盟商和连锁店通过网络进行注册,管理员审核后才可以正式使用系统 4.系统需要一个管理员,可以对系统进行管理 5.定料完成后生成定料单,并可以打印 6.直属连锁店按原价定料,加盟商按照等级分为5级,每级折扣不同
我们认为加盟商级别和折扣是很重要的特性,于是把它加到了特性列表里。
保证我们能够实现
上面我们已经避免了两种风险。现在再来看一种风险。举个例子,如果一个建筑设计师,设计了一座新型别墅,其中有一条特性是:院子里有一个季节调节装置,可以随意将院子里的季节调节为春夏秋冬中任意一个季节。你们认为这个特性怎么样?很酷的创意对不对?但是如果你是别墅的客户,你会这么想?我想你不会和设计师一起为这个非常酷的特性而激动,你会首先问设计师要怎么实现这个功能。没错,可以调节季节的院子是很棒,可以不要忘了,最终我们的别墅是要建筑在实际中的,而实际总会有诸多约束不能让每一个想法变成现实。
同上。无论我们设计的东西多么天花乱坠,最终都是要编码实现的。所以,我们要保证所有的特性可以在编码层级上有解决方案。即使我们不能马上知道精确的解决方案,但也要大体知道怎么实现。由此引出了第三种风险:
实现能力风险——指由于某项特性不能由具体技术解决带来的风险。这种风险包括两个层面,第一是现有技术完全解决不了。第二是由于开发团队没有解决方案。这种风险可能导致项目延期甚至失败。
要规避这种风险,就要逐一审查我们的特性是否可以在现有技术范围内解决。仔细审查后,第一个层面应该是没有问题,所有这6种特性都可以在现有技术内解决。但是对于特性2,我们存在一定问题。因为当时我们都没有设计购物车的经验,一下子不知购物车是如何实现的。
为了解决这个问题,要做如下工作。这里要注意,我们在这里可能讨论了很多细节,但是我们要避免提前进入细节。所以,这里讨论的所有细节并不是要进行分析或设计,而仅仅是通过头脑风暴的方式大约有个谱。这个“谱”往往和最终的实现有很大不同,但是至少我们知道这个特性通过某种方式可以实现。
在遇到这种风险时,首先要做的是查找相关资料。在查找了一些资料后,我们了解到购物车一般分为Session实现方式和数据库实现方式。这两种方式特点不同,前者支持未登录购物,确不能保存客户购物信息。而后一种又必须登录后才能购物。这里涉及到客户的利益,所以要由客户决定。
于是,我们询问了客户,得到的答复是“未登录时要可以定料,而且也要保持定料信息。”这句话有点模糊,但大体可以知道客户的意思,于是我们改写成如下一段话“未登录的用户可以使用购物车,但不能下定料单,登录后才可下单。登录用户可以保持购物车中信息。”我们拿给客户看,并进行了一定描述,客户认同了这个决策。
这个确定后,我们就要讨论一下具体解决方案了。我在这里再次说明,以下的讨论不是分析或设计,而仅仅是让我们对棘手的问题更清晰一些,从而心里有个谱,避免实现的时候不知如何是好。
在经过一番讨论后,我们都同意的解决方案是“未登录的用户使用Session处理购物车,登录的使用数据库存储购物信息。当用户登录时,如果Session中有将购物信息,将Session中的信息转入数据库。”
这个讨论可以到此为止了。因为我们不需要太精确,我们只要大致心里有个谱就行了。
重点总结
1.特性列表完成后,我们首先应该降低风险,而不是做分析或设计。 2.重复特性存在风险。可以用DRY原则处理。 3.存在模糊不清概念的特性存在风险。请仔细询问客户,不要想当然。 4.不知如何实现的特性存在风险。一定要保证对每条特性的实现方式心里大致有个谱,但不需很精确。
四、通览全局:避免过早陷入细节的泥沼
细节的泥沼
现在我们再次将特性列表贴过来:
1.可以将各种原料信息发布到系统上 2.加盟商和连锁店可以使用购物车功能在线定料 3.加盟商和连锁店通过网络进行注册,管理员审核后才可以正式使用系统 4.系统需要一个管理员,可以对系统进行管理 5.定料完成后生成定料单,并可以打印 6.直属连锁店按原价定料,加盟商按照等级分为5级,每级折扣不同
我们已经和这则列表折腾很久了,相信很多朋友已经厌倦了,肯定在想:不要在折腾这该死的特性列表了,赶快开始吧。这点我同意。但是要开始做什么?很多朋友可能会说:开始用例分析吧。说实话,用例是好东西,它让我们清晰认识到系统的工作流程,正式因为过于清晰,所以很容易让我们陷入一个细节的泥沼。
应该说,从“特性列表”直接到“用例分析”不是一个好注意,因为特性列表关注于功能(Function),而用例关注于系统的业务流(Business Flow),我们从功能直接开始分析系统的细节业务流,这个跨越太大,不利于软件质量的保证。特性是相对分散独立的功能描述,而用例是系统细节,很明显,在这之间应该有一个过渡,而这个过渡,就是一个高层次的,从全局角度对系统的一个概观认识。这个概观认识起到承上启下的作用,既将特性列表映射为一个系统的大概模型,又给系统细节的分析奠定了基础。所以,在系统特性基本确定后,我们首先要从全局给出一个系统的概览,避免落入用例分析这样细节的泥沼。
概览系统的有力工具——用例图
既然我们要给出一个全局的系统概览,自然就需要有一种方式将其表达出来。显然,仅仅通过说是不理想的,我们需要一种能用于书面表达的工具,而这个工具,就是我们非常熟悉的UML图之一的用例图。
很多朋友可能有疑问,上面不是说不进行用例分析吗?怎么这里又画用例图了?因为用例和用例图表述的信息层面完全不同,用例更倾向于细节和业务流的描述,而用例图倾向于整体的描述。下面给出两种工具要表述的信息:
用例——表述某个交互操作的动作执行者、用例名称、具体流程过程、例外情况等。
用例图——表述系统有哪些执行者、有哪些用例以及执行者于用例、用例于用例之间的关系。
很明显,用例更关注于某一个操作的具体流程,所以适合在需求分析中使用;而用例图更关注于整个系统的使用和交互情况,因此能给我们一个系统的概览。
下面,我们就使用用例图,从高层次角度看看系统的样子。在这里还要说明的是,随着UML和用例分析技术的发展,提出了业务用例和系统用例的区别,而且用例存在不同的粒度。在进行高层次概览的时候,我们是使用的是一种粒度比较粗的用例图。也许在以后的需求分析中,我们还会使用粒度更细的用例图。
通过简要对特性列表的分析,可以画出一张如下的用例图:
可以看到,这个用例图并没有太多细节的东西,而仅仅描述了三个信息:1.系统有哪些用户 2.系统有哪些操作 3.系统和用户有哪些交互。这些,就是我们要的一个系统概观。
用例图的验证
画完用例图,我们并不是就完事了。因为,要使得用例图真的是全局概观,就一定要保证一点:图中用例覆盖了所有特性。如果不能覆盖所有特性,说明我们的用例图中缺少用例甚至缺少动作执行者。现在我们来验证一下: 特性1覆盖于“原料管理”。 特性2覆盖于“在线定料”。 特性3覆盖于“注册”和“加盟商和连锁店管理”。 特性4覆盖于“原料管理”和“加盟商和连锁店管理”。 特性5覆盖于“打印定料单”。 特性6覆盖于...???
我们忽然发现一点,这里并没有和折扣有关的东西,那么这个特性没有被用例覆盖。我们知道,如果要实现这个特性,系统中一定要有一定的折扣机制,而一定是有管理员设置的。于是我们增加一个“折扣管理”用例。注意,这里我们可以先不陷入细节,仅仅知道系统有这么一个折扣机制,至于具体怎么实现,到分析设计阶段再讨论。于是,修改后的用例图如下:
现在我们可以说:特性6覆盖于“折扣管理”和“在线定料”。
好了,这样我们已经确认,用例图的用例覆盖所有特性。
重点总结
1.不要过早陷入细节 2.在特性列表到用例分析之间,用该先有一个系统概览,让我们从高层次上审视系统全貌。 3.用例图是实现这种概览的有效方式。 4.用例不要粒度过细,要能反应系统粗粒度操作。 5.最后不要忘了检查图中用例是否覆盖了所有特性。
作者:T2噬菌体 出处:http://leoo2sk.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 |