[ZT]软件和需求的实践(林星《IBM DeveloperWorks》)

类别:编程语言 点击:0 评论:0 推荐:

软件和需求的实践(1)
--------------------------------------------------------------------------------
 
林星(转载自《IBM DeveloperWorks》)
从猴子说起
  有这样一个笑话:一个旅客走进硅谷的一家宠物店,浏览展示的宠物。这时,走进一个顾客,对店主说:"我要买一只C猴。"店主点了点头,走到商店一头的兽笼边,抓出一只猴,递给顾客说:"总共5000美元。"顾客付完款,然后带走了他的猴子。这位旅客非常惊讶,走到店主跟前说:"那只猴子也太贵了!"店主说:"那只猴子能用C编程,非常快,代码紧凑高效,所以值那么多钱。"这时,旅客看到了笼子中的另一只猴子,它标价10000美元。于是又问:"那只更贵了!它能做什么?"店主回答:"哦,那是一只C++猴;它会面向对象的编程,会用Visual C++,还懂得一点Java,是非常有用的。"旅客又逛了一会儿,发现了第三只猴子,它独占一个笼子,脖子上的标价是50000美元。旅客倒抽一口气,问道:"那只猴子比其他所有猴子加起来都贵!它究竟能做什么?"店主说:"我们也不知道它究竟能做什么,不过它是做项目顾问出身的。"
  虽然这只是一个笑话,但是有一点是可以肯定的,项目管理是非常重要的,而项目管理的人才又是极为缺乏的。在软件工业发达的国家,大家多少都知道点软件工程规划的重要性。在我们身边的台湾、印度、日本,都不乏因实施软件工程而成功的软件团体,更不用说身为软件大国的美国,已经从较低级的软件实现摆脱出来,进入了设计和营销的境界。 软件首先是一种产品(软件是服务还是产品的问题,向来未有定论),看看世界上制造业的发展历程,就会发现一些很有意思的现象。在本世纪早些的年代,西方国家的制造业经历了规模生产、提高质量等等促进生产力提高的过程。可是由于西方国家的人力资源成本不断的攀升,越来越难降低产品成本,所以西方国家又不可避免的经历了一次将制造业外移的过程(制造业外移的结果是成本大幅下降、国际贸易频繁、接受制造业的国家发展了自身的制造业),而西方国家只留下营销和设计的能力,掌握了产品生产的重点。 同样,IT行业也在经历这种过程:美国将软件外包给印度,硬件外包给台湾。而中国的硬件也在崛起,但是在软件行业,中国和其他国家的差距还是太大了,且不说在软件行业中处于核心地位的操作系统、数据库。即便是应用软件,中国的软件水平也实在低的可怜。在国外制造业刚刚迁移进中国的时候(改革开放),中国的小企业家同样没有任何管理经验、质量意识。但是随着制造业的发展和国外先进思想的进入,中国也诞生了极为出色的全球制造业巨头。而中国的软件行业现在正是处于刚刚有了一点管理思想,但还没有成熟的地步。我们有理由相信,在不久的将来中国也会诞生出出色的全球性软件企业。 憧憬归憧憬,现实的问题还是必须要考虑的。软件这个产品很奇特,软件企业的管理思想同样很奇特。不同于现在企业推崇的各种管理思想,软件企业的管理思想主要是针对项目的管理,确保项目的成功。
项目和需求
  笑话里的猴子对应到项目就是指项目管理人员,这里要引入一个角色的概念(同样的人可以担任多种的角色),通常的项目管理角色包括:项目经理、项目复审员、变更控制经理、企业流程分析师、业务模型设计师、需求分析员、需求复审员、系统分析员…在一个成功的项目里,多种角色职责明确,分工合作,共同完成项目的设计实施。那么这?quot;猴子"在项目中都做了些什么呢?RUP(Rational Unified Process 瑞理统一过程,本文采用了众多的RUP的思想)把一个项目分成10个核心工作流程(Core Workflows)和4个阶段(Phases),并以核心工作流程为Y轴,阶段为X轴建立起一个项目视图(图一)。

  本文将主要对先启阶段做介绍。在先启阶段,需求是重中之中,这里指的需求不仅仅是RUP的一个工作流程(在业务建模下),而是比较广义的概念,包括了RUP的工作流程中的业务建模、需求、一部分的分析、测试计划、配置和变更管理。
需求是根本
  由于忽略需求过程造成的项目返工是恶性的,大量的项目在需求阶段就注定了它的失败。以下是需求过程不科学的典型例子:
  1.开发人员在用户处呆了两三天就埋头开发;
  2.用户告诉开发人员我要开发一个XX系统,但是我很忙,你先开发一个让我看看;
  上面的这两种态度都意味着项目的不成功,应该说上面的开发人员和用户都应该对此负责。需求是开发者和用户交互的一个过程,任何一方的不投入都会导致项目的失败。当然,由于用户不是专业人士,开发者有权利告诉用户应该采用何种态度来对待项目的需求。曾经和几个朋友聊过他们公司开发过的项目,最后得出一个结论,所有最成功的项目都有一个重要的特性:用户非常的支持。 评判一个软件项目成功的标准是看它是否解决了用户的问题,而用户的问题就是体现为用户的需求,需求也就顺理成章的成为项目的成功标准。而需求阶段的一个不慎都有可能导致软件实现阶段的大量返工,而需求的不慎不是说你小心就可以的,因为很多需求是隐性的,连用户都不清楚自己的需求。这时候就需要一种科学的方法来帮助软件组织实施需求过程。 需求是变化的
  大师说:"没有不变的需求,世上的软件都改动过3次以上,唯一一个只改动过两次的软件的拥有者已经死了,死在去修改需求的路上。"
  目前众多的软件项目有什么样的问题呢?早些时候上ERP的企业在企业发展的时候发现原有的ERP系统需要改进,可是要改进或者是更改现有的ERP系统,唯一的方法就是重新开发一个ERP系统。这对于企业来说是笔不小的支出。此时,落后的信息系统就成为制约企业发展的重要因素。是什么原因造成了这种情况呢?主要的因素是传统的系统分析是在假定需求不变的情况下进行的,这样可以把企业的资源配置到最优的程度。可是在现代瞬息万变的社会,一个企业固守旧有模式,势必会在竞争中处于劣势(因此现在也出现了"组件化"的ERP,这是题外话)。既然企业的需求是变化的、不稳定的,那么以变化的需求为基础建立起来的企业信息系统当然也就不稳定了。这时候,有个问题就产生了,前面我们已经说过,需求是项目的根本,既然需求都是不稳定的,那么何以建立起稳定的企业信息系统呢?
  要回答这个问题,首先要比较面向过程和面向对象的开发方法的差别,传统的面向过程的开发方法在前20年大行其道,为中国企业的信息化建设立下了汗马功劳。之所以称为面向过程,是因为开发的焦点集中于过程,开发者集中于以函数为核心的过程,例如前些年很多人试图编写一些通用转账函数来满足银行的需求。面向过程的开发语言包括:Cobol、Pascal、C及C的变形语言。面向对象的概念是在近10年才进入中国的,而它的思想至今也没有真正意义上得到普及。简单的说,面向对象就是面向世界,世界上的任何事物都是对象,因此面向对象是很自然的思想,是符合我们的思维习惯的。面向对象的语言包括了Smalltalk、C++、Java,还有Object Pascal,以及刚刚诞生的C#。
  需求是不稳定的,那么需求之中是不是没有稳定的东西呢?有的,就是对象。世界都是由对象组成的,而对象都是持久的,例如动物、植物已经有相当长的时间。虽然对象也在变化,动物,植物也在不断的进化。但对象在一个相当长的时期内都存在,动植物的存在时间肯定比任何一家企业长久。面向对象的开发方法的精髓就是从企业的不稳定需求中分析出企业的稳定对象,以企业对象为基础来组织需求、构架系统。这样得出的系统就会比传统的系统要稳定得多,因为企业的模式一旦变化,只需要将稳定的企业对象重新组织就行了。这种开发的方法就被称为OOAD(Object Orient Analysis & Design 面向对象的分析和设计),而分析出的企业对象就被称为Common Business Object。
需求是什么
  在RUP中定义了需求工作流程的工作目的:
  1.客户和其他涉众*在系统的工作内容方面达成并保持一致。
  2.使系统开发人员能够更清楚地了解系统需求。
  3.定义系统边界(限定)。
  4.为计划迭代的技术内容提供基础。
  5.为估算开发系统所需成本和时间提供基础。
  6.定义系统的用户界面,重点是用户的需要和目标。
  * 涉众:涉众是所有会受到项目结果重大影响的人。如客户(或客户代表) 用户(或用户代表) 、投资者 、股东 、生产经理 、买方 、设计员 、测试员 、文档编写员等。
  从上面的目的我们可以大致想到需求过程中要做些什么事。事实上,用简单的话来说明需求过程,就是确定系统该做些什么以及该符合什么条件。话虽然简单,实现起来可没有那么容易。所以科学的需求过程有一整套完整的理论、工具、方法来实现。就像任何企业要盈利都必须要有业务和伴随业务的管理一样,需求过程也分为需求分析过程和需求管理过程。企业的业务是盈利性的,需求分析过程在项目中也是产出型的;企业要保证业务的开展就必须要有管理,而需求分析过程也同样离不开需求管理。小企业没有成为体系的管理方法,企业规模小的时候还能够对付,可是企业一大,各种问题都接踵而来,管理上的不足直接导致了业务开展的低效性。同样,需求管理的不足可能可以应付小型的软件项目,可是对于大型的项目,管理的不足就会暴露出来,而直接的后果就是项目的失败。
  插句题外话,很多人认为需求管理的目的是为了控制需求过程,这是没有错,但是在RUP的思想中,更重要的思想是迭代*。迭代的目的是为了发展,为了进化,为了完善。所以RUP中的软件生命周期是分为多个迭代周期的。 * 迭代:迭代包括产生产品发布(稳定、可执行的产品版本)的全部开发活动和要使用该发布必需的所有其他外围元素。所以,在某种程度上,开发迭代是一次完整地经过所有工作流程的过程:(至少包括)需求工作流程、分析设计工作流程、实施工作流程和测试工作流程。实质上,它类似小型的瀑布式项目。
  需求分析过程主要做的事情无非就是获取涉众对系统的要求,可是需求是多变的,而你不可能告诉客户等到他们把一切都固定下来再开发软件。所以需求管理过程做的事情就是保证需求变更的可管理性。
需求的层次
  《软件需求》一书中有对需求层次的详细定义:
  软件需求包括三个不同的层次--业务需求、用户需求和功能需求--也包括非功能需求。业务需求(business requirement)反映了组织机构或客户对系统、产品高层次的目标要求,它们在项目视图与范围文档中予以说明。用户需求(user requirement) 文档描述了用户使用产品必须要完成的任务,这在使用用例(use case)文档或方案脚本(scenario)说明中予以说明。功能需求(functional requirement)定义了开发人员必须实现的软件功能,使得用户能完成他们的任务,从而满足了业务需求。所谓特性(feature)是指逻辑上相关的功能需求的集合,给用户提供处理能力并满足业务需求。软件需求各组成部分之间的关系如图所示:

  对应到RUP的工作流程,业务需求其实是RUP的业务建模流程(Business Modeling),在这个流程中,参与者主要是业务流程分析员(Business-Process Analyst)。主要的目的是对企业目前的业务流程进行评估,并根据要进行的项目,确定进行何种程度的业务建模(你要做一个ERP项目就意味着你必须优化业务流程,而上一个部门级MIS项目就没有必要用牛刀了)。然后你会得到一个叫做业务前景(Business Vision)的东西,其实就是项目成功后会是个什么样子,并在涉众范围内达成一致。业务需求层次需要投入的精力视具体项目而定,而业务需求的确定对之后的用户需求和功能需求起了限定作用,业务需求就是需求过程的宪法,任何需求不得与之相违背。
  到了用户需求层次上(RUP的需求工作流程),重心就转移到如何收集用户的需求上,即确定角色和角色的用例,需求分析是很难的,因为很多需求是隐性的,很难获取,更难保证需求完整,而需求又是易变的。一般来说,在过去作需求分析的时候,更多依靠的是阅读企业的文件,但是企业的文件往往有局限性,例如落后于当前的业务,不够明确,依赖于管理水平的高低,所以后来获取需求的方法逐渐倾向组织访谈会(Interview)。
  功能需求依赖于用户需求,可以说是用户需求在系统上的一个映射(Mapping)。开发者思考的角度从用户转移到开发者。在这个层次上,为用户做一个软件原型是一个很不错的主意。直到现在,用户对软件还是没有一个实实在在的概念,如果你给用户一个原型,用户就会说,"哦,我的XX系统原来就是这样的。"这就避免了用户在软件开发完成后才看到软件所带来的一些风险。是否有必要采用快速原型开发法和原型应开发到何种地步取决于具体的项目,很多时候,用一些非正规的方法来生成原型:如果你要开发一个WEB系统,让你的美工做几个页面给用户看看,如果你做一个C/S系统,做一个界面给用户,都已经足够用了,甚至你完全可以在黑板上画一画你将来的软件的面貌都可以。用户大都是比较友善的,不要把问题想的过于复杂。 需求的标准
  讨论软件需求的文章有很多,对于需求的标准也不尽相同,但是在思想上是相同,都是为了保证项目的顺利进行。这里我总结一些比较通用的标准,可能并不完善,但你只要能保证做到这几点,你的项目就不容易失败:明确(Clear)、完整(Complete)、一致(Consistent)、可测试(Testable),此外还有其他的概念,如可跟踪、可修改等等。
  明确:目前大多数的需求分析采用的仍然是自然语言(因为如果采用形式化语言的话,和用户的沟通将成为一个大问题,这意味着客户在开发软件之前必须先进行形式化语言培训,这是不现实的)。自然语言对需求分析最大的弊病就是它的二义性。所以我们不得不对需求分析中采用的语言做某些限制。例如尽量采用主语+动作的简单表达方式。说白了,需求分析中的描述让人看上去像是刚学习写作的小孩子就对了,千万不要采用疑问句、修饰这些华丽的表达方式。
  除了语言的二义性之外,注意不要使用行话,就是计算机术语。需求分析最重要的是和用户沟通,可是用户多半不是计算机的专业人士,如果在需求分析中使用了行话,就会造成用户理解上的困难。
  打个比方,如果你要做一个银行的信用卡系统,你就可以这样描述软件需求:银行的卡部管理信用卡,每张信用卡只属于一个帐户。信用卡有卡号、余额。一张信用卡有多笔的交易记录。
  完整:再也没有什么比软件开发接近完成时才发现遗漏了一项需求更糟的事情了。需求的完整性是非常非常重要的,想象一下遗漏需求而不得不返工,这简直就是恶梦。可是令人遗憾的是,需求的遗漏是很经常发生的事情,不仅仅是你的问题,更多的问题发生在用户那里,他们不知道该做些什么。要做到需求的完整性是很艰难的一件事情,它涉及到需求分析过程的各方各面,贯穿了整个过程,从最初的计划制定到最后的需求评审。
  一致:一致性也是一个比较大的概念,很难用几句话讲清楚。简单的来说,就是用户需求必须和业务需求一致,功能需求必须和用户需求一致。严格的遵守不同层次间的一致性关系,就可以保证最后开发出来的软件系统不会偏离最初的实现目标。在实现过程中,我们还必须把一致性关系细化。比如说用户需求不能超出先前指定的范围。
  可测试:大家觉得一个项目的测试从什么时候开始呢?有人说从编码完成后开始。更清楚一点的说是编码的时候同时进行单元测试,编码完成后进行系统测试。这些都没有错。但是实际上测试是从需求分析过程就开始了。需求分析是测试计划的输入和参照。这就要求需求分析是可测试的。什么是可测试呢?quot;我们要用新的系统完成报表自动化处理",你觉得这个需求是可测试的吗?当然不是,报表包括哪些?自动化处理的标准是什么?这些在需求中都没有说明。因此这项需求是无法测试的,就是不具有可测试性。说到这里,大家可能就会明白之前的需求的几项标准都是为了保证需求的可测试性的。事实就是这样,只有系统的所有需求是可以被测试的,才能够保证软件始终围绕着用户的需要,保证软件系统是成功的。

