我觉得无论结构化范型或面向对象的范型,都是应用到软件工程的每一个阶段。系统的分析、设计必然要为技术管理提供方便,而且从程序的设计方法不断演化(过程式程序设计-〉模块化的程序设计-〉面向对象程序设计)的过程来看,先进的分析和设计方法为技术管理提供更大的便利。我认为反之亦然。也就是说,我们在应用UML及其背后所体现的面向对象的分析建模与设计思想时,最好能有一个比较规范的软件工程环境,并把改进软件过程也看作一个目标,这样更能推动面向对象方法的应用。
之所以有此感受,是因为我以前在一家较小的软件公司工作,参与过一个数据库管理应用的开发。该公司的软件过程并不规范。UML的使用总局限于某些局部阶段。因为如果软件过程不规范,人们的思维容易从系统功能需求直接转向编码。对于使用JAVA这样的纯面向对象语言来说,此时使用UML作类设计是很有帮助的。而用例说明,构件图等对维护人员则很有帮助。
坦白的说,我觉得我以前的项目组在得到系统功能需求的过程中,很难说是使用结构化或面向对象的方法。如果说是结构化方法,有人会赞同;如果说是面向对象的方法,也不知道为什么不是。当时我和坐我隔壁的一个资格很老的系统分析员老宋都参与了系统功能说明和系统设计的工作。老宋一直就使用结构化分析的方法。而我在开始学习系统分析和设计的方法时,就选择的是OO方法,对结构化分析了解甚少。
但在得到系统功能需求过程的讨论中,我并没有感觉到分析方法的不同在实际工作结果中造成的区别。而且由于公司对系统功能需求等文档都有模版,我只能说我当时没有看出分析方法的不同在实际工作结果中造成的区别。关于结构化方法中的功能模块的划分和面向对象中用例的说明,我个人的感觉是区别不是很大。不论哪种方法,似乎都得先划分出几个大的模块,再划分小的模块。当然,有可能是我们开发的是一个中型的数据库管理应用的原因。
当时我们开发的是数据库管理应用,使用的是J2EE技术,所以在此后的系统设计的过程中,我先找对象,映射成数据库表,再确定对象的方法。老宋是先设计表,再规定模块间的接口。由于使用的技术的原因,老宋最后得到的结果和我的结果看起来都差不多。表设计、EJB接口定义、界面设计。
这些设计结果然后分配到具体的开发人员身上。由于使用的是JAVA,所以编程时都使用的是面向对象编程。整个过程中我很难找出结构化分析方法和面向对象方法的较大的区别。
我在读《软件工程JAVA语言实现》一书时,对于第6章的练习18分别使用结构化分析方法和面向对象方法进行分析,感觉两种方法着手点虽然不同,但结果都很类似。如果规定使用纯面向对象的语言的话,我觉得按这两种分析和设计方法最后得到的代码应该极为类似以至于难以看出系统分析的风格。结构化方法分析过程如下:
1、总结出系统应有的功能,对一个功能,从功能完成的过程考虑,将各个过程(或说小的功能(难以再分解))列出,标识出过程转向和传递的数据。这样,可以将所有的过程都画出来。
2、细化数据流。确定应该记录的数据。
3、分析各过程之间的耦合关系,合理地进行模块划分以提高它们之间的内聚性。实际上,对于这个练习,可以使模块具有信息内聚性。
而面向对象方法分析过程如下:
1、总结出系统应有的功能,从功能完成的过程考虑,描述每个功能的完成过程。对应UML的USECASE和SEQUENCE。
2、开始寻找定义对象,并归纳各对象应记录的属性,对象的状态及转换关系在这里定义。这一步的对象和第一步画SEQUENCE所带入的对象有联系但更重要的是区别。
3、从功能完成的过程考虑,区分所需要的各个功能。再根据定义出的对象,将功能分配到对象上。由于第一步的关系,在这个练习中,这一步相对简单。
4、根据前3步的结果,如果需要的话,应该重新画SEQUENCE。特别是希望UML图对编程能更有帮助时。由于我只做了系统分析,没有编程,所以这一步没有做。
对于自己做的这个练习,我想比较其中体现的两种方法的异同:
1、总结系统应具备的功能的时候,都是根据题目的描述,一条一条总结归纳得到的。对结构化方法,就是画数据流图。对面向对象方法,就是USECASE和SEQUENCE。实际上,在工作中使用时,一般还需要ACTIVITY图。
2、确定应该记录的数据。对结构化方法,就是细化数据流,并整理出一个一个的表。对面向对象方法,就是寻找和定义对象,并归纳各对象应记录的属性。一般O-R关系转换都是套用流行的方法,可能有些组织对此都有规定。
3、模块的组织。如果实在是要避免歧义的话,应该说成是“将数据和功能分配到不同的文件中,用文件来合理地组织代码”。对结构化方法,就是划分模块,每个模块应该包含哪些文件以及每个文件的内容。对面向对象方法,就是在已有对象的基础上,将功能分配到对象上。相比较结构化方法,面向对象在这里强制要求:将数据和功能分配到不同的文件中时,是以数据为中心。事实上,使用结构化方法划分模块时,如果希望模块具有信息内聚性,那么,也是以数据为中心。“有信息内聚性的模块,本质上是抽象数据类型的实现”[P89,《软件工程JAVA语言实现》]。
4、接下来就应该是编程了。如果都使用JAVA的话,我很难想象出两种结果的代码能有多大的区别。
以上列出了两个例子,其意图在于说明某些情况下,我们进行系统分析时,当我们希望模块有信息内聚性时,结构化方法和面向对象的方法得到的过程和结果不会有很大差别。
需要对关于使用这两个例子作一些说明:
1、在UMLCHINA网站上经常看到一些文章特别强调面向对象方法中寻找USECASE和结构化方法中功能模块的划分不同。在所有的这些文章中,我也一直没有找到能够让我明白为什么不同的文字。当然,不排除以下原因:
1、1:我使用系统分析方法进行进行系统分析并指导编程的时间不长。
1、2:我的理解有问题的原因,比方说,可能在某个环节上钻入了牛角尖。
1、3:我涉及的行业领域的原因。我一直参与项目,开发数据库管理应用。
1、4:其他原因。
一个系统必然先得划分为不同的子系统。子系统如果仍然太大了,那么也必须划分为不同的子系统。以此类推。面向对象方法中的用例分解和结构化的功能模块的划分是对应的。如果用面向对象的观点来看,系统是由各个级别的对象装配而成。一个系统就是一个大对象,子系统也是对象。因为完全地从下至上地构造系统是难以想象的,所以需要进行用例分解。对于一个中型系统,像上述的第一个例子,我自问难以找出用例分解和模块分解的区别。尤其是应用不同方法时如果产生区别的话,应该在思路上会在某一个或多个关键点上有重大区别。《软件工程JAVA语言实现》中说:“如果采用面向对象的范型,则在分析阶段中有一个确定对象的步骤。因为对象是一种模块,所以结构化设计是在面向对象范型的分析阶段执行的”[P13]。对此我深表赞同。当用例分解得足够小时,该用例就类似于第二个例子。
在面向对象方法中,寻找用例时引入的对象和用于编程的对象是不同的,而结构化方法中一个功能模块也不必就对应一个程序模块。
事实上,老宋也用UML建模,但他坚持他使用的不是面向对象方法。因为他说自己从没用过面向对象的方法分析问题。
2、前面的论述其实说明了:在给定的限制下,面向对象方法中的对象和结构化方法中的具有信息内聚性的模块区别很小。但有些情况下则不然。
就我个人的经验来看,在项目的系统分析和产品的系统分析中,面向对象方法的应用效果很可能不同。
2、1:对于项目开发来说,一般的软件公司都会只做某一个或某几个行业的某些领域的应用。不会打一枪换一个阵地。对于有项目经验积累的行业,除了一些系统框架性的功能,如根据权限限制的菜单生成,和极为底层的与业务无关的功能,如读配置文件来连接数据库,其他功能很难重用。这使得即使采用面向对象分析方法,但面向对象的继承、多态等能够有力支持重用的特点根本就没有用上。倒是函数重载用得较多。
2、2:对于开发数据库管理应用的项目来说,我觉得在使用结构化方法时以数据为中心组织模块是很自然的想法。这时再使用JAVA编程,那么使用结构化方法定义出来的接口和使用面向对象定义出来的接口基本相同。可以参考:“notes_svr52\CDMA事业部\软件工程论坛”中的一篇文档
''CSDN:独孤木专栏:UML OOAD and RUP''。
2、3:开发产品系列时对重用的需求应该远比开发项目要强烈。这种情况下使用面向对象方法进行系统设计应该会比使用结构化方法效果要好的多。
以C和C++为例,C最多可以做到不完全的封装,继承和多态是无法做到的。假设有个系统,如果使用继承和多态能比较简洁地使它有良好的可扩展性的话,用C要达到同样的目的肯定要复杂得多。此时,面向对象方法和结构化方法比较——不仅仅是技术上的原因,我认为更是技术管理上的原因——使得面向对象方法更为优秀。任何将“分而治之”贯彻得更好的技术和方法,如果能达到同样的系统功能性能移植性等的要求,必然代替其他方法。纯技术上的优势,我觉得相对于技术管理的优势,并不是主要的:
2、3、1:“在许多情况下,从继承不会获得任何实际利益。然而,在大型项目里,‘不用继承’的政策的结果将是不易理解的不够灵活的系统”[P638,《C++程序设计语言》]。
2、3、2:“面向对象技术包含了很多方法学上的进步。……面向对象应用在整个开发周期中,但是真正的获益只有在后续开发、扩展和维护活动中才能体现出来。Coggin
说:‘面向对象技术不会加快首次或第二次的开发,产品族中第五个项目的开发才会异乎寻常的迅速。’”[P130,《人月神话》]。
2、3、3:个人认为,公司的文档中将函数定义和说明写在文档中,确实比不上JDK那种有清晰的类层次的可以单独存在的帮助系统。
3、我对软件过程和软件工程并不是很熟悉,最多只能说听说过概念,对于一个概念在实际工作中的意义,我总有一种模模糊糊、懵懵懂懂、感觉好像是但又抓不准的感觉。但在我以前的工作中,我自认还算一直努力地想改进我参与的项目的开发过程。在我的看法中,技术管理和开发过程管理是不同的。开发过程管理更多地和项目管理结合在一起,而技术管理更多地指研发流程、制度以及文档规范等。我知道有些公司的项目经理可以不懂技术,但我所知道的担任技术管理干部的人没有不懂技术的。任何一个分析方法,都是要应用到开发过程的每一个阶段,对开发过程的每一个阶段的每一个成员的思路都有影响。所以我认为一种分析方法如果相对另外一种分析方法而言更优秀的话,那么它必须改善技术管理。很多优秀技术一旦提供,就会发现它对开发过程的某些个或某一方面的技术管理的问题的改善提供了核心的作用。
4、我以前对测试不太关心,觉得测试是很简单的事情。直到我工作后发现当时所在公司的测试经理的桌面上摆了一排测试方面的书,才在大惊之余觉得有必要对测试的重要性和地位重新认识。但坦白的说,我觉得我在测试方面的了解仍仅限于运行程序。我觉得一种系统分析方法或技术如果优秀的话,应该能对测试提供更多种且更有效的测试方法和规范。
如果你没听过UML,容我在此做个解释。这三个字就是U Must Learn的缩写,指的就.是你一定得学(you must learn),如果有下一句,应该是You
Must Pay。这是几个大师.级的人物,为了要把学术理论顺利转化成现金,所想出来的好点子。基本的想法是,.如果可以弄出一套理论,让全世界想要学软件开发的人都得要来学习,那他们光卖这.套理论的教育训练、认证、顾问咨询、以及难用的开发工具,就可以让公司上市,变成亿万富翁。.开玩笑的。
这是三位对象导向软件工程界的大师(Grady Booch, James Rumbaugh, Ivar Jacobson),.为了济世救人所整合出来的一种模型语言,称为Unified
Modeling Language。算是把.三个人的东西,切成小块以后煮一煮,放在碗里面用汤匙搅一搅,整合成一个大杂烩…
嗯,不是,是把三个人的理论去芜存菁,所整理出来的结果。
UML主要的目的,在于让所有进行系统分析设计的工程师,可以有一个共同的图形化.语言,来描述他们所想要建立的系统。至于让公司上市,以及让所有学习UML的工程.师,可以有比较显赫的履历表,则算是产品附加价值,不算是主要的目的。
因为这个语言,现在正流行,算是当红炸子鸡,所以许多软件公司,莫不努力地往这.个方向发展,期望引进UML,可以为软件开发,带来前所未有的助益。很多人的想法,.当然还是围绕着可以做出被重复使用(reuse)的软件组件,以加速系统开发为核心。
吉娜:布鲁斯,老板问我什么是UML?他说他到研讨会里听到,超人公司已经在采用.这个东西了,听说有非常好的成果。他觉得我们所有的工程师也应该学习这种新的skill,.这到底是什么东西?
布鲁斯:这是几个对象导向分析设计界的大师,所共同建立的新的Modeling Language。
吉娜:Modeling language是什么东西?算了,我不需要知道这些detail。既然老板已经.说需要引进这种新的趋势,这就是我们今年的目标。你先找一些人去上课,然后回来.我们拿几个项目开始试试这种新的方法。
既然这只是一种语言,其实并没有好坏的问题。这就像中文是否比英文优秀一样,每个.人会有不同的看法。只要在使用的时候,它可以发挥它的用处,可以让看到文件的每个.人,都很清楚了解你想描述的模型,我觉得它就发挥了这个模型的功用。
然而大师或是大师的徒子徒孙们,不会光把UML这三个字从头到尾念一遍就了事,他们.除了介绍这个语言,还会讲其它的理论。这些话,就跟着UML的推广,跟着被信众们奉.为圭臬,当作是神谕。例如引进UML的团队,通常会采用Use
Case Driven的OOAD(对.象导向分析设计),也通常会想要采用大师建议的开发流程:RUP(Rational Unified
.Process),来开发项目。
对很多老板来说,这些东西就跟用来杀狼人的纯银子弹一样,可以让专案所面临的所有.问题都顺利解决。所以每次听到一个比较新潮的理论,就会想要叫属下用用这么神奇的.理论。而这些东西看起来是这么的有连贯性,从OOA开始进行需求分析,到使用OOD.进行系统设计,接着再用OOP来开发程序,在开发过程中,都依循RUP的规范,再使用.共同的UML语言。只有依照这样完美的方法,才可以确保整个项目的品质,并且开发出.可以被重复使用的软件组件。
老板的思考的确比较单纯,然而不少信徒也吃这一套,于是乎根本就不管三七二十一,.直接就狠狠地给他用在项目上,丝毫没有考虑中国社会的特色,应该要先想想师夷之长.技以制夷,要尽量中学为体,西学为用才对啊。结果当然是撞的满头包。
还好对于信徒来说,通常他们还可以自我安慰:『美国这么先进的国家都采用这么新颖.的方法来开发,跟着世界趋势走,一定不会错。现在的问题,一定是因为我们的人资质.太过鲁钝,没有完全依照大师的指示来做。下一次,我们一定要按照大师精辟的理论来.开发,一定不会遇到什么问题。』
然后这些信众们,就会继续抱着众人皆醉我独醒的悲壮,继续努力下去。一边做的时候,.一边为自己又累积一些OOAD的开发经验而自豪。
当然,我个人也觉得,大师一定不会错,一定是我们资质比较鲁钝,又缺乏经验,所以.没有正确地体悟大师的讲法以及采取正确的做法,才会导致这样的结果。只是除了我们.比较笨以外,总也要找一些理由,把责任推给大师们,不然铁定会被客户砍头。大师既.然要济世救人,就只好请你们抱持着我不入地狱,谁入地狱的决心啰。
所以我会针对我观察到的几个因为采用OOAD,以及RUP在台湾做案子所发生的几个问.题,提出我个人的看法。几个我观察到的主要问题如下:
-没有依据项目的特性来选择项目开发方式。
-使用者或者是客户的信息人员,看不懂相关的文件。
-信息人员本身不了解UML, OOAD以及RUP。
-Relational Database
以下我会针对这些问题,进行我个人的看法。
没有依据项目的特性来选择项目开发方式
台湾的软件项目,通常规模都不是很大,除非你将人力外包给企业使用,否则一般的软.件项目,价格则多半是在一开始就定下来了,项目进行的过程里,通常没什么机会可以.调整金额。
项目成员人数,多半在二十人以下。所以如果你要采用RUP来开发项目,你的第一个问.题会是,你凑不到足够的人头,来担任每一个RUP所介绍的角色。
此外,你通常也没有那样的预算,可以让每个角色,都把他们该做的文件都做出来。所.以你会省略一些流程。每次有人跑RUP跑的不顺,他们第一个想法就是:『RUP的体系.博大精深,这是多少前人智能的结晶,一定是因为我省略了XX步骤,这次才会走的不.顺利,下回一定要…』
RUP的另一个问题是,它是iterative的开发方式,也就是说,因为项目一定会有变更需求.发生,所以它预期没有办法一次就开发出使用者所要的东西。因此在开发时,会重复来.个好几回。每次都会要求使用者提出评估。
这怎么会是个问题呢?实时取得使用者的响应是一件功德无量的事情啊。问题在于台湾.的使用者通常都有正职在身,他们多半是利用农闲时进行专案的开发。所以他们的时间.非常宝贵,有机会跟你谈一次需求,他就认为这是非常大的恩惠。
在台湾,进行使用者需求访谈,就像在火车站把一个要赶着去搭车的人拦下来进行问卷.调查差不多。一开始,他可能还会基于礼貌,填写问卷。当他需要第四次还是第五次回.答同一张问卷的话,他会觉得你是否听不懂人类所说的语言,还是存心找他麻烦。如果.你开发一个系统,得要使用者评估个好几回的话,God
bless you。
就算使用者对你十分仁慈,没有把你轰出去,采用iterative的做法会有的另外一个问题,.其实是在于你的系统是一个iteration,一个iteration慢慢调整,逐渐形成的。所以到底什.么算是在系统的范围(scope)里面,其实很难界定。所以如果使用者觉得这个iteration的.成品,与他原始需求还有距离,你大概都会被迫再多几个iteration。而这几个iteration,.是收不到钱的。这跟以前的所谓螺线型的开发方式,在台湾遇到的困难是一样的。客户.不会因为你多做了几个循环(cycle),而多给你钱。然而,你会因为多做了几个cycle,投.入超出预期的人力与时间。
事情多做了,可是赚不到钱,这怎么划算呢?要知道,开发项目跟开发产品是不同的。.开发项目,就是要在最少的资源之下,提供给客户一个可以接受的烂货。可以花100万.就让客户愿意结案,绝对不要花101万,让客户拥有一个比较好用的系统。越好用的东.西越难做,出槌的机率也越高,为什么要这样做呢?
除非今天客户是人力外包,花钱买你的人月,去帮他开发。这个时候,当然是尽量选择.可以做得长长久久的方式来开发啰。
所以我觉得应该要以项目的特性来选择项目开发方式。大部分的项目,应该用传统的软.件生命周期开发方式来开发。- (待续)
**使用者或者是客户的信息人员,看不懂相关的文件**
开发项目到底会遇到什么样的客户?其实就像是跟网友见面差不多,还没有看到真人,你永远不知道哪个每天跟你聊天分享心事的超级美女,其实是一个中年男子。就算你运气好,以前已经跟这个使用者接触过,彼此混的很熟,还是有可能会发生变化。
如果以前的项目做得好,这个人有可能升官,所以他就不会做这个专案了;如果以前的项目做得不好,有可能这个人就被列入下次裁员的黑名单里,所以他也不会做这个项目。更不要提有些时候,你是跟一些从来都没有打过交道的人一起开始做一个新的项目。
既然我们在描述的对象是项目,大部分的项目,都是从需求分析开始。使用者便会提出他们的需求,系统分析师听到使用者的需求以后,就会开始把他所收集到的需求写成文件,接着会去跟使用者确认需求是否便是如此。
采用use case driven的OOA(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的倍数。
|