UML软件工程组织 |
需求的实践 细节需求时期(下) |
IBM DW中国站点 |
和业务建模时期不同的是,我不再花费笔墨讨论需求要如何做,因为做法、注意点和业务建模时期并没有什么太大的区别。而在完整的流程上,像RUP、XP之类的方法学可比我讲的要好的多。因此,我会把焦点集中在我在实际工作中的一些困惑,以及一些思考。 1、"和其它阶段的关系"的再思考。 各个阶段的实质就是注重点的不同,这对于大多数的软件开发而言都是一样的。不论你采用的过程是传统的,还是迭代的。 2、架构 架构并不神秘,无非是一个决策而已,只是这项决策对软件特别重要就是了。软件开发人员可能根本没有主动的进行架构设计,但是他的行为,已经潜移默化的进行了;而还有一些人,总在谈论着架构,但是并不了解这个词的含义。 春运就要到了,学生也要赶着回家。如何选择回家的交通工具就是一个重要的决策。路程的远近、不同交通工具的价格都是显式的,比较容易知道的。而以往的经验也告诉你,火车票比较便宜,但是比较紧张,花费时间较长,整个过程也不舒服;飞机票比较贵,但是容易买到,花费时间少,整个过程很舒服。这时候你就要做出正确的决策,为回家选择一个正确的架构。你可能考虑的因素有哪一些?以下就列出了一些可能的因素: 拥挤程度,大家都知道春运时那种情况; 根据这些因素,以及这些因素对你的影响程度,即优先级,你可以自己估算出一个或几个可能的架构方案。而这种架构的选择,直接影响到你之后的行为,也影响到行为的结果。 开发软件和买票回家又能有什么区别呢?一样要考虑成本、结果、时间。所不同的只是复杂了:需要专业技能,有很多不确定的因素。 那么我这里谈论架构的问题,和需求有什么关系呢?在上面的例子中,大家可以看到架构是根据什么决定的?是因素。因素的本质是什么?就是需求。因素,就是需求。所以,需求决定架构。上一篇中,我谈到说,在进行细节需求之前,一定要定出架构。当然,这时的架构可能只是一张草图。为什么?因为我们已经进行了业务建模,对项目有了一定的认识,对用户的需求也有一定的把握,成本、范围、时间等要素也都清楚了(如果你还不了解这些,请你回到业务建模阶段,你的工作还没有结束)。这个时候,决定架构的因素已经形成了,可以进行架构的设计了。 需求能够决定架构,架构反过来也能够影响需求。最明显的一个例子就是用户界面的设计。虽然用户界面主要来自于需求,但是不同的架构对用户界面也会有影响,例如基于浏览器的客户端,和基于Windows界面客户端能够提供的界面就不同。 在XP中,这种的架构设计,被称为Architecture Spike。为什么叫做Spike呢?就是说你需要专研,解决一些主要的问题,但你并不是提供一个完整的解决方案。例如,在项目的初期,如果你对新近的服务器和操作系统不了解,你肯定会花时间去了解,去试用,去测试;如果对数据库不了解,你也肯定会试着使用看看。这种行为,就是Spike。所以呢,架构的设计只是很初步的设计,而不是一个完善、定型了的设计。这一点要注意。 架构的选择和开发人员的经验和能力非常有关系。一般来说,它需要开发人员具有相关的经验。提供架构的厂商多如牛毛,如何选择,也是一项学问。比如,数据仓库的平台,选择的品种就很多;而Web Server的选择也是五花八门;操作系统也是一样。这些又都是和架构息息相关的。 3、模式 "每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心,这样,你就能一次又一次的使用该方案而不必做重复的劳动"[AIS,77] 这句话源自模式的鼻祖――Christopher Alexander。而在软件开发领域,最值得一提的著作,就是GoF写的『设计模式』一书。在该书中,作者描述了23种的设计模式,可以说,这些模式奠定了面向对象设计的基础。而另一本值得阅读的著作,就是Martin Fowler所著的『分析模式』。 在软件设计中,我们遇到各种各样的问题,我们可能缺乏经验,或能力有限。这非常的正常。但是现实是,我们生产出的代码由于设计方面的缺陷,往往不够清晰,容易出错,难以扩展。相信只要是开发过软件的人,都遇到过这种问题。于是,我们就希望能够看看其他人,是如何处理这种问题的。这里的"其他人"指的可能是技术专家,也可能是经历过同种问题的人,他们对你遇到的问题有能力,有经验来解决。他们提出的解决方案往往是非常成熟的,能够解决你目前遇到的问题,也能够解决你目前尚未遇到的问题。 这对你的吸引力是很大的。那么,我们谈论模式,模式来源于何处呢。注意,模式是针对某一类的问题的解。这里的问题,所指的就是需求。比如说,客户希望能够在软件中实现不同的税率计算方法,那么,我们很自然的就可以想到Strategy模式;当客户的产品有一个很复杂的单位换算机制的之后,我们也能够很自然的想到Quantity模式。使用模式,能够使我们迅速的把握需求的解决方法。另一方面,模式往往告诉我们比目前的问题更多的方面,因为模式都是大家的经验沉淀。如上所说,它还可以解决你目前没有遇到的问题。因此,我们还可以从模式中发现出更深的需求。 另外一点也很重要,虽然它和需求的关系不大。模式往往都有一个模式名称。这就形成了一种沟通的语言。比如我们在下象棋的时候,只要说"马后炮",谁都知道这是什么意思,绝对不需要呢详细的解说每一步棋子的走法。对于软件开发也是一样的。我和我的同伴会心的一笑,说:"Factory Method。"两个人都能够理解这是什么意思,因为这是一种共通的语言,它代表了背后隐藏的各种类的关系和代码实现。这在软件开发中非常的重要。当然,这有个前提,大家都对模式有一个通透的了解。 4、简单设计 很多的软件人员都是完美主义者,他们喜欢完美的设计,然后把这种设计提供给用户。这种思想就是过分设计的开始。不必要的功能浪费了客户的投资。我们在做需求的时候,很经常发现开发人员随意的向客户推销一些新功能,或是在设计时,过多的考虑未来可能出现的需求变动。 所以,简单设计的意思,就是要针对目前客户提出的需求进行设计,不要过多的考虑目前没有提到的功能。 5、如何统一 在实际中,我们发现没有一个用户需要如此强大的功能,他们所需要的可能仅是密码控制,或是简单的用户管理。如此复杂的功能对他们来说没有任何的意义。完美的模式在现实中遭到了冷遇。 实际上,用户目前不需要这项功能,并不意味着他以后不需要这项功能。用户的计算机程度提高的很快,我们估计,再过那么一两年,用户可能就非常需要这项功能来管理他那日益庞大的员工队伍了。但是目前,这项功能对用户来说,设置复杂,所以他们并不愿意接受这个"有价值"的功能。 最后,我们想到了一个解决的办法,我们为这一项功能定义了一个通用的接口。通过这个接口,你可以实现复杂的功能,也可以实现简单的功能。总之,你只要是实现了接口的方法就行了。接口的方法很多,但是在目前的简单的实现中,可能就仅仅是一个返回语句,并没有很多的实现。相应的,用户的也仅仅需要使用简单的方法,诸如addUser(),updatePasswd()等。界面也做了简化的处理。 通过这种方法,我们可以在用户需要的时候,替换掉权限模块,对其它的应用并不影响。当然,其中有很多的细节需要注意。在完成之后,我们还发现了另一个副产品:整个的权限控制模块是高内聚,低耦合的。 模式,就好比螺帽的设计图纸,它规定了螺帽的技术规格,但是没有规定具体的尺寸。对应于不同的需要,我们可以设计出不同大小的螺帽以供使用。图纸只需要一份就可以了,并不需要为每一种尺寸的螺帽画一张图纸。 因此呢,一个经历了实践检验的模式,往往功能强大。但是它可以有多种不同的实现。有哪一条法律规定你必须完全的实现一种模式呢。在实际使用中,你需要权衡模式使用的成本和效益。你会发现,在很多情况下,你还是实现了模式,但只是模式的一个框架,或一部分,但是这在目前就够用了。而当需求变动,或新的需求出现的时候,你可以很方便的在原有搭起的框架上添砖加瓦。一切都是那么的自然。比如,在一个进销存的软件中,存在一个运输选择算法,目前的运输途径就一种,但是很有可能会增加新的途径。这时候,你就决定采用Strategy模式。但是你只是实现了一个简单的框架,只有一个具体子类,来实现目前的算法。当新的运输途径出现时,你需要增加一个算法,你就可以再增加一个子类,只要实现的接口相同,改动是不会影响到系统其它的部分的。 6、测试 上面这段话摘自『XPInstalled』。接收测试有两个作用:首先是让客户明白系统能够做什么,然后是让程序员明白该让系统做些什么。 有一种测试的方法是把测试留到最后才做,让客户去发现错误。千万别这么做。原先花费1块钱就可以改正的错误,到了这个时候,可能需要花费1000块钱才能解决。这是软件开发的放大效应。因为很多的工作已经基于这个错误建立了,开发人员也已经对这个错误没有映像了。 XP中有一个很重要的价值,叫做反馈(Feedback)。Kent Beck在Extreme Programming Explained中有句话讲得非常好:"乐观是编程的职业病,反馈则是其处方。"从需求的识别,到根据需求构建的系统交付给客户,客户提出意见。这就是一个反馈过程。反馈过程所花费的时间越少越好。接受测试就是解决客户反馈的一个有效的手段。客户编写可重复的测试脚本,开发人员开发出的软件要经受这个测试脚本的考验。这种的反馈速度是很高的,能够有效的解决反馈的问题。 因此,客户在要求实现需求时,同时也有义务提供相关的接收测试: 一个有价值的功能一定是可测试的,如果不是,那么这个功能要么是没有价值,要么是尚未描述清楚。 要注意,这个测试必须是可重复的。这是因为需求的易变性。需求在不断变化,这就意味着代码在不断的变化。因此,原先已经用接收测试证明过了的代码还需要再次证明。这就要求测试是可以重复的。 大量的测试,甚至重复的测试引出了一个新的问题:全凭手工进行测试会浪费大量的时间。因此,易变的需求对测试提出了一个新的要求:自动化测试。只有自动化的进行测试,才可以完成如此大量的测试工作。目前,最好的自动化测试工具,应该就是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要求开发人员在开发软件的过程中随时予以支持。诚然,要做到这一点是很难的。我自己也遇到过这种难题,知道问题的棘手程度。我想,这个问题可以分为两个方面。 一种是定制的软件。对于这种项目,你需要解决用户的参与问题,往往客户方的老总愿意投入资金,但是却不愿意投入支持的人力。我也曾见过客户方专门招了一个应届生来对付需求的情况。遇到这种情况,如果你没有能力克服它,那么这个项目绝对是失败的。即便项目最后成功了,申请了什么"重大攻关"之类的奖项,你我都很清楚,这只不过是表面功夫而已。造成这种问题的原因有很多,你需要分析它们,列举出最深层的原因,并且保证列出的这些原因之间并不会相互影响。然后再试着来解决它。一般而言,如果客户方是真正愿意实现这个软件的话,事情并不是不可解决的。 另一种是产品化的软件。我们可以把这种软件的客户分为三类:市场人员、领域专家、最终用户。市场人员往往对软件有最初的认识,但是这种认识往往不够深入。所以,在开发产品化的软件时,一定要配备专门的市场人员,他们对客户的需求最了解,是需求的第一手来源。既然你的老板想要开发这个软件,说明对软件的未来市场有期待,市场人员加入的要求应该是可以得到满足的。其次是领域专家,现在很多的软件公司都配备有领域专家,他们的作用可不小,和市场人员相比,他们也同样熟悉需求,因为他们自己就是资深的用户,并且他们还熟悉理论,能够为软件开发出大力气。最后是最终用户,前面的两类人的参与还不够,如果最终用户不认可软件,那还是没有用。所以,要求市场人员找寻可能的目标客户,试用软件,提出意见,是非常重要的。我们常说的Beta测试也就是这样做的。 9、结语 在写作的过程中,也有很多的热心人写来信件,其中好些还成为了好朋友。曾经想把里面的问题整理出来,但是由于疏忽,其中的一部分已经找不到了。希望还能有机会做这件事情。 参考资料: Karl Wieger:《Software Requirements》
|
版权所有:UML软件工程组织 |