软件和需求的实践(2)
--------------------------------------------------------------------------------
 
林星(转载自《IBM DeveloperWorks》)
煮鸡蛋的启示
  有个英国人学煮鸡蛋,开始,他把鸡蛋放到开水里煮时总会炸裂。他为此想了各种方法,并找到了一个解决方案:在鸡蛋上打个孔。但在鸡蛋上打孔带来了另一个问题:孔打小了,鸡蛋还会裂;孔打大了,蛋清会在它凝固以前流出来。于是,这个英国人给一批鸡蛋分别打了各种不同孔径的洞,并记录下每个鸡蛋孔径的大小。通过这一方法,他找到了一个最合适的大小──既避免了炸裂,又保证蛋清不会流出来。这时,虽然煮鸡蛋炸裂的问题解决了,但这个英国人仍然不知道煮多长时间才能把鸡蛋煮熟。为了解决这个问题,他又开始尝试煮不同时间的结果,并从中找出最佳的时间长度。最后,他终于找到了一个放之四海而皆准的煮鸡蛋的方法。这个案例对很多中国人来说是个可笑的例子。因为聪明的中国人早就知道把鸡蛋放在水中与之一起加热至鸡蛋浮起来就可以了。 从煮鸡蛋这样一个小小的事件上,中国人和英国人体现了两种完全不同的思维习惯──中国人凭借他的聪明直奔结果,而英国人却仔细地把每一个过程细化到最简单,然后按部就班地执行。(管理软件的发展之路 洪奇)
  聪明的中国人虽然拥有四大发明,但是对于现代的管理思想,中国人一直没有领会到真谛所在。无论是哪一种的管理方法,过程能力都是特别重要的,虽然生产一件产品的相关人员有千千万万,但是生产出来的产品却只有一种。这种能力并不是从天上掉下来的,是通过制定极为详尽的生产过程规定得到的。在中国接受了ISO的思想之后,这种能力也在国内的制造业中逐渐体现出来。但是在软件行业中,拥有这种过程能力的软件组织仍然是少的可怜,大多数的软件组织奉行的还是一种在八九十年代的个人英雄主义,开发软件单靠个人的力量,能力强的程序员能够成功的完成软件,能力差的则失败。大多数的软件组织中,少数人掌握着代码,他们就是一切,如果他们因为私人原因离开所在的组织,手上的代码则是他们的资本,原有的组织将受到沉重的打击。 中国人热衷于结果,2001年的热点在CMM上,现在还很难说CMM中是不是有一定的泡沫存在,但是可以肯定的一点是,CMM之进入中国软件组织为中国软件工业的发展开创了一个新的时代。中国的软件工业将逐渐摆脱原来的作坊式开发,进入软件工业时代。之所以用软件工业而不用软件产业的原因是希望软件产品能够像工业革命那样进入大规模生产,降低价格的时代。
  可惜,软件毕竟不同于工业产品,在工业化生产的过程中,质量检测的一个方法是在产品出厂前设置质量检测,通过质量检测的出厂,否则回收。这种方法无法适用于软件。后来,质量检测逐渐倾向于生产过程,在过程中监测产品质量。这种方法比起前一种方法进步了很多,但是它需要对生产全过程进行追踪。这种方法的思想正是软件过程的质量保证的精髓所在。
  在《软件工程》一书中,作者把软件工程分成三层,最底层是软件过程,上一层是软件方法,最高层是CASE工具。软件过程中充满了各种各样的方法论,从需求到最后的维护。要在自己软件组织中应用所有的方法是不可能的。所以你如果看完软件工程的文章后有一种要在明天就实现现代化的冲动的话,打消那种念头,从零做起。
需求过程
  需求过程是软件过程的一个很重要的部分。软件项目中百分之四十至百分之六十的问题都是在需求分析阶段埋下的"祸根"(Leffingwell 1997)。我在自己的身边也做过一次小范围的调查,结果显示成功的项目都离不开成功的需求(一个重要的标志是用户的支持)。
  需求过程,也有叫做需求工程和需求阶段的,包括了需求开发和需求管理,他们所涉及到的具体工作流如图所示:
 
  需求分析的这个过程,我们可以称它为需求工程,也有叫做需求过程和需求阶段的。需求工程包括了需求开发和需求管理,他们所涉及到的具体工作流如上图标明的那样。
需求过程和CMM
  软件工程协会 (SEI Software Engineering Institude) 的能力成熟度模型 (CMM Capability Maturity Model) 提供了一种著名的软件过程成熟度基准。CMM 已经成为了许多领域内的流行工具,用于评估一个组织的软件过程的成熟程度。(更详细的定义和说明请参看《CMM白皮书》)。
  CMM中和需求有关系的是第2级(可重复级)中对需求管理的要求和第3级(已定义级)中对需求跟踪能力的要求。必须指出的是,CMM只是规定成熟的软件组织应该达到的关键能力,是一种改进软件过程的策略,对具体的方法并没有做限制规定。所以CMM中没有涉及到需求开发的内容。
需求过程和软件生命周期模型
  任何软件都是从最模糊的概念开始的:为某个公司设计办公的流程处理;设计一种商务信函打印系统并投放市场。这个概念是不清晰的,但却是最高层的业务需求的原型。这个概念都会伴随着一个目的,例如在一个"银行押汇系统" 的目的是提高工作的效率。这个目的将会成为系统的核心思想,系统成败的评判标准。99年政府部门上了大量的OA系统,学过一点Lotus Notes的人都发了财(IBM更不用说了),但是更普遍的情况是,许多的政府部门原有的处理模式并没有变化,反而又加上了自动化处理的一套流程。提高工作效率的初衷却导致了完全不同的结果。这样的软件究竟是不是成功的呢?
  从概念提出的那一刻开始,软件产品就进入了软件生命周期。在经历需求、分析、设计、实现、部署后,软件将被使用并进入维护阶段,直到最后由于缺少维护费用而逐渐消亡。这样的一个过程,称为"生命周期模型"(Life Cycle Model)。
  典型的几种生命周期模型包括瀑布模型、快速原型模型、迭代模型。瀑布模型(Waterfall Model)首先由Royce提出。该模型由于酷似瀑布闻名。在该模型中,首先确定需求,并接受客户和SQA小组的验证。然后拟定规格说明,同样通过验证后,进入计划阶段…可以看出,瀑布模型中至关重要的一点是只有当一个阶段的文档已经编制好并获得SQA小组的认可才可以进入下一个阶段。这样,瀑布模型通过强制性的要求提供规约文档来确保每个阶段都能很好的完成任务。但是实际上往往难以办到,因为整个的模型几乎都是以文档驱动的,这对于非专业的用户来说是难以阅读和理解的。想象一下,你去买衣服的时候,售货员给你出示的是一本厚厚的服装规格说明,你会有什么样的感触。虽然瀑布模型有很多很好的思想可以借鉴,但是在过程能力上有天生的缺陷。
  迭代式模型是RUP推荐的周期模型,也是我们在这个系列文章讨论的基础。在RUP中,迭代被定义为:迭代包括产生产品发布(稳定、可执行的产品版本)的全部开发活动和要使用该发布必需的所有其他外围元素。所以,在某种程度上,开发迭代是一次完整地经过所有工作流程的过程:(至少包括)需求工作流程、分析设计工作流程、实施工作流程和测试工作流程。实质上,它类似小型的瀑布式项目。RUP认为,所有的阶段(需求及其它)都可以细分为迭代。每一次的迭代都会产生一个可以发布的产品,这个产品是最终产品的一个子集。迭代的思想如上图所示。
  迭代和瀑布的最大的差别就在于风险的暴露时间上?quot;任何项目都会涉及到一定的风险。如果能在生命周期中尽早确保避免了风险,那么您的计划自然会更趋精确。有许多风险直到已准备集成系统时才被发现。不管开发团队经验如何,都绝不可能预知所有的风险。"(RUP)二者的区别如下图所示:

  由于瀑布模型的特点(文档是主体),很多的问题在最后才会暴露出来,为了解决这些问题的风险是巨大的。"在迭代式生命周期中,您需要根据主要风险列表选择要在迭代中开发的新的增量内容。每次迭代完成时都会生成一个经过测试的可执行文件,这样就可以核实是否已经降低了目标风险。"(RUP)   快速原型(Rapid Prototype)模型是我喜欢采用的另一种模型。快速原型模型在功能上等价于产品的一个子集。注意,这里说的是功能上。瀑布模型的缺点就在于不够直观,快速原型法就解决了这个问题。一般来说,根据客户的需要在很短的时间内解决用户最迫切需要,完成一个可以演示的产品。这个产品只是实现部分的功能(最重要的)。它最重要的目的是为了确定用户的真正需求。在我的经验中,这种方法非常的有效,原先对计算机没有丝毫概念的用户在你的原型面前往往口若悬河,有些观点让你都觉得非常的吃惊。在得到用户的需求之后,原型将被抛弃。因为原型开发的速度很快,设计方面是几乎没有考虑的,如果保留原型的话,在随后的开发中会为此付出极大的代价。至于保留原型方面,也是有一种叫做增量模型是这么做的,但这种模型并不为大家所接受,不在我们的讨论之内。br>   上述的模型中都有自己独特的思想,其实现在的软件组织中很少说标准的采用那一种模型的。模型和实用还是有很大的区别的。
  软件生命周期模型的发展实际上是体现了软件工程理论的发展。在最早的时候,软件的生命周期处于无序、混乱的情况。一些人为了能够控制软件的开发过程,就把软件开发严格的区分为多个不同的阶段,并在阶段间加上严格的审查。这就是瀑布模型产生的起因。瀑布模型体现了人们对软件过程的一个希望:严格控制、确保质量。可惜的是,现实往往是残酷的。瀑布模型根本达不到这个过高的要求,因为软件的过程往往难于预测。反而导致了其它的负面影响,例如大量的文档、繁琐的审批。因此人们就开始尝试着用其它的方法来改进或替代瀑布方法。例如把过程细分来增加过程的可预测性。
