2.2 软件过程模型
软件工程(第4版•修订版)
软件工程文献描述了很多软件过程模型。有些模型是规定性的(prescription),说明软件开发应该进行的方式;而另一些是描述性的(description),说明软件开发实际进行的方式。从理论上讲,两种类型的模型应该是相似或相同的,但事实并非如此。建立过程模型并讨论它的子过程有助于开发团队理解开发过程的理想情况与实际情况之间的差距。
对过程进行建模的原因还有很多。
当一个小组记录下开发过程的描述时,就会形成对软件开发中的活动、资源和约束的共同理解。
建立过程模型有助于开发团队发现过程及其组成部分中存在的不一致、冗余和遗漏的地方。当注意并改正了这些问题以后,过程会变得更加有效并且集中在构建最终产品上。
模型应该反映开发的目标,例如构建高质量的软件、在开发的早期发现故障以及满足必需的项目预算和开发进度的约束。由于建立了模型,开发团队可以根据目标评估候选活动是否合适。例如,开发团队可能引入需求评审,这样可以在设计开始之前发现和修复需求中的问题。
应当根据具体情况对每一个过程进行裁剪。建立过程模型有助于开发团队理解应该在哪里对过程进行裁剪。
每一个软件开发过程模型都将系统需求作为输入,将要交付的产品作为输出。多年来,人们提出了很多模型。这里探讨几种最流行的模型,以理解它们之间的共性和区别。
2.2.1 瀑布模型
研究人员提出的第一个模型是瀑布模型(waterfall model),如图2-1所示,它将开发阶段描述为从一个阶段瀑布般地转换到另外一个阶段(Royce 1970)。如该图所提示的,一个开发阶段必须在另一个开发阶段开始之前完成。因此,当从客户引发的所有需求都已经过完整性和一致性分析,并形成需求文档之后,开发团队才能够开始进行系统设计活动。瀑布模型从一种非常高层的角度描述了开发过程中进行的活动,并且提出了要求开发人员经过的事件序列。
瀑布模型一直被用来规范软件开发活动。例如,美国国防部标准2167-A规定,瀑布模型是多年来国防部合同中软件开发交付的依据。每一个过程活动都有与其相关联的里程碑和可交付产品,以便于项目经理能够用模型判断在某一时刻项目离最后完成还有多远。例如,在瀑布模型中,“单元测试和集成测试”阶段结束的里程碑是“编写完经过测试和集成的代码模块”,其中间可交付产品是测试过的代码的副本。接着,代码被移交给系统测试人员,这样它可以与其他系统构件(硬件或软件)合并,并作为一个整体进行测试。
在帮助开发人员布置他们需要做的工作时,瀑布模型是非常有用的。它的简单性使得开发人员很容易向不熟悉软件开发的客户做出解释。它明确地说明,为了开始下一阶段的开发,哪些中间产品是必需的。很多其他更复杂的模型实际上是在瀑布模型的基础上的润色,如加入反馈循环以及额外的活动。
瀑布模型的很多问题已经在计算机文献中讨论过,补充材料2-1总结了其中的两个问题。瀑布模型最大的问题是它并不能反映实际的代码开发方式。除了一些理解非常充分的问题之外,实际上软件是通过大量的迭代进行开发的。通常情况下,软件用于解决以前从未解决过的问题,或者其解决方案需要更新以反映业务情况或操作环境的变化。例如,一个飞机制造商需要一种关于新型机体的软件,它要比当前的型号更大、更快。对于这种情况,即使软件开发人员在开发航空软件方面积累了大量的经验,他们仍然面临很多新的挑战。用户和开发人员都不完全了解影响期望结果的所有关键因素,并且在需求分析过程中花费的大量时间都用在了理解受系统及其软件影响的项和过程上,以及系统及其运行环境之间的关系上,就像在第4章将要看到的那样。因此,如果不对实际的软件开发过程加以控制,开发过程可能看起来会像图2-2那样:当开发人员试图搜集关于问题以及提议的解决方案如何解决该问题的有关资料时,他们会翻来覆去地从一个活动转向另一个活动。
补充材料2-1 瀑布模型的缺点
自从瀑布模型提出以来,招致了众多的批评。例如,McCracken和Jackson指出,瀑布模型在系统开发之上强加了一种项目管理结构(McCracken and Jackson 1981)。“主张任何一种生命周期方案(即使它具有各种变种)能够适用于所有的系统开发显然是违背现实的,或者由于假定一个过于简陋的生命周期而显得毫无意义。”
注意,瀑布模型说明了每一个主要开发阶段是如何终止于某些制品(例如需求、设计或代码)的,但并没有揭示每一个活动如何把一种制品转化为另外一种制品,例如,从需求转化为设计。因此,对于如何处理在开发过程中可能出现的产品和活动的变化,模型并没有向管理者和开发人员提供相关指导。例如,当在编码活动的过程中发生需求变化时,随之带来的设计和编码的变化并没有在瀑布模型中加以强调。
Curtis、Krasner、Shen和Iscoe指出,瀑布模型的主要缺点是没有把软件看作一个问题求解的过程(Curtis, Krasner, Shen and Iscoe 1987)。瀑布模型产生于硬件领域,它是从制造业的角度看待软件开发的。但是,制造业是重复生产某一特定的产品,而软件并不是这样开发的,相反,随着人们对问题的逐步理解和对候选方案的评估,软件在不断演化。因此,软件是一个创造的过程,而不是一个制造的过程。瀑布模型并没有说明我们创建最终产品过程中所需的往返活动的任何特有信息。尤其是创造通常包含不同的尝试、开发和评估原型、评价需求的可行性、比较若干种设计以及从失败的教训中学习,从而最终决定问题令人满意的解决方案。
通过引入加强理解的活动和子过程,软件开发过程有助于控制活动之间的往返。原型化就是这样的一个子过程。原型(prototype)是一个部分开发的产品,它使客户和开发人员能够对计划开发的系统的相关方面进行检查,以决定它对最终产品是否合适或恰当。例如,开发人员可以构建一个系统来实现一小部分关键需求,以确保需求是一致、可行和符合实际的。否则,在需求阶段就要进行修正,而不是在测试阶段(测试阶段代价会更高)进行修正。同样,设计的某些部分也可以进行原型化,如图2-3所示。设计的原型化有助于开发人员评价可选的设计策略以及决定对于特定的项目,哪一种策略是最好的。正如我们将在第5章中看到的,设计人员可能用几种完全不同的设计来处理需求,看一看哪一种具有最好的特性。例如,可以在一个原型中把网络设计为环形的,而另一个设计为星形的。然后评价其性能特性,看一看哪一种结构能更好地满足性能目标或约束。
通常,开发人员会构建用户界面,并把它作为原型进行测试,以便用户能够了解新系统将会是什么样子的,并且设计人员也能够更好地理解用户希望如何与系统进行交互。因此,在系统测试进行正式确认之前,主要的需求应该都已经过处理和确定。确认(validation)确保系统实现了所有的需求。每一个系统功能可以回溯到系统规格说明中的一个特定需求。系统测试也对需求进行验证,验证(verification)确保每一项功能都是正确的。也就是说,确认保证开发人员构造的是正确的产品(根据规格说明),而验证检查实现的质量。原型化对于验证和确认都很有用。但是,我们将在后面的章节中看到,这些活动也可以出现在开发过程的其他部分中。
2.2.2 V模型
V模型是瀑布模型的变种,它说明测试活动是如何与分析和设计相联系的(German Ministry of Defense 1992)。如图2-4所示,编码处于V形符号的顶点,分析和设计在左边,测试和维护在右边。正如我们将在后面的章节中看到的那样,单元测试和集成测试针对的是程序的正确性。V模型提出,单元和集成测试也可以用于验证程序设计。也就是说,在单元和集成测试的过程中,编码人员和测试小组成员应当确保程序设计的所有方面都已经在代码中正确实现。同样,系统测试应当验证系统设计,保证系统设计的所有方面都得到了正确实现。验收测试是由客户而不是开发人员进行的,它通过把测试步骤与需求规格说明中的每一个要素关联起来对需求进行确认。这种测试检查在接受系统和付款之前,所有需求是否都已经完全实现。
该模型中连接V形符号左边和右边的连线意味着,如果在验证和确认期间发现了问题,那么在再次执行右边的测试步骤之前,重新执行左边的步骤以修正和改进需求、设计和编码。换言之,V模型使得隐藏在瀑布模型中的迭代和重做活动更加明确。瀑布模型关注的通常是文档和制品,而V模型关注的则是活动和正确性。
2.2.3 原型化模型
我们已经看到如何使用原型化活动修正瀑布模型以改进对系统的理解。但是原型化不仅仅是附属于瀑布模型的,如图2-5所示,它本身也是一种有效的过程模型的基础。由于原型化模型允许开发人员快速构造整个系统或系统的一部分以理解或澄清问题,因此,它与工程化原型具有同样的目的,其中需要对需求或设计进行反复调查,以确保开发人员、用户和客户对需要什么和提交什么有一个共同的理解。依据原型化的目标,可以取消原型化需求、设计或系统中的一个或多个循环。但是,总体目标保持不变,即减少开发中的风险和不确定性。
例如,系统开发可能以客户和用户提出的一组需求为起点,然后,让相关各方一起探讨各种方案,查看可能的屏幕显示、表格、报表以及用户和客户直接使用的其他系统输出。当用户和客户对需要什么做出决定时,对需求进行修正。一旦对需求应该是什么达成了共识,开发人员就可以进行设计了。再次通过同样的过程,开发人员与客户和用户协商来探讨不同的设计。
对初始设计不断修正,直到开发人员、用户和客户对结果满意为止。实际上,考虑不同的设计方案有时会暴露需求中的问题,此时开发人员就需要退回到需求阶段,重新考虑和变更需求规格说明。最后,对系统进行编码并讨论不同的编码方案,还可能对需求分析和设计进行迭代。
2.2.4 可操作规格说明
对许多系统来说,需求的不确定性导致了后期开发的变化和问题。Zave提出了一种过程模型,它允许开发人员和客户在开发的早期检查需求及其隐含含义,在这个过程中,他们可以讨论和解决某些不确定性(Zave 1984)。在可操作规格说明模型(operational specification model)中,通过演示系统行为的方式来评估或执行系统需求。也就是说,一旦指定了需求,就可以用软件包进行演示。这样,在设计开始之前就可以评价它们的隐含含义。例如,如果规格说明要求计划构建的系统能够处理24个用户,规格说明的可执行形式就能够帮助分析人员确定用户数目是否给系统增加了太多的性能负担。
这种模型的过程与诸如瀑布模型这样的传统模型有很大的不同。瀑布模型把系统的功能与设计分离(即把系统要做什么与系统如何做分离开),目的是把客户的需要与实现分开,而可操作规格说明模型允许把功能和设计合并起来。图2-6说明了可操作说明模型是如何运作的。注意,可操作规格说明模型与原型化模型类似,该过程允许用户和开发人员在早期检查需求。
2.2.5 可转换模型
Balzer的可转换模型(transformational model)通过去除某些主要开发步骤来设法减少出错的机会。利用自动化手段的支持,转换过程使用一系列转换把需求规格说明变为一个可交付使用的系统(Balzer 1981a)。
转换的样例有:
改变数据表示;
选择算法;
优化;
编译。
由于从规格说明到可交付系统可以采取很多途径,它们所表示的变换序列和决策都保存为形式化的开发记录。
转换方法具有很好的前景。然而,如图2-7所示,应用转换方法的主要障碍在于需要一个精确表述的形式化的规格说明,这样才可以基于它进行操作。随着形式化规格说明方法的普及,转换模型将会被更广泛地接受。
2.2.6 阶段化开发:增量和迭代
在早期的软件开发中,客户愿意为软件系统的最后完成等待很长时间。有时,从编写需求文档到系统交付使用会经过若干年,称为循环周期(cycle time)。但是,今天的商业环境不会再容许长时间的拖延。软件使产品在市场上引人注目,而客户总是期待着更好的质量和新的功能。例如,1996年,惠普公司80%的收入来自过去两年开发的产品,因而,他们开发了新的过程模型来帮助缩短循环周期。
一种缩短循环周期的方法是使用阶段化开发,如图2-8所示。使用这种方法设计系统时使其能够一部分一部分地交付,从而在系统其余部分正在开发的同时,用户已经获得了一部分功能。因此,通常会有两个系统在并行运行:产品系统和开发系统。运行系统(operational system)或产品系统(production system)是当前正在被客户和用户使用的系统,而开发系统(development system)是准备用来替换现行产品系统的下一个版本。通常,用它们的发布代号表示一个系统:开发人员构建发布1,进行测试,然后把它交给用户作为第一个可运行的发布。然后,当用户使用发布1的时候,开发人员正在构建发布2。从而,开发人员总是在开发发布n+1,而与此同时发布n总是正在运行的。
开发人员可以用多种方法决定如何将开发组织为发布。增量开发(incremental development)和迭代开发(iterative development)是两种最常用的方法。在增量开发中,需求文档中指定的系统按功能划分为子系统。定义发布时首先定义一个小的功能子系统,然后在每一个新的发布中增加新功能。图2-9的上半部分显示了增量开发是如何在每一个新的发布中逐步增加功能直到构造全部功能的。
而迭代开发是在一开始就提交一个完整的系统,然后在每一个新的发布中改变每个子系统的功能。图2-9的下半部分说明一个迭代开发的3个发布。
为了理解增量开发和迭代开发之间的区别,我们来看一个用于文字处理的软件包。假设这个软件包要具有3种类型的功能:创建文本、组织文本(即剪切和粘贴)以及格式化文本(例如使用不同的字体大小和类型等)。要使用增量开发模型构建这样一个系统,我们可能在发布1中仅提供创建功能,然后在发布2中提供创建和组织功能,最后在发布3中提供创建、组织和格式化功能。但是,使用迭代开发方法时,我们要在发布1中提供简单的3种类型的功能。例如,可以创建文本,然后剪切并粘贴文本,但是剪切和粘贴功能可能不够灵活快捷。在下一次迭代(即发布2)中,提供相同的功能,但是系统的功能增强了:剪切和粘贴功能变得方便和快捷。每一个发布都在前一个发布的基础上进行了某些改进。
实际上,许多组织都将迭代开发和增量开发方法结合起来使用。一个新的发布版本可能包含新的功能,并且对已有功能做了改进。这种形式的阶段化开发方法是人们想要的,原因如下。
(1) 即使还缺少某些功能,但在早期的发布中就可开始进行培训。培训过程可以使开发人员观察某些功能是如何执行的,并为后面的发布提供了改进的建议。这样,开发人员能够很好地对用户的反馈做出反应。
(2) 可以及早为那些以前从未提供的功能开拓市场。
(3) 当运行系统出现未预料到的问题时,经常性的发布可以使开发人员能全面、快速地修复这些问题。
(4) 针对不同的发布版本,开发团队将重点放在不同的专业领域技术上。例如,一个发布可以利用用户界面专家的专业知识将系统从命令驱动的界面改为指向—点击式(point-and-click)的图形用户界面,另外一个发布可集中于改进系统性能。
2.2.7 螺旋模型
Boehm根据系统包含的风险看待软件开发过程并提出了螺旋模型。它把开发活动和风险管理结合起来,以将风险减到最小并控制风险(Boehm 1988)。图2-10所示的螺旋模型在某种意义上类似于图2-9所示的迭代开发模型。它以需求和一个初始的开发计划(包括预算、约束、人员安排方案、设计和开发环境)为起点,在产生“操作概念”文档(它从高层描述系统如何工作)之前,该过程插入一个评估风险以及可选原型的步骤。在操作文档中,一组需求被指定并进行详细检查,以确保需求尽可能完整和一致。因此,操作概念是第一次迭代的产品,而需求则是第二次迭代的主要产品。在第三次迭代中,系统开发产生设计,而第四次迭代能够进行测试。
螺旋模型的每一次迭代都根据需求和约束进行风险分析,以权衡不同的选择,并且在确定某一特定选择之前,通过原型化验证可行性或期望度。当风险确认之后,项目经理必须决定如何消除风险或使风险降到最低。例如,设计人员不能确定用户是否更喜欢某一种界面(相比较于另一种界面)。用户有可能会选择阻碍高效率使用新系统的界面,要把这种选择的风险最小化。设计人员可以原型化每一个界面,并通过运行来检验用户更喜欢哪一种界面。甚至可以在设计中选择包含两种不同的界面,这样用户能够在登录的时候选择其中一个。像预算和进度这样的约束有助于确定要选择哪一种风险管理策略。第3章将更详细地讨论风险管理。
2.2.8 敏捷方法
从20世纪70年代到90年代提出并使用的许多软件开发方法都试图在软件构思、文档化、开发和测试的过程中强加某种形式的严格性。在20世纪90年代后期,一些抵制这种严格性的开发人员系统地阐述了他们自己的原则,试图强调灵活性在快速有效的软件生产中所发挥的作用。他们将他们的思想整理为“敏捷宣言”,概括为以不同的方式思考软件开发的4条原则(Agile Alliance 2001)。
相对于过程和工具,他们更强调个人和交互的价值。这种观点包括给开发人员提供他们所需的资源,并相信他们能够做好自己的工作。开发团队将他们组织起来,让他们进行面对面交互式的沟通而不是通过文档进行沟通。
他们更喜欢在生产运行的软件上花费时间,而不是将时间花费在编写各种文档上。也就是说,对成功的主要测量指标是软件正确工作的程度。
他们将精力集中在与客户的合作上,而不是合同谈判上,从而,客户成为软件开发过程的一个关键方面。
他们专注于对变化的反应,而不是创建一个计划而后遵循这个计划,因为他们相信不可能在开发的初始就能预测到所有的需求。
敏捷开发的总体目标是通过“尽可能早地、持续地交付有价值的软件”使客户满意(Agile Alliance 2001)。很多客户都有一些随着时间变化的业务需求,不仅表现在新发现的需求上,也表现在对市场变化做出反应的需求上。例如,当软件正在设计和构造的时候,某一个竞争对手发布了一个新的产品,因此,需要在已经计划好的功能上做一些改变。类似地,政府机构或标准制订机构可能会强制推行一项规则或标准,而它可能影响到软件的设计或需求。人们认为,通过在软件开发过程中加入灵活性,敏捷方法使用户能够在开发周期的后期增加或改变需求。
在目前的文献中,有很多敏捷过程的典型方法。每一种方法都基于一套原则,这些原则实现了敏捷方法所宣称的理念(敏捷宣言)。具体方法有以下几种。
极限编程(XP):在下面会对它进行详细描述。它是激发开发人员创造性、使管理负担最小的一组技术。
水晶法(Crystal):它认为每一个不同的项目都需要一套不同的策略、约定和方法论。水晶法正是基于这一理念的一组方法。Cockburn是水晶法的创建者(Cockburn 2002)。他认为,人对软件质量有重要的影响,因而随着开发人员素质的提高,项目和过程的质量也随之提高。通过更好的交流和经常性的交付,软件生产力得以提高,因为它较少需要中间工作产品。
并列争球法(Scrum):该方法由对象技术公司于1994年创建,随后Schwaber和Beedle将它产品化(Schwaber and Beedle 2002)。它使用迭代的方法,其中把每30天一次的迭代称为一个“冲刺”(sprint),并按需求的优先级别来实现产品。多个自组织和自治小组并行地递增实现产品。协调是通过简短的日常情况会议(称为“scrum”)来进行的,就像橄榄球中的“并列争球”(scrum)。
自适应软件开发(ASD):它有6个基本的原则。在自适应软件开发中,有一个使命作为指导,它设立项目的目标,但并不描述如何达到这个目标。特征被视作客户价值的关键点,因此,项目是围绕着构造的构件来组织并实现特征的。过程中的迭代是很重要的,因此“重做”与“做”同样关键,变化也包含其中。变化不被视作改正,而是被视作对软件开发实际情况的调整。确定的交付时间迫使开发人员认真考虑每一个生产的版本的关键需求。同时,风险也包含其中,它使开发人员首先解决最难的问题。
通常,“极限编程”是描述敏捷方法最普遍的概念。实际上,XP是敏捷过程的一种具体形式,提供敏捷方法最一般原则的指导方针。XP的支持者强调敏捷方法的4个特性:交流、简单性、勇气以及反馈。交流是指客户与开发人员之间持续地交换看法;简单性鼓励开发人员选择最简单的设计或实现来处理客户的需要;XP创建者将勇气描述为尽早和经常交付功能的承诺;在软件开发过程的各种活动中,都包含反馈循环。例如,程序员们一起工作,针对实现设计的最佳方式,相互提供反馈;客户与开发人员一起工作,以完成计划的任务。
这些特性都包含在XP的12个实践操作中。
规划游戏:在XP的这一方面,由现场的客户定义价值的含义,以便对于每个需求,可以根据实现该需求所增加的价值对其进行评价。用户就系统应该如何运转来编写故事,然后,开发人员估算实现该故事所必需的资源。这些故事描述所涉及的演员和情节,很像在第4章和第6章定义的用例。每一个故事针对一个需求:只需要两三个句子足够详细地解释需求的价值,以便开发人员指定测试用例,估算实现需求所需的资源。故事编完之后,预期的用户对需求划分优先级,不断地拆分、合并需求,直到就需要什么、什么可测试、利用可用资源能够完成什么这些事项达成一致为止。然后,计划人员生成发布图,将发布的内容和交付的时间记录在文档中。
小的发布:系统的设计要能够尽可能早地交付。功能被分解为若干个小的部分,这样,可以尽早地交付一些功能。然后,在后面的版本中对这些功能加以改进和扩展。这些小的发布需要使用增量或迭代生命周期的阶段化开发方法。
隐喻:开发团队对于系统将如何运行的设想取得一致意见。为了支持这个共同的设想,开发团队选取共同的名字,并就处理关键问题的共同方法达成一致意见。
简单设计:只处理当前的需求,使设计保持简单。这种方法体现这样一个基本思想:对将来的需求进行预测可能导致不必要的功能。如果系统的某个特定部分是非常复杂的,那么开发团队可能要构建一个试验性解决方案(spike)(一个快速、有限的实现)以帮助决定如何继续进行。
首先编写测试:为了确保客户的需要成为开发的驱动力,首先编写测试用例,这是一种强迫客户需求在软件构建之后可以被测试和验证的方法。XP使用两种测试:功能测试和单元测试。功能测试由客户指定,由开发人员及用户测试;而单元测试由开发人员编写和测试。在XP中,功能测试是自动执行的,并且在理想情况下,每天都执行。功能测试被认为是系统规格说明的一部分。在编码前后都要进行单元测试,以验证每一个模块都符合设计规格说明。第8章将详细讨论这两种测试。
重构:随着系统的构建,很可能需求将发生变化。因为XP方法的一个主要特征是只针对当前的需求进行设计,所以,经常出现这样的情况:新的需求迫使开发人员重新考虑他们现有的设计。重构(refactoring)是指重新审视需求和设计,重新明确地描述它们以符合新的现有的需要。有时,重构是指重组(restructure)设计和代码,而不扰乱系统的外部行为。重构是以一系列小的步骤完成的,辅之以单元测试和对编程,用简单性指导工作。我们将在第5章讨论重构的难点。
对编程:如第1章指出的,将软件工程视作艺术和将软件工程视作科学这两种观点之间存在着紧张关系。对编程试图强调软件开发的艺术性这一方面,承认学徒-师父这样的隐喻,对于教会软件开发初学者如何逐步具有熟练开发人员的能力是很有用的。使用一个键盘,两个结成对的程序员,根据需求规格说明和设计开发系统,由一个人负责完成代码。但是,配对是灵活的:一个开发人员在一天中可能与多个伙伴配对。传统的开发方法是个人单独工作,直到他们的代码经过单元测试。第7章会将对编程与传统方法进行比较。
集体所有权:在XP中,随着系统的开发,任何开发人员都能够对系统的任何部分进行改变。在第11章,我们将讨论管理变化过程中的难点,包括当两个人试图同时改变同一个模块的时候引入的错误。
持续集成:快速交付功能意味着可以按日为客户提供可运行的版本,有时甚至可以按小时提供。重点是多个小的增量或改进,而不是从一个修正到下一个修正这样的巨大跳跃。
可以忍受的步伐:疲劳可能产生错误。因此,XP的支持者提出每星期工作40个小时的目标。逼迫程序员投入很长的时间来满足最后期限,就表明最后期限不合理,或者是缺乏满足最后期限的资源。
在现场的客户:理想情况下,客户应该在现场与开发人员一起工作以确定需求,并提供如何对它们进行测试的反馈。
代码标准:很多观察者认为XP和其他敏捷方法提供了不受约束的环境,在其中可以做任何事情。但是实际上,XP倡导清晰的代码标准定义,以利于团队改变和理解他人的工作。这些标准支持其他的实践,例如测试和重构。其结果应该是代码整体看起来就像是由一个人编写的,并且其方法和表述一致。
极限编程和敏捷方法是比较新的方法(补充材料2-2)。其有效性的证据很少,但却呈增长趋势。在后面的章节讨论其相关活动的时候,我们将再次讨论很多敏捷方法和概念,以及它们的实证性评估。
本章出现的过程模型仅仅是实际使用或讨论的模型中的一小部分。其他过程模型可以根据用户、客户和开发人员的需要进行定义和剪裁。正如在补充材料2-3中指出的那样,实际上,我们应该用一组过程模型描述软件开发过程,而不是集中于单个模型或视图。
补充材料2-2 什么时候极限编程显得过于极端?
就像大多数软件开发方法一样,敏捷方法也招致了一些批评。例如,Stephens和Rosenberg指出,很多极限编程的实践是相互依赖的,如果其中一个被修改,其他的都会受到影响(Stephens and Rosenberg 2003)。要了解其中的原因,我们假定一些人对于对编程是不满意的。那么,就可能需要更多的协调和文档来解决当人们各行其是时失去的共识。类似地,许多开发人员喜欢在编程之前进行设计。Scrum通过建立每月冲刺来处理这种喜好。Elssamadissy和Schalliol指出,在极限编程中,需求被表示为一系列必须能通过软件审查的测试用例(Elssamadissy and Schalliol 2002)。这种方法可能促使客户代表关注测试用例而不是需求。因为测试用例是需求的详细表述,并且可能是面向解决方案的,所以,将重点放在测试用例上可能会将客户代表的注意力从项目的目标转移开,并且可能导致这样一种情形:系统通过了所有测试,但是却不是客户认为他们应该得到的系统。正像我们将在第5章中看到的,重构可能是敏捷方法的要害,很难做到重做一个系统而不降低体系结构的质量。
补充材料2-3 过程模型的集合
我们在补充材料2-1中看到,开发过程是一个问题求解的活动,但是流行的过程模型很少会包含问题求解。Curtis、Krasner和Iscoe对17个大型项目进行了现场研究,以确定过程模型中应获取哪些问题求解的因素,以帮助我们理解软件开发(Curtis, Krasner and Iscoe 1988)。尤其是,他们考虑了影响项目结果的行为因素和组织因素。他们的研究结果提出了一个关于软件开发层次的行为模型,其中包含5个关键视角:业务环境、公司、项目、开发团队和个人。个人视图提供关于认知和动机的信息,项目和开发团队的视图告诉我们团体动态的相关情况。公司和业务环境提供了可能影响生产率和质量的组织行为的信息。这个模型并不是要替换传统的过程模型,它与传统模型是正交的关系,提供的信息是行为如何影响创建和生产活动,它是对传统模型的补充。
随着开发人员和客户对问题了解的加深,他们把彼此的领域知识、技术和业务结合起来,以得到一个合适的解决方案。通过把开发看作是一组相互协作的过程,我们可以看到学习、技术交流、客户交互和需求协商的效果。不过,当前描述一系列开发任务的模型“对下述问题的分析是没有帮助的:项目成员必须了解多少新信息,如何协商那些有分歧的需求,设计团队如何解决体系结构的冲突以及类似因素对项目内在的不确定性和风险有何影响”(Curtis, Krasner and Iscoe 1988)。然而,当我们引入认知的、社会的、组织的和过程的相关模型时,我们就开始了解瓶颈和低效率的原因。正是这样的认识使得管理人员能够理解和控制开发过程。而通过总体考虑跨越各个模型层的行为,可以了解每个模型对另一个模型因素的效果所产生的影响。
不论使用哪一种过程模型,许多活动都是所有模型所共有的。在后面章节中对软件工程进行探讨的时候,我们将研究每一个开发活动,了解它包含的内容,并找出什么样的工具和技术能够使我们的工作更加有效、生产率更高。
本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。