RUP和XP
  RUP是瑞理(Rational)公司经过不断的实践和理论总结发展出来的一套软件开发统一过程(Unified Process)的思想集和方法集。还记得我们在第一章的那张图吗,那就是RUP的核心图。RUP把软件开发过程分成4个阶段(Phases)和9个核心工作流程(Core Workflows),通过一次次的迭代(Iterations),完成整个的软件生命周期。RUP可以把软件开发过程分到非常细小的单位,每个角色(Workers)都参与活动(Activities),产生出工件(Artifacts)。由于精密的控制,所以RUP可以胜任于超大型的项目开发。虽然RUP定义了很多微小的活动,但是由于CASE工具的使用,它并不会像传统瀑布模型那样陷入文档的海洋中。RUP通过适当的剪裁,同样可以试用于较小型的项目。
  XP(Extreme Programming),极端编程。不过好像并没有这样翻译的(听上去像是计算机领域的极右组织)。它是由Kent Beck大师提出的。大师在经历传统软件开发的痛苦之后,希望能够找到一种优秀的软件开发方法。大师总结了大量的软件的成功和失败的因素之后,提出了改进软件开发方法的四个要素:沟通(communication)、简单化(simplicity)、反馈(feedback)、勇气(courage)。这形成了XP的核心价值观。在经历了数年的发展,XP在软件开发的各方面都发展出了众多的方法来支持软件开发。
  制定了大量的规则的RUP方法被称为重量级(Heavyweight)的方法,而像XP这样只制定少量的规则来规范行为的方法被称为轻量级(Lightweight)的方法(实际上,现在有一种倾向称这种方法为Agile方法的)。近来,也看到一些文章在讨论两种方法孰优孰劣。例如:XP兴起,RUP不适合中国国情等。我想,这和以前大家讨论C++和Java谁好的性质是一样的。方法都有两面性,只有最适合的方法,没有最好的方法。我在实践中也感觉到,国外的理论确实不能照搬于中国,毕竟中国人的人文环境和国外相差太大了。不过,RUP不适合的,我想,XP也未必会适合。如果说,有人把RUP的一整套东西生搬硬套,导致了最后项目失败的结果的话。这种行为无异于刻舟求剑。
  在我看来,RUP就像是一个软件工程思想和方法的大百科全书。在其中,你可以看到诸子百家的论调,可以了解软件工程的整个演化过程。RUP是很值得你投入大量时间去研究的东西的。一个武林高手走进了少林寺的藏经阁,你可以想想,那是一种什么景象。XP,更强调团队的充分交流,最大限度的发挥人的创造力。它并不制定大量的规则来限制人的行动(必要的规范是必须遵守的),开发的团队中的每一个人都能自由的发挥想象力,毕竟,软件是创造性的劳动(这听起来像是共产主义实现了一般)。至少,国内的公司都应该学习XP的一条规则:一周只工作40小时。相比较之下,RUP比较适合大企业、大项目,因为大的团队往往需要法制;XP适合于小团队,比较能够发挥小团队的创造力。但是在实际中,也有例外的情况。例如XP方法的第一个项目就是克莱斯勒公司的一个名为C3的大型项目。
  在现实中,RUP和XP应用于目前中国的软件企业都有一定的难度。有一些来信来问我,RUP真的适合中国的企业吗?我会直接告诉他们肯定不适合。对RUP这个庞然大物来说,很难去评定它的优和劣。关键在于它裁减以后的样子。我看到过一篇文章,是讨论如何将RUP裁减适合XP思想的方法的。所以RUP的使用要很小心。一个高明的铁匠用铁锤可能可以打出一把好兵器,如果是普通人搞不好就会砸到脚。
  提升企业的内力值并不是一两天的事情,这需要长期的投入和锲而不舍的努力。大刀阔斧的引进一整套流程并不是不行,只是猛药伤身这个道理大家也应该懂得。很多年轻有为的软件界人士希望在自己公司中引入先进的开发理念,但是在真正实施时,往往会被碰得头破血流,也有这方面的原因存在。对他们,我是很佩服的。 


 
需求的实践(3)
Customer Oriented,而不是Program Oriented
--------------------------------------------------------------------------------
 
来自:IBM China 作者:林星 [2003/04/02]
软件开发人员总是在困惑为什么软件分明是按照需求做出来的,可是客户为什么仍然不满意。客户总是在困惑为什么软件和自己想要的差距会那么大。这究竟是怎么回事?如何才能把开发人员和客户之间的沟壑填平?本文作为这个关于需求的软件工程专栏的第三篇,将向您介绍这个把客户和开发人员联系在一起的工具――UML(统一建模语言,Unified Modeling Language)。
一个软件系统的开发过程说到底就是由客户提出需求,再由开发人员将之翻译成机器能够理解的语言,构建成系统,交付给客户使用。在客户看到软件的时候,客户通常会说一句话:"哦,那正是我所说的,但那不是我想要的。" 即使是开发人员异常的尽责,花费大量的时间了解客户需求,依然避免不了出现上述的客户抱怨。更何况开发人员通常都想当然的认为自己已经了解了需求,并喜欢按照自己的想法给软件加入一些新特性(feature)。在这样的情况下,用户的"真正"的需求就更加得不到保障了。
出现了什么问题?因为大部分的软件开发工作都是Program Oriented,而不是Customer Oriented。开发人员认为自己已经了解了客户的需求;客户表达不出或是表达不全自己的需求;开发人员抱怨客户经常修改需求;客户不明白软件开发为什么有如此多的限制…。所有这些,都是Program Oriented的软件开发模式避免不了的弊病。
归根结底,这些问题都是由于客户和开发人员的立场不同而导致的。
所以呢,在客户和开发人员之间,缺少一种东西来把他们联系在一起。因此,众多的方法学,都把这个问题视为重中之重。
1. UML
UML(统一建模语言,Unified Modeling Language)是一种面向对象的建模语言。在软件工业化方面做出了杰出的贡献。被OMG(Object Management Group)采纳为业界标准。
UML就是解决上面这个问题的一个相当有代表性的例子。UML的实质,就是一种沟通方法,就象是英语能够解决把世界各地的人交流的问题一样。
2. UML起源
公认的面向对象建模语言出现于70年代中期。1989年到1994年是建模语言的战国时期,其数量从不到十种增加到了五十多种。虽然有利于学术的发展,但是对于最终用户来说,了解众多的建模语言是一件非常没有必要的事。在建模语言的战国时期出现了三个强者:Grady Booch,James Rumbaugh和Ivar Jacobson(人称"The Three Amigos"),以及他们的方法:Booch 1993、OOSE和OMT-2。
Booch是面向对象方法最早的倡导者之一,他提出了面向对象软件工程的概念。Booch 1993比较适合于系统的设计和构造;Rumbaugh提出了面向对象的建模技术(OMT)方法,采用了面向对象的概念,并引入各种独立于语言的表示符。这种方法用对象模型、动态模型、功能模型和用例模型。 OMT-2特别适用于分析和描述以数据为中心的信息系统;Jacobson于1994年提出了OOSE方法,其最大特点是面向用例(Use-Case),并在用例的描述中引入了外部角色的概念。用例的概念是精确描述需求的重要武器,但用例贯穿于整个开发过程,包括对系统的测试和验证。OOSE比较适合支持商业工程和需求分析。
天下大势,分久必合。Grady Booch,James Rumbaugh和Ivar Jacobson三个人的方法各有所长,而用户有希望能够有一种标准出现,结束混乱的百家争鸣的现状。1994年10月,Grady Booch和Jim Rumbaugh开始致力于这一工作。他们首先将Booch9 3和OMT-2 统一起来,并于1995年10月发布了第一个公开版本,称之为统一方法UM 0.8(Un ified Method)。1995年秋,OOSE 的创始人Ivar Jacobson加盟到这一工作。经过Booch、Rumbaugh和Jacobson三人的共同努力,于1996年6月和10月分别发布了两个新的版本,即UML 0.9和UML 0.91,并将UM重新命名为UML(Unified Modeling Language)。1996年,一些机构将UML作为其商业策略已日趋明显。UML的开发者得到了来自公众的正面反应,并倡议成立了UML成员协会,以完善、加强和促进UML的定义工作。当时的成员有DEC、HP、I-Logix、 Itellicorp、 IBM、ICON Computing、MCI Systemhouse、Microsoft、Oracle、Rational Software、TI以及Unisys。这一机构对UML 1.0(1997年1月)及UML 1.1(1997年11月17日)的定义和发布起了重要的促进作用。
UML是集合了众家之长的建模语言,从诞生的那一天开始,就经过了不断的验证和修改,它着重强调的是一种标准的建模思想,但它并不是一种标准建模过程,对于不同的软件企业来说,建模的过程是不同的。UML并没有特定的平台,与具体的实现无关。它是一种图形化的面向对象建模语言。UML通过不同的图形表示来捕捉系统静态结构和动态行为的信息,建立起对象模型。不同的图形是从不同的角度来看待系统。由于UML的独立性,所以它可以通过专用的工具转化成具体的编程语言,或是从编程语言代码转回UML,这叫做"逆向工程"。
3. UML是什么
UML的概念包括了UML语义(Semantics)和UML表示符(Notation)两个部分,UML语义定义了结构(Structural)模型和行为(Behavioral)模型。结构模型(又称为静态模型)强调系统的对象结构,如对象的类(Classes)、接口(Interfaces)、属性(Attributes)和关系(Relations);行为模型(动态模型)关注的是系统对象的行为动作,如对象的方法(Methods)、交互(Interactions)、协作(Collaborations)和状态(State Histories)。以此为基础,UML为UML表示符提供了完整的语义定义。UML的表示符包括了下面的几种主要的图:类图(Class Diagram),用例图(Use Case Diagram),顺序图(Sequence Diagram),协作图(Collaboration Diagram),状态图(State Diagram),活动图(Activity Diagram),部署图(Deployment Diagram)语义由于我们的讨论重点并不是UML语言,我们只是简单的介绍UML的实际应用,如果大家对UML有兴趣,可以参看《UML1.3白皮书》。
4. 用例图和用例
用例图(Use Case Diagram)是UML中最简单也是最复杂的一种图。说它简单,是因为采用了面向对象的思想,又是基于用户视角的,绘制非常容易,简单的图形表示让人一看就懂。说它复杂是因为用例图往往不容易控制,要么过于复杂,要么过于简单。一个系统的用例图太泛不行,太精不行,太多不行,太少也不行。用例的控制可以算是一门艺术。突然想起当年我刚刚接触UML的时候,对用例不屑一顾,认为是UML中最无用的一种图,现在每每想到不禁感慨自己的愚蠢。
Use case diagrams show actors and use cases together with their relationships.『OMG-UML V1.3』
用例图表示了角色和用例以及它们之间的关系。
A use case is a kind of classifier representing a coherent unit of functionality provided by a system, a subsystem, or a class as manifested by sequences of messages exchanged among the system and one or more outside interactors (called actors) together with actions performed by the system. 『OMG-UML V1.3』
用例描述了系统,子系统和类的一致的功能集合,表现为系统和一个或多个外部交互者(角色)的消息交互动作序列。
有点复杂是吗,就是角色(用户或外部系统)和系统(要设计的系统)的一个交互,为了实现一个目的(Goal),这个目的的描述通常是一个谓词短语,例如,开立信用证,给客户回单等。用例图则图形化的表示了这种关系。
一个具体的用例图可能是这样的:

5. 用例和需求,用例和过程
可以说,之前说的所有的东西都是为了能够导出用例在需求中的作用。用例是从用户的角度看待系统,而不是基于程序员的角度。这样的话,用例驱动的系统能够真正做到以用户为中心,用户的任何需求都能够在系统开发链中完整的体现。用户和程序员间通过用例沟通,避免了牛头马嘴的尴尬局面。
从前,系统开发者总是通过情节来获取需求,是问用户希望系统为他做什么。在可爱的Jacobson发明了用例的概念之后,需求获取就变成问用户要利用系统做什么。这是立场不同导致的结果。用户通常并不关心系统是如何实现的(也有少数可爱的技术狂是例外)。对他们来说,更重要的是要达到他的目的。相反的,大部分的程序员的工作习惯就是考虑计算机应该如何实现用户的要求。所幸的是,用例方法能够调和双方的矛盾,因为虽然用例是来源于用户,服务于用户,但是它同样可以用于开发的流程。当系统的开发过程都是基于用例的,用用例获取需求,用用例设计,用用例编码,用用例测试的时候。这个开发过程就是用例驱动的。
在具体的需求过程中,有大的用例(业务用例),也有小的用例。主要是由于用例的范围决定的。用例像是一个黑盒,它没有包括任何和实现有关或是内部的一些信息。它很容易就被用户(也包括开发者)所理解(简单的谓词短语)。如果用例不足以表达足够的信息来支持系统的开发,就有必要把用例黑盒打开,审视其内部的结构,找出黑盒内部的Actor和Use Case。就这样通过不断的打开黑盒,分析黑盒,再打开新的黑盒。直到整个系统可以被清晰的了解为止。
用例是重要的,用例图只是用例的表达方式,其实用例的表达不仅仅是用例图,还有很多方式,我们在下面会具体讲到。
6. 使用用例的误区
上面曾经花了一些篇幅来说明用例的简单和复杂的关系。在很多介绍UML的书中都会首先介绍用例图,并会用一些近乎完美的例子来说明用例图。可是在实际的使用过程中,都会有很多实际的问题。我咨询过很多使用UML的朋友,发现或多或少都存在问题。
用例的发明者Ivar Jacobson 曾经说过,Ericsson花掉了上千万元去研究建立Use Case模式的过程(process) ﹐现在他任职的Rational公司也花掉不少钱研究开发过程的问题。大师花了数十年心血建立起来的理论体系并不是那么容易的。用例决不仅仅是定义Actor、Use Case、Association那么简单。用例需要在很多的细节方面都做足功夫。我曾经看过一个软件企业推行Use Case图,但是在花费心血画出了几十张项目的用例图后,设计编码阶段却回到了从前的开发流程。
用例的使用绝不仅仅是画用例图,用例也不是软件团体一步登天的捷径。用例贵在思想,在软件团体中引入用例并能够和团体很好的融合,是一个渐进的过程。因为在软件工程领域应用用例思想涉及到的内容方方面面。即使是用例图的编号也是大有讲究。对于一个没有OO实践经验的软件团体,从事这样的作业,需要大量的工作,可以说是"百业待举"。如果没有长期的积累和探索,何来用例和软件团体的融合呢?
7. 用例的观点
为什么说用例是有效的呢?在软件开发的过程中,大部分问题的产生都是由于沟通的不畅。设计者和用户沟通不畅,设计者和实现者的沟通不畅。软件开发就是踢足球。教练、前锋、中场、后卫各顾各的,相互之间形成断层,怎么能赢球呢?上面提到的一些应用OO用例思想失败的例子也表明,如果开发团队有人排斥用例思想的话,项目是不会成功的。
用过Rose的人都知道,在Rose的界面中,有四种视图(View):用例视图(Use Case View),逻辑视图(Logical View),组件视图(Component View),部署视图(Deployment View)。这个思路源于Kruchten大师提出来的4+1的观点模式。其描述了系统开发工作的参与者﹕使用者(end users) 、程序员(programmers) 、系统整合师(system integrators)、以及系统工程师(system engineers)等5 种人员心中所关切的焦点与看法。

为了能够把4种人不同的观点统一起来,Kruchten大师提出了一个情节(Scenarios)观点(这个词翻译的不好,如果有谁有更好的翻译,请更正)。这个观点其实就是用例观点(Use Case View)。在用例观点的统一下,保证这四种观点能够相互协作,共同营造一种良好的开发氛围,实现软件项目的成功。
那么,应该如何营造一种和谐的气氛呢?还记得在介绍UML语言的时候我们谈过UML中的几种图吗。这几种图都不是孤立的。在画出一份用例图后,通常都会用顺序图和状态图来规定用例图的规格,这些都是Rose中的用例视图。在用例图中,我们可以分析出基本的类,并将类组织成包,并将其分配到系统的三层结构中,这是Rose中的逻辑视图。在写出基本类之后,我们还可以将类组织成组件(针对特定的架构,如J2EE或COM),这是Rose中的组件视图。把组件部署实现,就是Rose中的部署视图所关心的。(需要指出的是,Rose中的视图与Kruchten大师的4+1观点有些许出入,Rose中的组件视图相当于Kruchten大师的Development观点和Process观点。)
(注:这里的View对应的有两种说法:视图和观点。视图是比较正式的说法,但是我觉得在通常得用语中,大多采用观点的说法。所以这里的观点和视图表述的是同一个意思。)
这里谈到用例的观点主要是要让大家了解为什么会有用例的产生,以及在软件开发中不同的人看待问题有不同的角度。
8. 用例的不足
用例的出现虽然能够解决很大一部分问题,但是它并不是万能的。
The first is the matter of how difficult it is to get a UML-like design into a state that it can be handed over to programmers. The problem with a UML-like design is that it can look very good on paper, yet be seriously flawed when you actually have to program the thing。(Fowler 2001)
首先是把像UML那样的设计图交给程序员来实现是一件极为困难的事情。问题的关键在于那种设计看上去不错,可你打算编程来实现它的时候就出现了问题。
不但是分析员和程序员之间的沟通存在问题,客户和分析员之间的隔阂更大。客户对于用例的观点仍然不能够接受,这仍然需要开发人员作出不懈的努力来调和这一矛盾。
由于软件工程最早提出是根据建筑方面的理论,所以很自然的就会把软件工程和土木工程做一个比较。在土木工程中,设计图和模型制定出来来需要严格的执行。可是:
The models that civil engineers use are based on many years of practice that are enshrined in engineering codes. Furthermore the key issues, such as the way forces play in the design, are amenable to mathematical analysis. The only checking we can do of UML-like diagrams is peer review. (Fowler 2001)
土木工程师使用的模型建立在多年实践的基础上,它们用土木工程的专用语言来描述。而且主要的问题在于,通常这种设计需要符合数学原理。而我们对UML之类的图表唯一能做的就是同级检查。
看到问题所在了吧。单纯的凭借没有完善理论支撑的设计图就轻率的决定这个软件的设计是及其危险的。不止一次的经验告诉我,一开始写出的用例在项目结束时一看往往会吓一大跳:设计和实现已经完全脱节了。其中主要的代沟有两个:客户和开发人员之间,分析员和程序员之间。我们这里的重点在于客户和开发人员之间的需求部分。
需求的问题单单由UML语言来解决是不现实的,且不说国外的软件环境那么好的情况下,客户对于UML仍然不理解。国内的情况要糟糕的多,大多数的客户并没有计算机方面的基础知识,对于他们来说,只有一点:"花钱买东西,天经地义。"在这样的观点下,软件的开发过程就很难得到客户的支持。所以这也是国内ERP项目鲜有成功范例的一个重要原因。
这时候,讨论的问题已经不是局限在技术层面了,主要的焦点已经转移到了管理、营销、谈判技巧等方面了。UML的成功也是需要这个大前提在的。McConnell建议在一个大的项目中,编码和单元测试的开销占整个项目开销的15%。而其中有很大一部分的时间都会花在BPA(企业流程分析)和BPR(企业流程再造)上面。因为有很多企业在实施电子化之前管理都不规范,以人治为主。对于软件而言,不论其中的设计多么的成功,如果没有各个环节输入的准确来保证,那结果是可想而知的。我的一个朋友开发过一套连锁店管理的软件,可是系统运行以来,会计帐从未平过。其中主要的问题就是各个结点的输入不规范。这种问题已经不是计算机能够解决的了。说到这里,有一个笑话,有一个特定行业的企业要开发一个管理软件,于是我就给企业的负责人分析他的流程,突然他很惊讶的看着我:"你是我们这个行业的吗,怎么比我还熟。"其实,我只是以逻辑的观点来分析他们流程,把一些漏洞给堵住。关于业务建模方面的知识,在接下去的文章中还会有大规模的篇幅,这里就不罗嗦了。
所以呢,作需求分析,往往技术并不是最重要的。
9. 迭代式的需求分析
软件工程不断的向前发展,其中的一些新兴的方法论中的佼佼者就是XP。(关于XP的介绍请参看我的上一篇文章)。XP对需求的影响在于:开发方和客户方已经不再是客户关系,而是战略合作关系。客户将作为领域专家参加整个开发过程,并提供现场(on-site)指导。
XP大概的流程是:领域专家组(包括开发方和客户方)将会提出需要开发的功能,体现为素材卡片(Story Card)。项目经理配合将素材卡片分配到每个迭代周期。各个素材卡片都会有一个小型的开发团队(由分析人员、开发人员、品保人员组成)来负责。每次迭代周期都会得到一个可发布、可供客户使用的产品。通过把整个项目划分为多个迭代周期,可以:
较短的迭代周期容易预测,资源分配计划可以做的非常细致;
给客户提供了一种实际使用的感觉,并且客户可以通过实际使用发现自己潜在的需求,提交需求,在随后的迭代周期中安排实现;
不断的有最终产品推出,团队能够保持较高的士气;
不同的小组可以同时处于不同的迭代周期中,降低了传统开发方法中常常出现瓶颈的风险;
不可否认,XP作为新生代的方法,有它的优势所在。可是要指出的是,在中国,能够采用XP方法企业可以说是屈指可数。这个问题大家经常都可以看到评论,这里就不罗嗦了。不过,有一种开发环境,还是有天然的使用XP方法的优势的。就是内部开发。例如很多的大型企业、银行、事业单位都有自己的软件开发部门。这种和客户关系特别亲密,使用XP方法就有他的优势。只是,目前影响这种开发方式的主要原因,却是在体制上的。
10. 小节
平心而论,UML还是不错的,绝对值得我们花时间来学习。尤其是随着大环境的逐步改善,UML将很有可能成为统一建模语言,就像它的名称那样。需求要是Customer Oriented的,这点知易行难。要采用先进的方法,更非朝夕之功。


 
需求的实践(4)
业务建模时期(上)
--------------------------------------------------------------------------------
 
来自:IBM China 作者:林星 [2003/04/02]
在大规模的需求调研展开之前,有一个重要的工作要做。这项工作在项目中所占的时间跨度非常的小,但是却有非常重要的意义。不同的人、不同的方法对这项工作有不同的描述,在我们的文章中,根据UP的思想,称之为"业务建模"。
所有的项目都有业务建模时期
1. 业务建模是什么
业务建模(Business Modeling),业务建模是一个复杂的过程,对其下一个准确的定义是困难的事情。在RUP的词汇表中将其解释为:
"包含您可用来对业务进行可视化建模的所有建模方法。这些是您可用于执行业务工程的方法的子集。"
从定义中可以看出,它是一种建模方法的集合,目的是对业务进行建模。这方面的工作可能包括了对业务流程建模,对业务组织建模,改进业务流程,领域建模等方面。
2. 为什么要业务建模
Brooks 大师说,三十多年来各式各样的应用系统(Application Programs AP)历经多次的修修改改,已经变得面目全非,如同一群的怪兽,难以驯服。
Rogerson大师也说,The application is a rock in the river of change.(应用(系统)成为改变之潮流中的顽石)。
对很多企业而言,有一个统合企业各部门的信息系统的心愿似乎已经成了一种奢望。企业中或多或少都会有一些应用系统在辅助企业的自动化运作,当企业信息主管希望能够对目前的信息系统进行整合,能够配合企业的发展的时候,他们失望了。大多数的应用缺乏一个统一的接口,难以进行整合。
在我们进行项目开发的银行中,我们也同样发现了这个问题,不同部门的系统之间无法进行互联,跨部门的业务流程必须经过手工的处理。
以前,应用程序的开发都是基于部门的功能的而建的。单纯只是为了解决目的而建立应用系统。所以这种方式建立的应用系统是针对特定的功能区域(Function Area)而建立的。至于如何使企业内的多个应用系统共同运作,就不在设计者的考虑之列了。随着企业的发展,就会发现企业需要变化以适应市场变化,业务发展的时候,原有的一系列应用系统却成了企业发展的拦路虎,这使得企业不得不回到手工的时代。
针对这种情况,有没有相应的解决之道呢?解决的方法就是从业务建模入手,而不是从较低层次(部门级或以下)入手。通过用例分析技术,建立企业的业务模型,进行适当的切割,选取稳定的软件架构,分析出企业的业务实体(Business Entity 企业中微小不可分的事物,抽象或具体的,如帐户,契约等,又被称为Business Object),以此为基础,组装出组件(Component),落实到相应的三层结构,建立针对特定功能区域的应用系统。
以这样的流程做出来的企业应用系统,不论规模是部门级的,还是企业级的,都有扩展的余地。以组件为基础的软件三层构架,也能够较好的配合企业的业务变化而变化(相应变化的代价较小)。而整个流程的第一步,就是业务建模。
在前一段时间,中国很流行企业流程再造BPR(Business Process Re-engineering)这个名词。BPR这一名词中的R(Re-engineering)一词是由Dr. Hammer提出,说明企业必须推动四个层面的重新设计:Re-position、Re-organization、Re-system、Re-vitalizing之再造工程;名称中的P(Process),更是管理上由销售、采购到财务、生产各层次,力求降低成本、提高产出,所必须精密设计的企业管理流程或程序。这个词目前都是和ERP串联在一起,成了ERP的前置工程,更成为保证ERP能建立企业完美管理体系,以支持高绩效的最重要因素。实际上呢,这个BPR就是我们所谈到的业务建模。
可以看出,业务建模在ERP工程中被着重强调,而且ERP中的BPR已经成为一门独立的学科。不仅如此,即便是在普通的信息系统中,业务建模也是非常重要的,所不同的,仅仅是它们的规模而已。这一点上,可能大家会不理解,如果你只是为企业的业务自动化建立应用,直接照搬企业模式不就行了吗。这里有两点原因,一是企业原有的业务模式在以人为主的环境中可能运行的很好,可是把这套模式原本不动的搬到计算机上就未必会适合了。人的能力和计算机的能力有很大的出入,所以流程必须经过调整以适应计算机;第二个原因是上面已经提到过的避免产生部门级的,部分功能区域的应用系统。
在RUP中,业务建模被作为下游流程的输入重点强调:业务模型是需求工作流程的一种重要输入,用来了解对系统的需求。业务实体是分析设计工作流程的一种输入,用来确定设计模型中的实体类。(RUP)
3. 需求和业务建模
业务建模是需求工程中最初始的阶段,也是整个项目的初始阶段。需要指出的是,业务建模时间的跨度在不同的项目中有很大的差别的。在有些项目中,例如大型ERP系统,可能需要几个月的时间。而对于普通的项目,业务建模的时间可能仅仅需要几天的时间。
需求是技术无关(technology independent)的。在需求阶段讨论技术是没有任何意义的。那只会让你的注意力分散。技术的实现细节是在后面的分析、设计阶段才需要考虑的事情。而在业务建模阶段,不但要保证需求的技术无关性,还要保证你的需求不要深入细节。因为在业务建模阶段,最重要的事情就是要了解业务的全貌,深入细节会浪费时间和精力。要知道,讨论一个企业里的业务细节,就算给你一个月的时间也没必能够结束。
在实际中,这两点都是很难做到的。例如企业原先有一个系统,这就不得不由你讨论和新旧系统的兼容问题。这时候就要注意,如果你是讨论就有系统的架构的话,那还是属于技术无关的范畴,如果你一旦进而讨论各具体模块/组件的细节,那就非但不是技术无关,而且也深入细节了。在不深入细节的问题上,往往你很难禁止项目涉众(Stakeholder)①不去讨论一些相关的业务细节。这个时候你可以将这些细节记录下来,然后再回到业务建模上。
①A stakeholder is defined as anyone who is materially affected by the outcome of the project.
涉众是所有会受到项目结果重大影响的人。
4. 业务建模时期的主要任务
项目涉众的共同愿景:要想项目成功,可离不开项目涉众的支持。在项目一开始,不论是项目涉众还是开发人员,对项目的任务、范围都是模糊不清的。但随着项目的深入,原来模糊的景象会慢慢清晰、立体起来。但是为了不浪费时间,我们有必要在项目射入之前,现在项目涉众中竖立一个共同的愿景。
共同愿景的竖立可没有想象中的那么简单,因为每位涉众都关心自己的利益,都有自己的评判标准。你可以把大家的意见都列在白板上,然后逐项集中讨论,做出修正,直到大家的意见一致的时候为止。在共同远景的竖立过程中,其实有两件事情也已经同时做了,项目范围(scope)和高阶(high-level)需求。
项目范围:项目该做什么,不该做什么,需要在一开始就有明确的定义。对于项目范围内的需求,一个也不要放过,而项目之外的,一个也不要去关心。虽然有的时候,范围的变化会有利于项目本身,例如客户的合理要求或是市场目标客户的变化,但是这种变化应该要在"资源能够支持"和"得到审批"的前提下进行。
项目范围的描述可以通过陈述和图示来进行。我建议大家使用图示。因为陈述语句比较含糊不清。例如常常听到有客户说。"我要建立我公司的电子商务系统。"这句话就是含糊不清的,你的电子商务系统是销售什么产品?面向什么客户?是否要支持在线支付?根据这些疑问,这个陈述句可以做进一步的修改,"建立在线订货系统,针对当前的目标客户销售公司的目前产品。"这样就清楚许多了。不过图示的方法会更好一些,在图的选择上,你可以使用DFD图或是用例图。根据经验,DFD图比较容易为客户所接受。
高阶需求:这个部分我们在下面会详细讨论。既然是高阶需求,就不能讨论过多的细节。在讨论高阶需求的时候,尽量保证快速的讨论出系统的概貌,建立需求模型,得到项目涉众的一致通过。
取得支持:为了保证需求计划的顺利进行,取得项目涉众的支持至关重要。你可以选择在这个时候告诉项目涉众他们的权利和义务,以及开发人员的权利和义务。在这个方面,具体的我不想多说,大家可以参考『软件需求』的第二章。主要的就是"涉众有改变需求的权利,同时要承担向开发人员讲解需求的义务。"开发人员的权利和义务正好和涉众相反。
业务建模会议:所有的这一切都通过业务建模会议进行,和其它会议不同的是,这个会议需要所有的项目涉众参加,如果不能获取所有项目涉众的意见,那就不是完美的。会议中最重要的工具就是白板,一位出色的速记员也是必须的。
建模原理
5. 业务建模中的用例
在上一篇中我们讨论了很多用例的知识,可是落实到企业中的时候,我们往往会感觉难以把握企业的用例,这一点我们在用例的误区中也有提到。在实际的情况中,你可能会对角色的归类,用例的划分,粒度的把握等很细节的方面都没有底,偏偏这些实际的东西对你的项目有非常大的影响。
RUP中,有多种的概念来支持用例的实现:业务主角(Business Actor)、业务实体(Business Entity)、业务用例(Business Use Case)、业务角色(Business Worker)、业务用例实例(Business Use-Case Instance)。为了能够比较清楚的展示出业务建模,我们采用了UP方法的代表――RUP。但在实际中,要视大家具体的情况而定,这里所讲到的概念,都是为了帮助大家理解建模过程,并不是让大家生搬硬套。
在我们对系统还丝毫不了解的时候,我们就会把系统看成一个很大很大的黑盒,这个大黑盒子我们会叫他业务域(Business Domain),把它的外部看成一个业务环境(business environment)。而那些在业务环境中和业务域有关系的人(也可能是物)就被称为业务主角(Business Actor)。在实际的例子中,我们可能会把信贷业务(注意不是信贷业务系统,这里是业务建模,系统还不存在。)称为业务域,我们经过调查,发现平时和信贷业务打交道的有客户,人民银行,外汇管理局,其他银行,信贷部门使用的其他系统,银行内部的其他部门。所以这些人(物)就是业务主角。业务主角的实例一般包括了客户、供应商、合作伙伴、潜在客户("市场")、当地政府、在业务中未建模部分工作的同事等。必须注意的是,业务主角表示的特定类型的用户,而不是某一个具体的用户。一个角色可能会有很多实际用户担任,一个实际的用户也可能会担任很多的角色。
业务用例以及业务用例实例在RUP中的定义如下:
A business use-case instance is a sequence of actions performed in a business that produces a result of observable value to an individual actor of the business. A business use case defines a set of business use-case instances. A business use case has a name.
业务用例实例是在业务中执行的一系列动作,这些动作为业务的个体主角产生具有可见价值的结果。业务用例定义了一组业务用例实例。业务用例具有名称。
刚开始大家可能会对业务用例以及业务用例实例有所疑问。其实可以把他们看成基类和子类的关系。在一个企业中,具体的工作流程可能有很多很多,比如你去麦当劳的时候,点汉堡和点薯条的工作流程就不一样。众多的流程给需求的调查工作造成了一定的难度。即使是最古老的哲学也告诉我们,表面现象是复杂的,本质是简单的。为了简化需求工作,我们就把点汉堡和点薯条归纳为点餐。这样,点餐就是一个业务用例,而点汉堡、点薯条就是相对应的业务用例实例。

业务用例
业务角色和业务主角的概念也很容易让人摸不着头脑。其实看它们的英文愿意会更容易理解它们的区别:Business Worker,Business Actor。Worker有工人的意思,而Actor有参与者的意思。所以它们的区别就是一个在内部,一个在外部。业务角色是实现业务用例的人,业务主角是和业务有关的人。例如,对银行的押汇业务而言,客户就是业务主角,他和业务有关。而押汇人员就是业务角色,因为他们是实现业务用例的人。在RUP中,二者定义如下:
A business worker represents a role or set of roles in the business. A business worker interacts with other workers and manipulates business entities while participating in business use-case realizations.
业务角色代表业务中的一个或一组角色。参与业务用例实现时,一个业务角色和其他角色进行交互,并操纵业务实体
A business actor represents a role played in relation to the business by someone or something in the business environment.
业务主角代表了与业务有关的角色,此角色由业务环境中的某个人或物来担任。

业务角色

业务主角
分辨业务角色和业务主角要看环境而定。当你开发企业的ERP系统时,部门的员工都属于业务角色,而你开发一个部门级的应用时,其他部门的员工可能属于业务主角。
业务实体,在一些文章中被称为商业对象(Business Object)。不论怎么叫,所表示的意义都是一样的。例如在银行信贷这个例子中,我们就涉及到很多业务实体:契约、单笔贷款、客户等。所以业务实体就是企业中那些很基本的要素。如果觉得银行押汇的例子不好理解。可以想象餐厅中的菜单、汉堡等都是业务实体。在RUP中,业务实体被定义为:
A business entity represents a "thing" handled or used by business workers.
业务实体代表业务角色处理或使用的"事物"。

业务实体
在很早以前,我们讨论过需求易变性。相对于需求的不断变化,可是业务实体对象在一段相当长的时间内都存在。航空公司今天打折,明天又不打,还有明折、暗折。可是机票从来没见有什么大的变化,从来也只有那几样属性:价格、航班、出发地、目的地。所以业务实体是比较稳定的。这对于我们是有很大的意义的:
"一个业务实体经常代表某个对多个业务用例或用例实例有价值的事物,因此,业务实体对象的生存期相当长。一般而言,一个好的业务实体不包含关于其使用主体和使用方法的信息。"(RUP)
由业务实体组成的业务用例会稳定很多。在以前,开发方式采用模块为基础的方法,需求变化的时候,只好改写模块。如果采用稳定的业务实体来实现业务用例的话,业务用例的改变只需要对业务实体进行重新的组合。当然,这里还需要很多的技术来实现,并没有那么简单。要知道,四个现代化可不是一天就能够实现的。
还有一个使用业务实体的重要原因:业务实体的特性决定它具有天生的重用性。就像麦当劳的销售系统中有汉堡实体,生产系统中也有,供应链系统中也有。天哪,这世界真是美好!
使用业务实体一个很大的困惑是应该把它做为类还是属性。这个取决于业务环境对这个实体的重视程度。一个客户在银行信贷部门是一个很重要的类,而在押汇部门就只是信用证实例的一个属性。这个问题非常的重要。设计时的失误可能会导致今后系统改进的极大痛苦。例如本该设计为类的业务实体设计成了属性,在今后增加属性的时候不得不面对着数据库的调整和系统的修改。
6. 建立业务用例模型
业务用例模型(business use-case model),在RUP中定义为:
The business use-case model is a model of the business intended functions. The business use-case model is used as an essential input to identify roles and deliverables in the organization.
业务用例模型是说明业务预期功能的模型。作为一个核心输入模型,业务用例模型用于确定组织的各个角色和可交付工件。
从业务用例模型的定义可以看出,它是企业最核心,最概括的业务说明。它主要是由业务用例和业务主角构成的,其主要目的是说明客户和合作伙伴是如何开展业务的,它描述业务的主要方式是通过业务用例的方式。下图为RUP中业务用例模型的图示。

业务用例模型
从图中我们也可以很清楚的看出业务用例模型包括一组的业务用例。这是因为企业中的业务通常都会由多个的业务用例的多个实例构成。这些业务用例形成的企业工作流程可能会由业务主角所引发,也可能会由业务规则②所引发。
②业务规则(Business Rules):业务规则是必须遵守的政策或条件的声明。(Business Rules are declarations of policy or conditions that must be satisfied.)
业务用例模型实际上就是企业经营业务的一种描述,为了建立完整、准确的企业用例模型,应该将注意力专注于企业的业务做了些什么事情,而不应该集中于如何做。虽然这样可能会产生一些业务用例相冲突,相重复的情况,但是RUP的思想在于迭代,这项工作完全可以在接下去的迭代周期内完善。
业务用例模型是和企业业务最贴近的计算机模型。它的很多思想和企业日常经营如出一辙。在企业的日常活动中,业务的种类可能有很多种。在一些讲述ERP思想的文章中,通常会强调三类:
一种是和主营业务密切相关的工作,例如银行的营业部、信贷部、押汇部等。这种工作通过人的劳动,将一种资源转变为另一种资源,产生价值。
一种是管理型的工作,例如公司的管理层,财务部门等。这种工作本身并不产生价值,但是它通过指导、管理、检测第一种工作,加大第一种工作的产出价值。
还有一种称为支持工作,例如系统管理、安全等。它并不是很重要,具有支持其他工作的性质。
业务模型同样可以使用这种分类。通过这种分类,可以更好的把握核心业务用例,为下一步的工作打好基础。
有很多业务用例是由业务主角触发的,RUP中也把和业务主角有关联关系的业务用例称为核心业务用例(Core Business Use Case)。这强调了构建业务模型的目的是为了提供以用户为中心的服务。这也是我们建立业务用例的时候应该注意的。
当然,有时候业务用例的触发是为了产生用户需要的结果。例如企业的市场调查行为就不是由业务主角触发,而是企业积累了大量用户请求的结果。而对于管理型、支持型的,不直接和业务主角的客户类发生联系,但是也有其特定的业务主角,如管理型的业务用例需要和董事会为发生联系,支持型的业务用例可能和供应商发生联系。
在建立了基本的业务用例模型之后,对此模型进行精化是非常有必要的,这时候,在上一章中我们介绍的用例的扩展关系和使用关系就有了用武之地。除了这两种关系,还有一种新的关系。
7. 在业务建模中使用关系
泛化关系(Generalization):根据我的理解,可以把它看作我们比较熟悉的继承关系很相似的一种关系。Generalization一词含有一般化、概括的意思。它是一个相对抽象的词。虽然它和继承关系非常相似,但是它们在使用环境和产生目的方面都有相异之处。下图描述了四个业务实体之间的泛化关系:

当你去麦当劳的时候(不要误会,我并不是很经常去的),会选择麦香鸡汉堡、麦香鱼汉堡或是吉士汉堡。但是分别对这三种汉堡建立业务实体就非常没有意义。所以可以将它们概括为汉堡这个业务实体。同样的道理,企业的业务流程中也可以概括出一些共有的属性和行为。为了避免多次说明同一个工作流程,您可以将共有的行为放在一个单独的业务用例中。称为父用例,执行子用例的用例实例将遵循父用例的事件流,同时插入附加行为或修改在子用例事件流中定义的行为。
8. 方法的选择
以上的原理我采用了UP的方法。但是除了UP方法,还有XP、FDD等方法。所以在做业务建模的时候,也要根据不同的方法选择适当的工件。例如素材和功能。方法的好坏并不是我们这片文章讨论的重点,我会在另一篇文章中讨论方法。再一次需要强调的是,上面讨论的RUP的工件只是为了学习,所以才定义了比较复杂的工件,区分了它们之间的区别。但是在实际中,并不需要这么多的工件,那只会使你的项目涉众和开发人员糊涂。这些工件的区别只要在你心中就可以了。至于具体的实践,我们会在下一篇文章中讨论。
 
需求的实践(4)
业务建模时期(下)
--------------------------------------------------------------------------------
 
来自:IBM China 作者:林星 [2003/04/02]
和上一篇的理论不同,这一篇文章更注重于实际,举出了在业务建模简短需要注意的一些原则和实践,每一条都来自于实践之中,也都有理论的支持。其中的很多内容更是经过多次的失败才总结出来的。相信大家如果能够理解这些原则和实践的某些方面,至少能够避免重蹈覆辙。
原则(Principle)
1. 谁才是"上帝"
<我们说客户是上帝,是因为客户的重要性,客户占有决定性的地位。可是在软件开发中,到底是谁有决定权呢?是出资方,还是项目经历,或是程序员?
职责不清,是业务建模失败的主要原因之一。我们可以很容易的看见客户把自己的要求用几句话高度浓缩之后扔给开发人员,或是开发人员按照自己的意思开发程序。难道说,客户和开发人员之间真的是"心有灵犀",完全不用沟通的吗。
我在前文中已经提到过项目涉众和开发人员的权利和义务,我想这里还有必要再次强调。Scott W. Ambler说:
it is the role of project stakeholders to provide requirements, it is the role of developers to understand and implement them.
在我一次开发过程中,遇到过一个很有意思的涉众,他在他的需求分析中这样写:"总之,要实现那种能够想到就能做到功能。"我想,这位涉众对我们的计算机工业有着非常远大的抱负。但我不得不客气的告诉他目前实现是不太现实的。
大家听了可能会觉得好笑,但是在我自己和客户打交道的生涯中,这种客户不在少数。现实就是这样,你要怎么做?是一笑之后,弃之不顾吗?我想大多数人会这样做。因为他的要求太荒唐了嘛。可是,你有没有花时间去了解一下,他这句荒唐的话背后代表了他的什么意思呢?我觉得,软件开发人员负有教育涉众的义务,你需要引导你的涉众,让他们说出自己的心声。我在看到这位涉众的这句话后,就花了一些时间去了解,其实呢,事情很简单,他就是想要一个能够定制报表模板的功能。而在项目结束后,我和这位涉众有幸再一次的合作,这时候,他已经成为了一个出色的客户方的项目领导者了。
这个例子说明了什么呢?涉众往往都是领域专家,对自己的工作有很深的认识,可是由于对软件开发的不了解,涉众往往表达不清,甚至表达不出自己的需求。这时候,就是体现你的功力的时候了。记住,象对待上帝一样对待你的客户。
2. 耐心是首要的
明白了谁是"上帝",那就要耐心的对待上帝。学理工科的人,一般在逻辑思维上会比较好,可是对于涉众来说,可不一定是这样。我就遇到过一位做档案工作的涉众,在了解需求的时候,扯东扯西,含糊不清。明明一分钟前才否定的方法,下一分钟又提出来了。我觉得我的脾气应该是不错的,可到最后也几乎发飚。所幸,最后我终于撑了下来。我想,在经历过这件事情之后,我的耐心指数又会有一个很大的提高了吧。
我有一位同事的耐性是我所佩服的,在一个网站项目中,他负责系统分析。他整整花了三天的时间,和网站项目的负责人住在一起。最后系统分析出来之后,他的精神还不错,可是那位负责人已经快不行了。
当然,这只是个笑话,并不是去鼓励大家拼命。劳逸结合还是很重要的,身体是革命的本钱嘛。但是这告诉我们,如果缺少耐心,需求是很难成功的。例如在业务建模的讨论会上,你虽然规定了这次的会议讨论的是高阶需求,可是与会者总会时不时的争辩一些芝麻绿豆的小事儿。你怎么办?我相信这种情况是很普遍的。
耐心最后会仍会体现为沟通,只有耐心的沟通,你才能揭开需求的重重面纱。人的行为总是会受到思想的指导,如果你解不开涉众的心结,你就不可能了解他真正需要的。
我的一位项目涉众的表现很奇怪,她总是在不停的说一件事情:"她要实现报表自动生成。"她的需求讲来讲去好像总脱不出这个范围,可是我从她那里几乎听不到别的东西了。这时候,我决定放弃了,我想从她哪里可能已经没有更多的资料了。但在我了解到她的工作中报表处理占用了她大量的时间之后,我改变了想法。在我花了一些时间帮她理清了报表处理的思路之后,她还在其他方面给了我很大的帮助。
3. 参与是重要的
XP方法的一个重要实践,就是提倡"现场客户"(on-site customer)。也就是说,客户应该随时和开发人员在一起,随时提供资料和做出决策。而这个客户,也必须领域专家,而且能够有权做出决策。
这种现场客户相信国内的软件组织多半还做不到。但是一定要往这方面努力。我认为,这种现场客户有两种人:一种是项目涉众,还有一种是行业专家。其实很多软件公司都会配备一些管理咨询人员,这些人就是行业专家。有数据统计说,目前广东省软件公司中的咨询人员和开发人员的比例达到了3:1。我觉得这是好事。项目涉众往往对自己的工作中的事务性部分有很深的认识,但是很难将之提升到一个理论的水平。这时候就需要一些行业专家来帮助了。让行业专家和项目涉众共同探讨,还能够激发项目涉众的灵感,想到原来他想不到的方面。这就是"潜在需求"的开发。
另一方面,参与还意味着需要项目涉众全身心的投入到业务建模的过程中来,要能够调动他们的积极性。因此呢,太复杂的流程会阻碍涉众的参与。所以,使用一些简单的、能够为客户所接受的工件(Artifact)来进行业务建模是很有必要的。我说过前面讨论的那些"主角"啊,"用例"啊,那是理论,是给开发人员看的,让开发人员心里有个底。你给涉众看这些,他们能懂吗?等他们了解了这套机制,恐怕黄花菜都凉了吧。
素材(User Story)、特性(Feature)、CRC卡片这些都是很不错的工件,既简单,又能够满足需要。
知识点:素材和特性都表述了用户的一个简单的要求,它能够在较短的时间内完成。素材是XP方法中的工件,特性是FDD方法中的工件。CRC是class、 responsibility、collaborator的缩写,它是一张分为三个部分的卡片,分别标记了类名,类的责任,以及类之间的合作关系。非常的贴近客户,甚至可以在做游戏的过程中完成卡片的填写,能带来很强的客户参与度。
4. 拥抱变化
我想这一点会遭到开发人员点一致指责。毕竟,需求变化是开发人员最讨厌的一件事了。不错,我也讨厌。可是,就像我们常说"哭不能解决问题"一样,讨厌能解决问题吗?拒绝客户的变更要求,要求客户在需求规格说明书上签字。这些做法只能是适得其反。没有任何正面的、积极的意义。
必要的需求变更管理是重要的。因为无休止、无控制的变化必然会造成资源的极大浪费。但从另一方面说,需求变更被接受的评判标准应该是"是否合理",而不是"是否易于实现"。
需求变更要求我们的开发工作要迭代式进行,包括需求、设计、实现等阶段。这样才能将变更风险减到最小。这一点我们在讨论具体需求建模的时候会进一步讨论。
拥抱变化的更高一个层次是提前预估变化。制定一个可能的变化清单来记录可能出现的变化。最简单的例子就是一个企业在开发了进销存系统之后又希望能够开发财会系统与之相连。如果你能够预先留下伏笔,相信能够省不少力气。预估变化的另一种做法是通过使用模式。但是切记,模式的使用也不能过头。这些是题外话,如果有机会我会在其他的文章中集中讨论这方面的问题。
实践(Practice)
5. 建模会议
会议是业务建模最重要的手段。尽管会议在中国总是背负着一些骂名,但是只要组织得好,它是一种相当有效的沟通(Communication)手段。建模会议是一种大范围的会议,换句话说,所有的相关人员都应该参加会议。因为在业务建模时期,主要的目的就是建立对系统的高阶需求,这就要求众多项目涉众的共同参与,以保证需求的广泛性。所以呢,建模会议的规模是相当大的。出资方、高级经理、经理、直接用户、开发人员,各方各面的人都应该参加或是派代表参加建模会议。
如果大家有过参加大型会议的经验都知道,越是大型的会议,它的决策效率就越低。这是正常的。因为一个人的时候,不需要沟通,决策效率最高。等到两个人的时候,他们需要沟通的时间来进行决策。等到三个人的时候,这个沟通并达成一致的时间就更长。如果人数到了四个人、五个人甚至一二十个人,那么大部分的时间都会花在沟通上。更何况,人和人之间还有观念不同、利益之争。所以呢,为了保证会议的效率和效果,应该遵循一定的规则:
做好准备:如果你要开会,与会者连内容都不清楚,那你会怎么办。你必须首先花很多的时间来说明你开会的目的,是不是。要事先将会议的主题、议程连同会议通知发送给与会者,让他们先有个准备,会议开始时就能够迅速进入正题。
尽量邀请最多的人:我已经说过,如果建模会议不能够听取最广泛的意见,它就不是一个成功的会议。可是在现实中,这点往往难以做到。因为目标组织做为客户,往往都很"拽",在没有充分认识会议的重要性之前,要做到全部到场简直就是不可能。而客观上也会有出差、休假、有要事等原因做不到这一点。这里,一方面你需要向目标组织的决策者阐明利害,让他们重视。另一方面,你也需要积极主动的邀请项目涉众参与。因为邀请所有的人是不可能的,所以就尽可能的多吧。
分出与会者的级别:我很喜欢那种有一个内圈、一个外圈的会议室。因为我邀请所有人是件无法做到的事情,所以我首先要保证核心人员能够全部到场,坐在内圈,然后才是次要的人员,坐在外圈。核心人员是和你的项目息息相关的那种人。比如,财务系统,财务主管就是核心人员。要保证核心人员全员到场,至于次要人员,越全越好。
从底层开始:中国人有个比较不好的习惯,就是老板说一的时候,他决不会说二。所以要先让底层先说话,然后才轮到中层,再到上层。开发人员是不说话的,他们要么听,要么引导大家说话。如果我们一开始就先让领导来训话一番,那底层的人也就不用再说什么了。
列举所有涉众的所有观点:首先要让大家能够对新的系统畅所欲言,然后把所有的观点都罗列在白板上。这里头可能会有一些观点会是非常荒唐的,但没有关系,尽管写上去。这是一个脑力激荡的过程,很容易产生出新的idea。主持的开发人员的主要工作就是引导和鼓励大家说出更多的想法,并记录下来。这里我们稍微离题一下,有人说中国人在会议上大都不愿意发表意见,我看在这种建模会议上不必过于担心此事。为什么呢,因为项目涉众不需要为他们的发言担任何的责任,说了,白说,白说谁不说。
将观点分类:想必你的项目涉众已经有些累了,创意也差不多了,你的白板估计也满了。但是你看看白板上的观点,有很多是重复的,有很多是类似的。所以你需要用逻辑的观念将这些观点归类整理。这个工作也可以由你引导大家去做。
确定优先级:对观点排出优先级也是非常重要的,它能够帮助你识别出重大的风险,并为你在制定迭代计划时提供指导。同样,这项工作也应该由项目涉众来确定。
调查主要业务逻辑:什么叫主要业务逻辑?包括了企业的主要业务流程、主要的业务规则、重大的算法。这些都是需要在一开始就十分明确的资料,需要在建模会议上了解清楚。当然,你不能对你的项目涉众说,"这个,接下来,大家谈一谈主要的业务逻辑吧。"下面的涉众一定摸不着头脑。你还是应该引导涉众,从涉众的话语中捕捉你需要的信息。
注意会议时间:人不是机器,是会累的。所以控制好会议的长度很关键。一般,这种会议会有四五个小时,根据统计,两个小时内的会议不会让人产生疲劳感。所以应该把会议分成几小段。另外,你还可以根据会议的进展来决定每小段会议参与的人数。因为,会议越往后,一些与会者就不太重要了。
避免细节:建模会议主要的目标是建立高阶需求。如果把过多的时间花在讨论鸡毛蒜皮的小事,那就会浪费大家的时间。而在此时调查需求细节是没有很大的意义的。因为你对很多的事情都还不了解,需要进一步的深入。这时候的细节对你并没有太多的帮助。
回避技术:我在一次建模会议的时候,遇到一位负责技术的涉众,他总是不停的询问系统的技术架构,推销他的设计理念。使得我不得不好几次重申,"技术问题我们会单独找时间谈。"我想,那位技术人员应该是有比较好的理念,也很希望能够表现一把,这点无可厚非。但是这个时候还不是讨论技术的时候,需求尚未明确,讨论技术实现不是本末倒置么?
做好记录:俗话说,好记性不如烂笔头。所以在会议上做好记录是非常关键的。因为这种会议的代价相当高昂,你的项目涉众不可能每天不干活,陪你开会的,就算他们肯,他们的老板也不肯。所以要充分利用好会议的成果,所以一个优秀的速记员绝对是必要的。另外,根据研究显示,如果使用录音机的话,会使得与会者心存芥蒂而不愿开口,所以,不要使用录音机。
6. 测试
在需求的初始阶段提到测试可能会觉得有些奇怪。凡是项目,总会有一个标准来考核是否成功。这里的测试指的是考核软件项目是否成功的一个"执行性目标"。
这个目标将会是软件开发最终要满足的条件,软件成功与否的判定标准。很多企业在信息化建设的时候没有一个比较明确的目标。所以在被问道这方面的问题时,他的答案往往是我的目标是建成企业的ERP系统,建设企业的信息化平台等空洞的话。这样的软件怎么开发?连结束的标准都没有。是费用用完结束呢,还是决策者说停就停了呢。目标应该有一个可以量化的标准。例如,开发物流系统的目的是为了缩短产品周转周期,降低库存;开发供应链系统是为了加强和供应商的联系,降低库存。这些和具体业务有关的指标都是可以通过细化,用多种分指标来度量的,所以是可以做到的。
我们把这种目标称为测试就是要提醒开发人员,要把满足这种目标当作最终的测试。你的软件做得再好,不是涉众想要的,又有什么用?这是很浅显的道理,可是在实际中,涉众方和开发方往往因为一些具体的因素看不到这一点。其实,这个目标在上一篇中我们也讲过,那时我们是把它叫做愿景、范围。在本质上是一样的。
这种"可执行性目标"可以使用一些因素来衡量:
7. 业务实体
业务实体(business entity)是企业中的一些起到关键作用的类别。客户、供应商、员工、订单、凭证,这种业务实体的例子可以举出很多很多。业务实体往往会成为一个很关键的因素,因为在系统中,角色操作业务实体的行为往往会分配给业务实体,例如"根据订单计算价格"会成为订单的一个行为。这样,工作流程的实现往往是多个业务实体相互合作完成的。所以业务实体设计的好坏会对系统有很大的影响作用。
业务实体设计的主要工作包括找出业务实体,确定业务实体的属性和行为。
要确定业务实体,首先必须确定角色,并从角色的行为找出业务实体。角色需要我们对目标组织进行讨论。以我个人的经验,寻找业务角色一般比较简单,但是要记住,一个人可能担任好几个的业务角色,这是经常发生的情况。从业务角色的行为,我们可以找出业务角色所处理的事物,这些就是我们所需要的业务实体。业务实体是一个单独的业务实体还是业务实体的一个属性是值得研究的。一个本该是属性的事物被判断成业务实体只是会带来一些开销,可是一个本该单独列出的业务实体却只是被判定为其它业务实体的一个属性就有可能会带来灾难性的后果,最大的可能是系统难以扩展。
在一个人力资源管理系统中,员工类可能是非常重要的一个业务实体,它可能有非常多的属性。而在其它的系统中,例如进销存,员工类只是起到一个记录、权限管理的作用罢了。再比如,在一些企业内部的自动化处理系统中,客户可能只是其它一些实体的属性,而以客户为中心的设计大行其道的现在,这种设计就有它的致命缺陷。
要确定业务实体的属性和行为,主要是要确定每个类(业务实体)要做的事情,属性则是为了能够更好的描述类和类要做的事情。利用CRC卡片是一个不错的办法。
CRC是"类"(class),"责任"(responsibility)及"辅助者"(collaborator)三者的简称,这些资料常呈现在一张卡片上。
类名称
责任1 责任1的辅助者1
责任2 责任2的辅助者2
… …

通过制作这样的CRC卡片,可以比较容易的找出每个业务实体的行为(责任)和属性(辅助者)。您可能会问,为什么不直接找出属性和行为,而要多此一举呢。这个问题是我们一直在强调的。在建模阶段,我们面对的是可能对计算机技术完全不懂的涉众,所以,采用大家易于接受的方法,可以够保证需求的完整和正确。
8. 准备计划
目前在软件开发中,关于计划有两个极端的误解。
在有些软件组织中,一般不做计划,或是做一些笼统的、没什么用处的计划。一些开发人员认为,"做计划是虚的,还不如做些实际的事。"对于项目经理,或是对这种情况没有办法,或是发布的计划开发人员阳奉阴违,让计划成为一纸空文。项目执行中随意性极大,偏离方向的事情时有发生。
而在另外一些组织中,计划被视为重中之重,需要花费大量的时间、人力,做出来的计划可谓事无巨细,算无遗策。而写的出这种计划的项目经理也被视为高级人才。开发人员叹口气说,"写程序的不如写文档的。"可是在执行的时候,原来精密的计划往往漏洞百出,项目的进度一拖再拖。
我们所有人都知道那句明言:在软件开发中,要花90%的时间完成90%的项目,然后再用90%的时间完成剩下的10%的项目。为什么呢?计划不科学。
在管理学中,计划,也有叫规划的,定义是"为组织确定目标、实现目标的战略与手段、步骤、程序的过程。"打个比方说,我想要把一个箱子推倒一个地方,这个地方就是我的目的,我为了到达那里,我是不是要估计一下按什么路线推,要推多快。然后我就开始推,还要不时的和原先的计划比较比较,需不需要调整路线和速度。这个估计就是计划。
计划的目标不是消除错误,而是让所有错误变成一堆经过细心规划后的小错误。研究四种设计方式后,最终放弃三种,最多不过是三个小错误而已,但因没有做好设计而将程序重写三遍,却可能造成三个大错误。
然而为什么会出现上面提到的两个极端呢?第一种情况其实是软件行业最早期的一种形态,没有计划,资源分配混乱,软件的开发过程处于混沌、无序、自发的状态。项目的成功全凭运气和项目成员的个人能力。而第二种情况其实一个前进了的形态,最典型的代表就是我们之前提到过的瀑布模型。那这种考虑周密的计划为什么也容易失败呢?很简单,你认为你考虑周密,可是实际上却不一定。我就见过标榜自己考虑周详的计划中排出的时间表是一周7天的。看来他一开始就没打算让开发人员休息了。计划是对未来的一种估计,哪一个人能够准确的说出6个月后的情况,恐怕没人能行吧。9月11号之前,有几个人能料到那天会发生这么大的事情?那你凭什么推算出半年,甚至一年后的事情呢?另外,你是不是真的非常了解你的开发人员,以至于有信心代替他们制定计划呢?
有人说,计划没有变化快。这句话说得很对,它提醒我们,没有计划是不行的,不具备可执行性的计划也是不行的。计划不是拿来炫耀的,是要用来执行的。我们定计划的时候,可以没有华丽的词藻,美好的构想。但是我们不能没有一些要素:
什么(WHAT):按顺序列出达到目标所需完成的工作;
何时(WHEN):完成工作所需要的时间;
做到的程度(HOW-WELL):要完成的工作以何标准来度量;
资源(RESOURCES):完成工作需要的人员/资金等;
谁(WHO):由谁负责完成任务。
但是我们仍然逃不开现实和计划的背离的问题。我们虽然对预计一年后的事情把握不大,对把握开发人员在想什么把握也不大。但是如果你自己想想自己两个星期后的事情应该还是能够猜的八九不离十吧。这就引出了迭代的概念。一个项目由几个甚至几十个的迭代周期组成,每个迭代周期都是比较容易估算并制定计划的。这就是迭代的思想,也是软件工程技术的一个大飞跃。说到这里,我又要吊大家的胃口了。关于具体制定迭代计划的讨论,我们会留到下一章节讨论细节需求建模的时候再谈。
9. 培训
我很难想象一个项目没有培训该如何进行。兵书有云,"三军未动,粮草先行。"我们可以理解为事先做好充分的准备。项目也是一样,在一开始就要指定好培训的计划,留出培训的时间。我想,除非是一个非常完美的团队,否则他的成员一定也还是有不懂的东西吧,如果没有培训计划,把学习的任务推倒个人头上,项目的风险就会变得难以控制。
说起培训,大家可能就会认为是大家正儿八经的坐在那里,听一位老师上课。并不是这样的,这里说的培训是一个广义范围的培训,达到一组课程、一次会议,小到一次讨论、一次交流,都可以是培训。而其目的,就是为了让团队成员拥有足够的知识和技能,来完成项目。
 
 
需求的实践(5)
细节需求时期
--------------------------------------------------------------------------------
 
来自:IBM China 作者:林星 [2003/04/02]
和业务建模时期不同的是,我不再花费笔墨讨论需求要如何做,因为做法、注意点和业务建模时期并没有什么太大的区别。而在完整的流程上,像RUP、XP之类的方法学可比我讲的要好的多。因此,我会把焦点集中在我在实际工作中的一些困惑,以及一些思考。
1、"和其它阶段的关系"的再思考
上一篇的末尾我们简单的讨论了细节需求阶段和其它阶段的关系。对于软件过程的各个阶段,不同之处只是注重的焦点不同而已。在业务建模阶段,我们关注于系统的整体需求;在细节需求阶段,我们更关注于需求的细节部分。其它的阶段也是一样,架构阶段,所关注的当然是如何设计出一个合适的架构;到了设计阶段,注意力就转移到了如何设计方面。 当然,焦点的不同,导致了各个阶段所需要的技能和工具也不尽相同。业务建模阶段需要你有整体的把握能力,你可以使用简单的用例图,基本的用户素材等工具。细节需求阶段则要求你能够充分的挖掘需求和进行良好的沟通。相应的,在架构、分析、设计等阶段,也会有不同的需要。
各个阶段的实质就是注重点的不同,这对于大多数的软件开发而言都是一样的。不论你采用的过程是传统的,还是迭代的。
2、架构
Martin Fowler在他的ISA中写到:
I'm using architecture to mean the important design decisions, the ones that shape most aspects of a software system. These are often the harder decisions to change later on in the project (although often not as hard as people think). As a result these are ones where it's useful to start in the right direction, and thus knowing about architecture is a valuable skill for any software developer.
架构并不神秘,无非是一个决策而已,只是这项决策对软件特别重要就是了。软件开发人员可能根本没有主动的进行架构设计,但是他的行为,已经潜移默化的进行了;而还有一些人,总在谈论着架构,但是并不了解这个词的含义。
春运就要到了,学生也要赶着回家。如何选择回家的交通工具就是一个重要的决策。路程的远近、不同交通工具的价格都是显式的,比较容易知道的。而以往的经验也告诉你,火车票比较便宜,但是比较紧张,花费时间较长,整个过程也不舒服;飞机票比较贵,但是容易买到,花费时间少,整个过程很舒服。这时候你就要做出正确的决策,为回家选择一个正确的架构。你可能考虑的因素有哪一些?以下就列出了一些可能的因素:
拥挤程度,大家都知道春运时那种情况;
购买票的难易程度,火车票需要很早就要预定了;
是否有额外的渠道,比如你能够买到飞机的学生票;
经济实力,经过了一个学期的花销之后,现在还剩多少生活费;
根据这些因素,以及这些因素对你的影响程度,即优先级,你可以自己估算出一个或几个可能的架构方案。而这种架构的选择,直接影响到你之后的行为,也影响到行为的结果。
开发软件和买票回家又能有什么区别呢?一样要考虑成本、结果、时间。所不同的只是复杂了:需要专业技能,有很多不确定的因素。
那么我这里谈论架构的问题,和需求有什么关系呢?在上面的例子中,大家可以看到架构是根据什么决定的?是因素。因素的本质是什么?就是需求。因素,就是需求。所以,需求决定架构。上一篇中,我谈到说,在进行细节需求之前,一定要定出架构。当然,这时的架构可能只是一张草图。为什么?因为我们已经进行了业务建模,对项目有了一定的认识,对用户的需求也有一定的把握,成本、范围、时间等要素也都清楚了(如果你还不了解这些,请你回到业务建模阶段,你的工作还没有结束)。这个时候,决定架构的因素已经形成了,可以进行架构的设计了。
需求能够决定架构,架构反过来也能够影响需求。最明显的一个例子就是用户界面的设计。虽然用户界面主要来自于需求,但是不同的架构对用户界面也会有影响,例如基于浏览器的客户端,和基于Windows界面客户端能够提供的界面就不同。
在XP中,这种的架构设计,被称为Architecture Spike。为什么叫做Spike呢?就是说你需要专研,解决一些主要的问题,但你并不是提供一个完整的解决方案。例如,在项目的初期,如果你对新近的服务器和操作系统不了解,你肯定会花时间去了解,去试用,去测试;如果对数据库不了解,你也肯定会试着使用看看。这种行为,就是Spike。所以呢,架构的设计只是很初步的设计,而不是一个完善、定型了的设计。这一点要注意。
架构的选择和开发人员的经验和能力非常有关系。一般来说,它需要开发人员具有相关的经验。提供架构的厂商多如牛毛,如何选择,也是一项学问。比如,数据仓库的平台,选择的品种就很多;而Web Server的选择也是五花八门;操作系统也是一样。这些又都是和架构息息相关的。
3、模式
武功有招式,下棋有棋谱。不论是招式,还是棋谱,都是针对某一种问题的特定解决方案。在软件开发领域,这种解决方案就被称为模式。
"每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心,这样,你就能一次又一次的使用该方案而不必做重复的劳动"[AIS,77]
这句话源自模式的鼻祖――Christopher Alexander。而在软件开发领域,最值得一提的著作,就是GoF写的『设计模式』一书。在该书中,作者描述了23种的设计模式,可以说,这些模式奠定了面向对象设计的基础。而另一本值得阅读的著作,就是Martin Fowler所著的『分析模式』。
在软件设计中,我们遇到各种各样的问题,我们可能缺乏经验,或能力有限。这非常的正常。但是现实是,我们生产出的代码由于设计方面的缺陷,往往不够清晰,容易出错,难以扩展。相信只要是开发过软件的人,都遇到过这种问题。于是,我们就希望能够看看其他人,是如何处理这种问题的。这里的"其他人"指的可能是技术专家,也可能是经历过同种问题的人,他们对你遇到的问题有能力,有经验来解决。他们提出的解决方案往往是非常成熟的,能够解决你目前遇到的问题,也能够解决你目前尚未遇到的问题。
这对你的吸引力是很大的。那么,我们谈论模式,模式来源于何处呢。注意,模式是针对某一类的问题的解。这里的问题,所指的就是需求。比如说,客户希望能够在软件中实现不同的税率计算方法,那么,我们很自然的就可以想到Strategy模式;当客户的产品有一个很复杂的单位换算机制的之后,我们也能够很自然的想到Quantity模式。使用模式,能够使我们迅速的把握需求的解决方法。另一方面,模式往往告诉我们比目前的问题更多的方面,因为模式都是大家的经验沉淀。如上所说,它还可以解决你目前没有遇到的问题。因此,我们还可以从模式中发现出更深的需求。
另外一点也很重要,虽然它和需求的关系不大。模式往往都有一个模式名称。这就形成了一种沟通的语言。比如我们在下象棋的时候,只要说"马后炮",谁都知道这是什么意思,绝对不需要呢详细的解说每一步棋子的走法。对于软件开发也是一样的。我和我的同伴会心的一笑,说:"Factory Method。"两个人都能够理解这是什么意思,因为这是一种共通的语言,它代表了背后隐藏的各种类的关系和代码实现。这在软件开发中非常的重要。当然,这有个前提,大家都对模式有一个通透的了解。
4、简单设计
模式属于设计的一环,所以前面我们讨论的其实就是设计和需求的关系。这一小节我们还是讨论这个话题。但是侧重点有所不同。XP中有一个原则:KISS。不是kiss哦。它是Keep it simple and stupid的缩写。除了XP,其它的敏捷方法都提倡简单设计,反对过分设计(over build)。也就是说,针对目前的需求,设计目前的软件。
很多的软件人员都是完美主义者,他们喜欢完美的设计,然后把这种设计提供给用户。这种思想就是过分设计的开始。不必要的功能浪费了客户的投资。我们在做需求的时候,很经常发现开发人员随意的向客户推销一些新功能,或是在设计时,过多的考虑未来可能出现的需求变动。
所以,简单设计的意思,就是要针对目前客户提出的需求进行设计,不要过多的考虑目前没有提到的功能。
5、如何统一
细心的读者看到这里可能已经是疑窦丛生了。一边是鼓励使用、设计最完美的方案;另一方面,又强调简单。似乎是自我矛盾。不错这其中是由矛盾的地方,但也有一致的地方。因此,在使用先进的模式和保持设计的简单性之间,我们需要权衡。
一次,我们看到了一个关于权限设置的模式,我们觉得这个模式非常的好,它提供了类似于UNIX操作系统那样的权限控制,可以很随意的增加组、用户,并能够在文件级别上设置权限。我们如获至宝,觉得这是一个非常有用的模式。于是,我们花了一些时间将之实现,并打算应用于新的软件中。
在实际中,我们发现没有一个用户需要如此强大的功能,他们所需要的可能仅是密码控制,或是简单的用户管理。如此复杂的功能对他们来说没有任何的意义。完美的模式在现实中遭到了冷遇。
实际上,用户目前不需要这项功能,并不意味着他以后不需要这项功能。用户的计算机程度提高的很快,我们估计,再过那么一两年,用户可能就非常需要这项功能来管理他那日益庞大的员工队伍了。但是目前,这项功能对用户来说,设置复杂,所以他们并不愿意接受这个"有价值"的功能。
最后,我们想到了一个解决的办法,我们为这一项功能定义了一个通用的接口。通过这个接口,你可以实现复杂的功能,也可以实现简单的功能。总之,你只要是实现了接口的方法就行了。接口的方法很多,但是在目前的简单的实现中,可能就仅仅是一个返回语句,并没有很多的实现。相应的,用户的也仅仅需要使用简单的方法,诸如addUser(),updatePasswd()等。界面也做了简化的处理。
通过这种方法,我们可以在用户需要的时候,替换掉权限模块,对其它的应用并不影响。当然,其中有很多的细节需要注意。在完成之后,我们还发现了另一个副产品:整个的权限控制模块是高内聚,低耦合的。
模式,就好比螺帽的设计图纸,它规定了螺帽的技术规格,但是没有规定具体的尺寸。对应于不同的需要,我们可以设计出不同大小的螺帽以供使用。图纸只需要一份就可以了,并不需要为每一种尺寸的螺帽画一张图纸。
因此呢,一个经历了实践检验的模式,往往功能强大。但是它可以有多种不同的实现。有哪一条法律规定你必须完全的实现一种模式呢。在实际使用中,你需要权衡模式使用的成本和效益。你会发现,在很多情况下,你还是实现了模式,但只是模式的一个框架,或一部分,但是这在目前就够用了。而当需求变动,或新的需求出现的时候,你可以很方便的在原有搭起的框架上添砖加瓦。一切都是那么的自然。比如,在一个进销存的软件中,存在一个运输选择算法,目前的运输途径就一种,但是很有可能会增加新的途径。这时候,你就决定采用Strategy模式。但是你只是实现了一个简单的框架,只有一个具体子类,来实现目前的算法。当新的运输途径出现时,你需要增加一个算法,你就可以再增加一个子类,只要实现的接口相同,改动是不会影响到系统其它的部分的。
6、测试
测试是非常重要的,是软件成败的关键。但是目前国内对测试并不关注,或是假装关注。这样就无法保证软件的质量。测试有很多种,我们这里要说的是和需求息息相关的测试,就是接收测试(Acceptance Test)(关于这个词,可能不同的文章会有不同的译法)。
Surely you aren't going to assume you're getting what you need. Prove that it works! Acceptance tests allow the customer to know when the system works, and tell the programmers what needs to be done.
上面这段话摘自『XPInstalled』。接收测试有两个作用:首先是让客户明白系统能够做什么,然后是让程序员明白该让系统做些什么。
有一种测试的方法是把测试留到最后才做,让客户去发现错误。千万别这么做。原先花费1块钱就可以改正的错误,到了这个时候,可能需要花费1000块钱才能解决。这是软件开发的放大效应。因为很多的工作已经基于这个错误建立了,开发人员也已经对这个错误没有映像了。
XP中有一个很重要的价值,叫做反馈(Feedback)。Kent Beck在Extreme Programming Explained中有句话讲得非常好:"乐观是编程的职业病,反馈则是其处方。"从需求的识别,到根据需求构建的系统交付给客户,客户提出意见。这就是一个反馈过程。反馈过程所花费的时间越少越好。接受测试就是解决客户反馈的一个有效的手段。客户编写可重复的测试脚本,开发人员开发出的软件要经受这个测试脚本的考验。这种的反馈速度是很高的,能够有效的解决反馈的问题。
因此,客户在要求实现需求时,同时也有义务提供相关的接收测试:
if it's worth having the programmers build it, it's worth knowing that they got it right.
一个有价值的功能一定是可测试的,如果不是,那么这个功能要么是没有价值,要么是尚未描述清楚。
要注意,这个测试必须是可重复的。这是因为需求的易变性。需求在不断变化,这就意味着代码在不断的变化。因此,原先已经用接收测试证明过了的代码还需要再次证明。这就要求测试是可以重复的。
大量的测试,甚至重复的测试引出了一个新的问题:全凭手工进行测试会浪费大量的时间。因此,易变的需求对测试提出了一个新的要求:自动化测试。只有自动化的进行测试,才可以完成如此大量的测试工作。目前,最好的自动化测试工具,应该就是Xunit系列。关于这方面的问题,大家可以参考相关的资料,这里我们不作深入的讨论。
接收测试最可能的一种形式就是自然语言的说明,外带一组的测试数据。需要强调的一点是,这个测试数据一定要包括输入和输出。这样才可以做出比较。如果只有输入没有输出。测试很可能就是白费劲。所以,计算这个输出是手工计算的,它也是必要的。
除了接收测试,还有一个很重要的概念就是单元测试(Unit Test)。但是单元测试和设计的关系比较大,和需求没有过多的关系,我们这里就只是点一下。大家如有兴趣,可以参考相关的资料。
7、分解
对于需求来说,需要用到的最多的技能可能就是分解的技能了。可以说软件科学最重要的思想就是"分而治之"的思想。不是吗?面向对象是不是一种分解的思想。类、组件、包,这种层级结构不正是体现了"分而治之"吗?当然我这里可能把包和组件弄混淆了。但我的主要目的是要指出这种分解的方法在软件开发中是无处不在的。对于需求也是一样。我们最早做的业务建模就是为了得到一个系统的概貌图。然后到了细节需求阶段,我们会把这张图放大,细分,一直到我们有把握处理为止。
如何把100块砖累起来呢?如果一块一块的累,那很容易就倒了。一种比较好的做法,就是先10块10块的打包,这样,100块砖就变成了10个砖包,再把它们累起来就容易的多了。面向对象其实就是这么做的,当然,面向对象的实现比累砖要难多了。
我们看看XP中是如何处理分解的。XP中最大的周期叫做发布版(release),一个发布版需要一个月或几个月的时间,一般不超过6个月。发布版的末期,需要向客户提供一个可以运行的软件的发布版。然后,XP还定义了次级的周期,称为迭代(iteration),一次的迭代大概需要一周或几周的时间。每一次的迭代都是一个"伪发布版"(pretend release),就是说,迭代的最后也必需要提供一个可以工作的软件,这个软件随时都可以发布。为了定义一次迭代中要处理的事情,XP还定义了素材(story),一份素材代表了客户希望在软件中出现的一项功能(feature),一份素材是很小的,它只需要花费一个开发人员几天或几周的时间。素材已经很小了,但是还需要细分到任务(task),一项任务只需要1到4天的工作量。这并不是最小的单位,XP还把任务划分到测试(test),但这已经到个人级别上了。
我们看到,XP从客户到每一个开发人员,定义了5级的单位,并把时间精确到了天、小时。所以我有时候听人说,XP好像对开发人员的要求不严格。错了,XP可以说是目前要求最为严格的方法,这种分类方法可见一斑。这种分类有什么好处呢?
首先,我们来看发布版,发布版的最短时间是一个月,也就是说,最频繁是一个月向客户交付一次软件。这样,就在很大程度上保证了反馈的迅速进行。避免了传统的开发方法中最后客户发现问题时已经太迟了的现象。
再看迭代,迭代之所以被称为伪发布版,就是因为它的产出物的性质和发布版是一样的。都是可以交付的产品,但是迭代的功能比较少,没有必要交付给客户。我们知道,在传统的软件开发中,整合是一个大问题。整合必然会出现问题,但是没人知道问题在哪儿。所以呢,XP通过不间断的整合,避免了这个问题。
但是,迭代的周期如此之短,能够做些什么呢。这就是素材出现的原因。素材由客户提出,由客户决定优先级,由客户决定放在哪一次的发布版和迭代中。同时,如上面我们谈到的,客户需要为素材制定接收测试。
一份素材的周期是几天或几周,而一次迭代的时间也就几周。这说明素材对迭代而言,单位过大了。所以要把素材再次分解为任务。每一个任务都需要一个开发人员认领,签字。在分解素材的过程中,我们可以发现有一些任务是多个素材共享的,这个概念和用例中的使用的概念是一致的。开发人员会估计自己的任务所需要的时间。从而得出一个迭代周期的总时间。这个时间的估计是基于以往的经验的,因此随着项目的进行,这个估计往往会越发的准确。
我们这里讲XP的分解哲学,并不是要求大家也依样画葫芦,你真要那样做也不行。因为XP的各项实践都是一体的,只有实现了所有的实践,才能体现其威力。我们这样断章取义是行不通的。但是其中的思想我们是可以借用的。分解、归类、排序、估计。这种分析问题的方法,也是我们值得借鉴的。这里有几点要注意:
最早的分解依据往往是客户要求的时间。例如,客户希望在3个月内看到什么什么。在客户和开发放商议之后,决定制定两次的发布版。这个决定虽然开发方可以提供参考意见,但是决定权在客户方;
素材的提出,素材的优先级,素材的安排,这些都是客户的权利。客户也有权利取消、增加、修改素材,或是改变其优先级;
客户投入多少,就能够看到多少的软件。客户也可以取消目前的项目,而且,先前的投资也会有相应部分的软件产出;
对于开发时间的估计是开发人员的权力,其它任何强加于开发人员的时间安排都是不对的;
任务的选择也是出于开发人员自愿的原则;
如果开发人员估计出的总的时间和迭代的预计的时间有出入,绝对不能牺牲开发人员的额外时间换取迭代在限定时间内完成。这种做法无异于饮鸩止渴。比较好的做法是去掉一些任务。
8、客户如何参与
这是一个纯粹的补充问题。一次,一位读者写信来问我,中国的客户素质比较低,对计算机不了解,XP强调的现场客户现实中根本做不到。
XP要求开发人员在开发软件的过程中随时予以支持。诚然,要做到这一点是很难的。我自己也遇到过这种难题,知道问题的棘手程度。我想,这个问题可以分为两个方面。
一种是定制的软件。对于这种项目,你需要解决用户的参与问题,往往客户方的老总愿意投入资金,但是却不愿意投入支持的人力。我也曾见过客户方专门招了一个应届生来对付需求的情况。遇到这种情况,如果你没有能力克服它,那么这个项目绝对是失败的。即便项目最后成功了,申请了什么"重大攻关"之类的奖项,你我都很清楚,这只不过是表面功夫而已。造成这种问题的原因有很多,你需要分析它们,列举出最深层的原因,并且保证列出的这些原因之间并不会相互影响。然后再试着来解决它。一般而言,如果客户方是真正愿意实现这个软件的话,事情并不是不可解决的。
另一种是产品化的软件。我们可以把这种软件的客户分为三类:市场人员、领域专家、最终用户。市场人员往往对软件有最初的认识,但是这种认识往往不够深入。所以,在开发产品化的软件时,一定要配备专门的市场人员,他们对客户的需求最了解,是需求的第一手来源。既然你的老板想要开发这个软件,说明对软件的未来市场有期待,市场人员加入的要求应该是可以得到满足的。其次是领域专家,现在很多的软件公司都配备有领域专家,他们的作用可不小,和市场人员相比,他们也同样熟悉需求,因为他们自己就是资深的用户,并且他们还熟悉理论,能够为软件开发出大力气。最后是最终用户,前面的两类人的参与还不够,如果最终用户不认可软件,那还是没有用。所以,要求市场人员找寻可能的目标客户,试用软件,提出意见,是非常重要的。我们常说的Beta测试也就是这样做的。
9、结语
最早这片文章的想法是来自于一个信贷系统(以文章的观点来看,这个系统是一个失败的案例)。除此之外,还加上了一些以前的项目的经验,以及朋友的一些经验。最后综合成了这一篇文章。
这个系列的文章的写作时间的跨度很长。在这个期间,我的思想也经历一个很大的转变,所以在写作中也出现过对已经完稿的部分大肆删修的情况。这篇文章虽名为『需求的实践』,但所提到的各种想法、方法,都有理论的依据。当然也是参考了很多的资料。而我个人的能力又极为有限,所以有些时候是心有余而力不足。在这样的情形下,文章难免会出现很多的错误。还希望能得到读者们的谅解和指正。
在写作的过程中,也有很多的热心人写来信件,其中好些还成为了好朋友。曾经想把里面的问题整理出来,但是由于疏忽,其中的一部分已经找不到了。希望还能有机会做这件事情。
参考资料:
Karl Wieger:《Software Requirements》
Scott W. Ambler: AgileModeling: http://www.agilemodeling.com
Scott W. Ambler: The Object Primer 2nd Edition
Jacobson, I., Booch, G., and Rumbaugh, J. (1999). The Unified Software Development Process
GOF:《Design Patterns: Elements of Reusable Object Oriented Software》
Eric Gamma, Kent Beck: Junit: http://www.junit.org
Kent Beck,Martin Fowler:《Planning Extreme Programming》

作者简介:
林星,辰讯软件工作室项目管理组资深项目经理,有多年项目实施经验。辰讯软件工作室致力于先进软件思想、软件技术的应用,主要的研究方向在于软件过程思想、Linux集群技术、OO技术和软件工厂模式。您可以通过电子邮件 [email protected] 和他联系。
 

本文地址:http://com.8s8s.com/it/it26239.htm