系统开发基础知识
软件开发方法
软件开发生命周期
传统的软件生命期(software life cycle)是指软件产品从形成概念(构思)开始,经过定义、开发、使用和维护,直到最后被废弃(不能再使用)为止的全过程。按照传统的软件生命周期方法学,可以把软件生命期划分为软件定义、软件开发、软件运行与维护三个阶段。
软件定义时期
软件定义包括可行性研究和详细需求分析过程,任务是确定软件开发工程必须完成的总目标。具体可分成问题定义、可行性研究、需求分析等。
(1)问题定义。问题定义是人们常说的软件的目标系统是“什么”,系统的定位以及范围等。也就是要按照软件系统工程需求来确定问题空间的性质(说明是一种什么性质的系统)。
(2)可行性研究。软件系统的可行性研究包括技术可行性、经济可行性、操作可行性和社会可行性等,确定问题是否有解,解决办法是否可行。
(3)需求分析。需求分析的任务是确定软件系统的功能需求、性能需求和运行环境的约束,写出软件需求规格说明书、软件系统测试大纲、用户手册概要。功能需求是软件必须完成的功能;性能需求是软件的安全性、可靠性、可维护性、结果的精度、容错性(出错处理)、响应速度和适应性等;运行环境是软件必须满足运行环境的要求,包括硬件和软件平台。
需求分析是重要的,然而又是困难的。作为开发者,要充分理解用户的需求,并以书面形式写出规格说明书,这是以后软件设计和验收的依据;困难的地方是,由于软件系统的复杂性,作为用户也许很难一次性说清楚系统应该做什么。因此,需求分析也就十分艰巨,它要完成大量的工作。
需求分析过程应该由系统分析员、软件开发人员与用户共同完成,反复讨论和协商,并且逐步细化、一致化、完全化等,直至建立一个完整的分析模型。需求分析工作完成后要提交软件需求规格说明(Software Requirements Specification, SRS)。内容可以有系统(或子系统)名称、功能描述、接口、基本数据结构、性能、设计需求、开发标准、验收原则等。
软件开发时期
软件开发时期就是软件的设计与实现,可分成概要(总体)设计、详细设计、编码、测试等。
概要设计是在软件需求规格说明的基础上,建立系统的总体结构(含子系统的划分)和模块间的关系,定义功能模块及各功能模块之间的关系。
详细设计对概要设计产生的功能模块逐步细化,把模块内部细节转化为可编程的程序过程性描述。详细设计包括算法与数据结构、数据分布、数据组织、模块间接口信息和用户界面等的设计,并写出详细设计报告。
编码又称编程,编码的任务是把详细设计转化为能在计算机上运行的程序。测试可分成单元测试、集成测试、确认测试和系统测试等。通常把编码和测试称为系统的实现。
软件运行和维护
软件运行就是把软件产品移交给用户使用。软件投入运行后的主要任务是使软件持久满足用户的要求。
软件维护是对软件产品进行修改或对软件需求变化做出响应的过程,也就是尽可能地延长软件的寿命。
当软件已没有维护的价值时,宣告退役,软件生命随之宣告结束。
软件开发模型
软件生存周期模型又称软件开发模型(software develop model)或软件过程模型(software process model),它是从某一个特定角度提出的软件过程的简化描述。模型的主要特点是简单化。软件过程模型是软件开发实际过程的抽象与概括,它应该包括构成软件过程的各种活动,也就是对软件开发过程各阶段之间关系的一个描述和表示。
$\color{green}{\text{软件过程模型的基本概念}}$ :软件过程是制作软件产品的一组活动以及结果,这些活动主要由软件人员来完成,软件活动主要如下一些。
(1) $\color{green}{\text{软件描述}}$ 。必须定义软件功能以及使用的限制。
(2) $\color{green}{\text{软件开发}}$ 。也就是软件的设计和实现,软件工程人员制作出能满足描述的软件。
(3) $\color{green}{\text{软件有效性验证}}$ 。软件必须经过严格的验证,以保证能够满足客户的需求。
(4) $\color{green}{\text{软件进化}}$ 。软件随着客户需求的变化不断改进。
软件过程模型是软件工程的重要内容,它为软件工程管理提供里程碑和进度表,为软件开发过程提供原则和方法。软件过程有各种各样的模型,如瀑布模型、演化模型、原型模型、螺旋模型、喷泉模型和基于可重用构件的模型等。软件开发模型至今仍在不断发展和改进,以下介绍主要的几种。
$\color{green}{\text{瀑布模型}}$
瀑布模型(waterfall model)可以说是最早使用的软件生存周期模型之一。由于这个模型描述了软件生命的一些基本过程活动,所以它称为软件生命周期模型。这些活动从一个阶段到另一个阶段逐次下降,它的工作流程形式上又很像瀑布,因此人们更常把它称为瀑布模型,该模型如图4-1所示。
图4-1 瀑布模型
瀑布模型的特点是因果关系紧密相连,前一个阶段工作的结果是后一个阶段工作的输入。或者说,每一个阶段都是建筑在前一个阶段正确结果之上,前一个阶段的错漏会隐蔽地带到后一个阶段。这种错误有时甚至可能是灾难性的。因此每一个阶段工作完成后,都要进行审查和确认,这是非常重要的。历史上,瀑布模型起到了重要作用,它的出现有利于人员的组织管理,有利于软件开发方法和工具的研究。
瀑布模型的主要缺如下。
(1)软件需求分析的准确性很难确定,甚至是不可能和不现实的。因为用户不理解计算机,无法回答目标系统是“什么”的情况,对系统将来的改变部分难以确定,往往用“我不能准确地告诉你”回答开发人员。
(2)用户和软件项目负责人要相当长的时间才能得到初始版本,这时如果改变需求,将会带来巨大的损失(例如人力、财力、时间等)。该模型的应用有一定的局限性。
$\color{green}{\text{原型模型}}$
原型模型(prototype model)又称快速原型。由于瀑布型的缺点,人们借鉴建筑师、工程师建造原型的经验,提出了原型模型。该模型如图4-2所示。原型模型主要有以下两个阶段:
(1)原型开发阶段。软件开发人员根据用户提出的软件系统的定义,快速地开发一个原型。该原型应该包含目标系统的关键问题和反映目标系统的大致面貌,展示目标系统的全部或部分功能、性能等。
开发原型可以考虑以下三种途径:
● 利用模拟软件系统的人机界面和人机交互方式。
● 真正开发一个原型。
● 找来一个或几个正在运行的类似软件进行比较。
图4-2 原型模型
(2)目标软件开发阶段。在征求用户对原型的意见后对原型进行修改完善,确认软件系统的需求并达到一致的理解,进一步开发实际系统。但是在实际工作中,由于各种原因,大多数原型都废弃不用,仅仅把建立原型的过程当作帮助定义软件需要的一种手段。原型模型的使用应该注意:
● 用户对系统模糊不清,无法准确回答目标系统的需求。
● 要有一定的开发环境和工具支持。
● 经过对原型的若干次修改,应收敛到目标范围内,否则可能会失败。
● 对大型软件来说,原型可能非常复杂而难以快速形成,如果没有现成的,就不应考虑用原型法。
$\color{green}{\text{螺旋模型}}$
螺旋模型(Spiral Model)是在快速原型的基础上扩展而成。也有人把螺旋模型归到快速原型,实际上,它是生命周期模型与原型模型的一个结合,如图4-3所示。这种模型把整个软件开发流程分成多个阶段,每一个阶段都由4部分组成,它们是:
(1)目标设定。为该项目进行需求分析,定义和确定这一个阶段的专门目标,指定对过程和产品的约束,并且制定详细的管理计划。
(2)风险分析。对可选方案进行风险识别和详细分析,制定解决办法,采取有效的措施避免这些风险。
(3)开发和有效性验证。风险评估后,可以为系统选择开发模型,并且进行原型开发,即开发软件产品。
(4)评审。对项目进行评审,以确定是否需要进入螺旋线的下一次回路,如果决定继续,就要制定下一阶段计划。
螺旋模型的软件开发过程实际是上述4个部分的迭代过程,每迭代一次,螺旋线就增加一周,软件系统就生成一个新版本,这个新版本实际上是对目标系统的一个逼近(更接近一步)。经过若干次的迭代后,系统应该尽快地收敛到用户允许或可以接受的目标范围内,否则也有可能中途夭折。
图4-3 螺旋模型
该模型支持大型软件开发,适用于面向规格说明、面向过程和面向对象的软件开发方法,也适用于几种开发方法的组合。
基于可重用构件的模型
事实上,在许多软件项目中都存在一些重用软件。当软件人员意识到某一个项目中的设计或者代码在另一个项目中重复出现时,重用就自然地发生了。构件也正是基于这一思想而产生的。构件的重用提高了软件的可靠性和易维护性,程序在进行修改时产生较少的副作用。近几年来,出现了以组件为基础的软件工程方法,基于构件组装的软件过程模型也随之产生,并且逐渐地被广泛使用。该模型如图4-4所示。
图4-4 基于可重用构件的模型
人们可以把软件工程项目所创建的构件不断地积累和存储在一个构件库中,在一个系统开发过程中,一旦标识出候选构件,则可以在构件库中检索该构件,确认这些构件是否存在,如果构件已存在,就可以从构件库中取出重用。如果一个候选构件在构件库中并不存在,那么,就要进行新构件的开发。新构件开发成功后,一方面用它来构造目标系统,另一方面可以把它存入构件库中。软件目标系统是基于可重用构件的一种集成,这将大大地提高软件的可靠性和生产率。
显然,一个系统将依赖构件的健壮性。但毫无疑问,构件组装模型使软件可以重用,而重用给软件工程师提供大量的好处。构件组装模型具有极其广阔的实用性和深远的意义。
基于面向对象的模型
面向对象技术自从问世后,很快被人们所接受,并得到广泛的应用。面向对象技术确实有很多的优点,其中构件重用是非常重要的技术之一。对象技术强调了类的创建与封装,一旦一个类创建与封装成功,就可以在不同的应用系统中被重用。
对象技术为基于构件的软件过程模型提供了更强的技术框架。基于面向对象的模型,是综合了面向对象和原型方法及重用技术的一种模型。该模型如图4-5所示。
该模型描述了软件从需求开始,通过检索重用构件库,一方面进行构件开发,另一方面进行需求开发,需求开发完成后,在进行面向对象分析过程中,它可以在重用构件库中读取构件,并快速建立OOA(Object-Oriented Analysis)原型。同理,在进行面向对象设计时,它可以在重用构件库中读取构件,并快速建立OOD(Object-Oriented Design)原型。最后利用生成技术,建造一个目标系统。在这个模型中,一个系统可以由重用构件组装而成,甚至通过组装可重用的子系统而创建更大的系统。
图4-5 基于面向对象的模型
基于四代技术的模型
四代语言(4th Generation Language, 4GL)是在大型数据库管理系统的基础上发展起来的程序设计语言。程序设计语言可分成机器语言、汇编语言、高级语言和第四代语言,以及为人工智能领域应用而设计的语言——第五代语言。
4GL目前还没有统一的定义,它的描述定义如下。
(1)用于快速开发应用软件的高产工具(重点强调了提高软件开发的生产率)。
(2)用于快速事务处理系统的高产工具(突出了主要应用领域)。
其主要特征描述如下。
(1)它是非过程化的语言,目的在于高效、直接地实现各种应用系统。它完全不用编程的方式来构造应用系统。程序员可以不再使用通常编程的方法、算法等来完成某一个功能,而是利用一些生成器,例如,菜单生成器、报表生成器、屏幕生成器、图形软件包等。在屏幕上以对话的交互方式,通过填表或操作屏幕上的窗口和按钮图标,或者在某一个按钮定义时加上适当的一段程序……从而构造用户需要的应用系统生成器自动生成源程序。
(2)它与数据库的关系密切,能够对大型数据库进行高效处理。它被广泛地应用于数据库管理系统中。
注意:第四代语言与通常的软件工程环境或计算机辅助软件工程(Computer-Aided Software Engineering, CASE)不同,CASE支持软件开发的全过程,4GL不支持应用软件开发的全过程,只侧重于支持应用软件开发过程中的设计阶段和实现阶段,特别是支持界面以及与界面有关的处理过程。
以4GL为核心的软件开发技术称为四代技术。使用四代技术可以给我们带来许多方便,在软件开发的时间、成本和质量等方面都会取得较好的效果,但它毕竟在系统开发全过程中应用有限。
敏捷方法
敏捷方法的特点
敏捷型方法主要有两个特点,这也是其区别于其他方法,尤其是重型方法的最主要的特征。
● 敏捷型方法是“适应性”(adaptive)而非“预设性”(predictive)的。重型方法试图对一个软件开发项目在很长的时间跨度内做出详细的计划,然后依计划进行开发。这类方法在计划制定完成后拒绝变化。而敏捷型方法则欢迎变化。其实,它的目的就是成为适应变化的过程,甚至能允许改变自身来适应变化。
● 敏捷型方法是,“面向人的”(people-oriented)而非“面向过程的”(process-oriented)。它们试图使软件开发工作能够利用人的特点,充分发挥人的创造能力。它们强调软件开发应当是一项愉快的活动。
下面是对上面两点的详细解释:
适应性和预设性
传统的软件开发方法的基本思路一般是从其他工程领域借鉴而来的,比如土木工程等。在这类工程实践中,通常非常强调施工前的设计规划。只要图纸设计得合理并考虑充分,施工队伍可以完全遵照图纸顺利建造,并且可以很方便地把图纸划分为许多更小的部分交给不同的施工人员分别完成。
但是,软件开发与上面的土木工程有着显著的不同。软件的设计是难以实现的,并且需要昂贵的有创造性的人员。土木工程师在设计时所使用的模型是基于多年的工程实践的,而且一些设计上的关键部分都是建立于坚实的数学分析之上。而在软件设计中,完全没有类似的基础。我们对开发计划所能做的只是请专家审阅。这就使得我们无法将设计和实施分离开来,一些设计错误只能在编码和测试时才能发现。根本无法做出一个交给程序员就能直接编码的软件设计。
所以,软件过程不可能照搬其他工程领域原有的方法,需要有适应其特点的新的开发方法。
软件的设计之所以难以实现,问题在于软件需求的不稳定,从而导致软件过程的不可预测。但是传统的控制项目的模式都是针对可预测的环境的,在不可预测的环境下,就无法使用这些方法。
但是我们必须对这样的过程进行监控,以使得整个过程能向我们期望的目标前进。于是Agile方法引入“适应性”方法,该方法使用反馈机制对不可预测过程进行控制。
面向人而非面向过程
传统正规方法的目标之一是发展出这样一种过程,使得一个项目的参与人员成为可替代的部件。这样的一种过程将人看成是一种资源,他们具有不同的角色,如分析员、程序员、测试员及管理人员。个体是不重要的,只有角色才是重要的。这样考虑的一个重要的出发点就是:尽量减少人的因素对开发过程的影响。但是敏捷型方法则正好相反。
传统方法是让开发人员“服从”一个过程而非“接受”一个过程。但是一个常见的情况是:软件的开发过程是由管理人员决定的,而管理人员已经脱离实际开发活动相当长的时间了,如此设计出来的开发过程是难以为开发人员所接受的。
敏捷型过程还要求开发人员必须有权作技术方面的所有决定。IT行业和其他行业不同,其技术变化速度非常之快。今天的新技术可能几年后就过时了。只有在第一线的开发人员才能真正掌握和理解开发过程中的技术细节。所以技术方面的决定必须由他们来做出。这样一来,就使得开发人员和管理人员在一个软件项目的领导方面有同等的地位,他们共同对整个开发过程负责。
敏捷方法特别强调开发中相关人员之间的信息交流。Alistair Cockburn在对数十个项目的案例调查分析后得出一个结论,“项目失败的原因最终都可以追溯到信息没有及时准确地传递到应该接受它的人”。在开发过程中,项目的需求是在不断变化的,管理人员之间、开发人员之间以及管理人员和开发人员之间,都必须不断地了解这些变化,对这些变化做出反应,并实施在随后的开发过程中。敏捷方法还特别提倡直接的面对面交流。Alistair Cockburn认为面对面交流的成本要远远低于文档交流的成本,因此,敏捷方法一般都按照高内聚、松耦合的原则将项目划分为若干小组,以增加沟通,提高敏捷性及应变能力。
敏捷方法的核心思想
(1)敏捷方法是适应型,而非可预测型。与传统方法不同,敏捷方法拥抱变化,也可以说它的初衷就是适应变化的需求,利用变化来发展,甚至改变自己,最后完善自己。
(2)敏捷方法是以人为本,而非以过程为本。传统方法以过程为本,强调充分发挥人的特性,不去限制它。并且软件开发在无过程控制和过于严格繁琐的过程控制中取得一种平衡,以保证软件的质量。
(3)迭代增量式的开发过程。敏捷方法以原型开发思想为基础,采用迭代增量式开发,发行版本小型化。它根据客户需求的优先级和开发风险,制定版本发行计划,每一发行版都是在前一成功发行版的基础上进行功能需求扩充,最后满足客户的所有功能需求。
敏捷型方法的含义及其特征
我们把软件开发过程中拥有大量中间产品(如需求规约、设计模型等)和复杂控制的软件开发方法称为重型方法;由此,我们称中间产品较少的方法为轻型方法。从表象来看,重型方法注重开发文档的完备性和充分性;而敏捷型方法认为最根本的文档应该是源码,而不是繁琐的文档。从实质上说,有如下两方面更深层次的区别:
(1)敏捷型方法的思想是“自适应”的,而非如“预设”的重型方法试图预先固定需求并拟定详细开发计划;敏捷型方法适应需求的变化,甚至可以说其初衷就是针对变化的需求的。
(2) $\color{green}{\text{敏捷型方法的思考角度}}$ 是“ $\color{green}{\text{面向人}}$ ”的,而非“ $\color{green}{\text{面向开发过程}}$ ”的。重型方法在实践原则中总是把开发者看作是一个泛化的生产要素,而忽视了作为决定性因素的人的特殊性;而敏捷型方法则强调以人为本,并贯穿实践始终。由上可知敏捷型方法其实是软件开发方法论从无到重型再进一步发展的成果。
敏捷方法的适用范围
实际上,满足工程设计标准的唯一文档是源代码清单。“软件项目的设计是一个抽象的概念。它涉及了程序的概括形状(shape)、结构以及每一模块、类和方法的详细形状。”系统设计得到了有关系统的一个清晰的“图像”,这一图像可以保持到首次发布。但随着项目的开发,程序“片段”就可能像不断腐化的“面包碎片”,发出“臭味”,并不断蔓延和积累,使得系统越来越难以维护,以至于不得不要求重新设计。但这样的重新设计是很难成功的。
因此,与这种传统的方法相比,敏捷方法比较适合需求变化比较大或者开发前期对需求不是很清晰的项目,以它的灵活性来适应需求的变化,有效地控制项目进度和成本。另外,敏捷方法对设计者、开发者和客户之间的有效沟通和及时反馈要求比较高,所以不易在开发团队比较庞大的项目中实施,当然这也不是绝对的。
敏捷方法的主要内容
敏捷方法的主要内容包括4个核心价值观和12条过程实践规则。4个核心价值观分别为沟通、简单、反馈和勇气。沟通,它强调设计者、开发者和客户三者之间的有效交流是开发成功的关键;简单是设计和编码的指导原则,它强调只满足当前功能需求,不做假想设计,尽量使代码简单化;反馈,强调设计者、开发者和客户之间及时和详尽的意见反馈是开发成功的保证;勇气,是开发适应变化的前提,要求设计者和开发者在必需做出取舍或重构时,勇于抉择,勇于实践。
依据敏捷方法的4个核心价值观,提出12条过程实践规则,分别为简单设计、测试驱动、代码重构、结对编程、持续集成、现场客户、发行版本小型化、系统隐喻、代码集体所有制、规划策略、规范代码、40小时工作机制。
主要敏捷方法简介
手工作坊式的软件生产方式已经被无数次的项目失败证明为低效和应被舍弃的:传统软件开发方法(如ISO9000和CMM)在规范和保证开发进程的同时,由于其繁琐的过程控制和严格的文档要求招致了开发者潜在的抵触;此外,开发人员流动性大于软件的可持续开发之间的矛盾日渐显露,如何保证软件的高可传承性以及尽可能地延长软件生命周期成了摆在开发者和管理者面前的难题。为了应对这种局面,近年来,已经出现很多敏捷型方法,它们有许多的共同特征,但也有一些重要的不同之处。这里就其中影响比较大的几种敏捷方法作一些简单的介绍。
(1)XP(Extreme Programming, $\color{green}{\text{极限编程}}$ )在所有的敏捷型方法中,XP是最引人瞩目的。它源于Smalltalk圈子,特别是Kent Beck和Ward Cunningham在20世纪80年代末的密切合作。XP在一些对费用 $\color{green}{\text{控制严格}}$ 的公司中的使用,已经被证明是非常有效的。
(2)Cockburn的 $\color{red}{\text{水晶系列方法}}$ 。水晶系列方法是由Alistair Cockburn提出的。它与XP方法一样,都有以人为中心的理念,但在实践上有所不同。Alistair考虑到人们一般很难严格遵循一个纪律约束很强的过程,因此,与XP的高度纪律性不同,Alistair探索了用 $\color{green}{\text{最少纪律约束而仍能成功的方法}}$ ,从而在产出效率与易于运作上达到一种平衡。也就是说,虽然水晶系列不如XP那样的产出效率,但会有更多的人能够接受并遵循它。
(3) $\color{red}{\text{开放式源码}}$ 。这里提到的开放式源码指的是开放源码界所用的一种运作方式。开放式源码项目有一个特别之处,就是程序开发人员在 $\color{green}{\text{地域上分布很广}}$ ,这使得它和其他敏捷方法不同,因为一般的敏捷方法都强调项目组成员在同一地点工作。开放源码的一个突出特点就是查错排障(debug)的高度并行性,任何人发现了错误都可将改正源码的“补丁”文件发给维护者。然后由维护者将这些“补丁”或是新增的代码并入源码库。
(4) $\color{red}{\text{SCRUM}}$ 。SCRUM已经出现很久了,像前面所论及的方法一样,该方法强调这样一个事实,即明确定义了的可重复的方法过程只限于在明确定义了的可重复的环境中, $\color{green}{\text{为明确定义了的可重复的人员所用,去解决明确定义了的可重复的问题}}$ 。
(5)Coad的 $\color{red}{\text{功用驱动开发方法}}$ (Feature Driven Development, $\color{red}{\text{FDD}}$ )。FDD是由Jeff De Luca和大师Peter Coad提出来的。像其他方法一样,它致力于短时的迭代阶段和可见可用的功能。在FDD中,一个迭代周期一般是两周。
在FDD中, $\color{green}{\text{编程开发人员分成两类:首席程序员和“类”程序员}}$ (class owner)。首席程序员是最富有经验的开发人员,他们是项目的协调者、设计者和指导者,而“类”程序员则主要做源码编写。
(6)ASD方法。 $\color{red}{\text{ASD}}$ (Adaptive Software Development)方法由Jim Highsmith提出,其核心是三个非线性的、重叠的开发阶段: $\color{green}{\text{猜测}}$ 、 $\color{green}{\text{合作}}$ 与 $\color{green}{\text{学习}}$ 。
RUP
RUP概述
RUP(Rational Unified Process)根据字面理解,可以知道RUP包括三方面的意思,即Rational、Unified和Process。Rational表示RUP是由Rational公司提出的,Unified表示RUP是最佳开发经验总结,而Process表示RUP是一个软件开发过程。
RUP的生命周期
RUP软件开发生命周期是一个二维的软件开发模型,RUP中有9个核心工作流,这9个核心工作流如下。
● 业务建模(business modeling):理解待开发系统所在的机构及其商业运作,确保所有参与人员对待开发系统所在的机构有共同的认识,评估待开发系统对所在机构的影响。
● 需求(requirements):定义系统功能及用户界面,使客户知道系统的功能,使开发人员理解系统的需求,为项目预算及计划提供基础。
● 分析与设计(analysis & design):把需求分析的结果转化为分析与设计模型。
● 实现(implementation):把设计模型转换为实现结果,对开发的代码做单元测试,将不同实现人员开发的模块集成为可执行系统。
● 测试(test):检查各子系统的交互与集成,验证所有需求是否均被正确实现,对发现的软件质量上的缺陷进行归档,对软件质量提出改进建议。
● 部署(deployment):打包、分发、安装软件,升级旧系统;培训用户及销售人员,并提供技术支持。
● 配置与变更管理(configuration & change Management):跟踪并维护系统开发过程中产生的所有制品的完整性和一致性。
● 项目管理(project management):为软件开发项目提供计划、人员分配、执行、监控等方面的指导,为风险管理提供框架。
● 环境(environment):为软件开发机构提供软件开发环境,即提供过程管理和工具的支持。
需要说明的是表示核心工作流的术语discipline,在RUP 2000以前用的是core workflow这个术语,但在最新的版本中已改为用discipline。discipline的中文意义较多,根据RUP的定义,discipline是相关活动的集合,这些活动都和项目的某一个方面有关,如这些活动都是和业务建模相关的,或者都是和需求相关的,或者都是和分析设计相关的等等。
RUP把软件开发生命周期划分为多个循环(cycle),每个cycle生成产品的一个新的版本,每个cycle依次由4个连续的阶段(phase)组成,每个阶段完成确定的任务。这4个阶段如下。
● $\color{green}{\text{初始}}$ (inception)阶段:定义最终产品视图和业务模型,并确定系统范围。
● $\color{green}{\text{细化}}$ (elaboration)阶段:设计及确定系统的体系结构,制定工作计划及资源要求。
● $\color{green}{\text{构造}}$ (construction)阶段:构造产品并继续演进需求、体系结构、计划直至产品提交。
● $\color{green}{\text{移交}}$ (transition)阶段:把产品提交给用户使用。
每一个阶段都由一个或多个连续的迭代(iteration)组成。迭代并不是重复地做相同的事,而是针对不同用例的细化和实现。每一个迭代都是一个完整的开发过程,它需要项目经理根据当前迭代所处的阶段以及上次迭代的结果,适当地对核心工作流中的行为进行裁剪。
在每个阶段结束前有一个里程碑(milestone)评估该阶段的工作。如果未能通过该里程碑的评估,则决策者应该做出决定,是取消该项目还是继续做该阶段的工作。
RUP中的核心概念
RUP中定义了如下一些核心概念,理解这些概念对于理解RUP很有帮助。
● 角色(Role)——who的问题:角色描述某个人或一个小组的行为与职责。RUP预先定义了很多角色,例如体系结构师(architect)、设计人员(designer)、实现人员(implementer)、测试员(tester)和配置管理人员(configuration manager)等,并对每一个角色的工作和职责都做了详尽的说明。
● 活动(activity)——how的问题:活动是一个有明确目的的独立工作单元。
● 制品(artifact)——what的问题:制品是活动生成、创建或修改的一段信息。也有些书把artifact翻译为产品、工件等,和制品的意思差不多。
● 工作流(workflow)——when的问题:工作流描述了一个有意义的连续的活动序列,每个工作流产生一些有价值的产品,并显示了角色之间的关系。
RUP 2003对这些概念有比较详细的解释,并用类图描述了这些概念之间的关系,除了role、activity、artifact和workflow这4个核心概念外,还有其他一些基本概念,如工具教程(tool mentor)、检查点(checkpoints)、模板(template)和报告(report)等。
$\color{red}{\text{RUP的特点}}$
与别的软件开发过程相比,RUP具有自己的特点,即RUP是用例驱动的、以体系结构为中心的、迭代和增量的软件开发过程。下面对这些特点做进一步的分析。
$\color{green}{\text{用例驱动}}$
RUP中的开发活动是用例驱动的,即需求分析、设计、实现和测试等活动都是用例驱动的。
$\color{green}{\text{以体系结构为中心}}$
RUP中的开发活动是围绕体系结构展开的。对于软件体系结构,目前还没有一个统一的精确的定义,不同的人对软件体系结构有不同的认识。Mary Shaw和David Garlan对软件体系结构的定义是:软件体系结构是关于构成系统的元素、这些元素之间的交互、元素和元素之间的组成模式以及作用在这些组成模式上的约束等方面的描述。具体来说,软件体系结构刻画了系统的整体设计,它去掉了细节部分,突出了系统的重要特征。
软件体系结构的设计和代码设计无关,也不依赖于具体的程序设计语言。软件体系结构是软件设计过程中的一个层次,这一层次超越计算过程中的算法设计和数据结构设计。体系结构层次的设计问题包括系统的总体组织和全局控制、通讯协议、同步、数据存取、给设计元素分配特定功能、设计元素的组织、物理分布、系统的伸缩性和性能等。
体系结构的设计需要考虑多方面的问题:在功能性特征方面要考虑系统的功能;在非功能性特征方面要考虑系统的性能、安全性和可用性等;与软件开发有关的特征要考虑可修改性、可移植性、可重用性、可集成性和可测试性等;与开发经济学有关的特征要考虑开发时间、费用、系统的生命期等。当然,这些特征之间有些是相互冲突的,一个系统不可能在所有的特征上都达到最优,这时就需要系统体系结构设计师在各种可能的选择之间进行权衡。
对于一个软件系统,不同人员所关心的内容是不一样的,因此软件的体系结构是一个多维的结构,也就是说,会采用多个视图(view)来描述软件体系结构。打个比喻,对于一座大厦,会有大厦的电线布线结构、电梯布局结构、水管布局结构等,对于大厦的建设和维护人员来说,有些人关心大厦的电线布局,有些人关心大厦的电梯布局,还有些人关心水管布局,对于不同类型的人员,只需要提供这类人员关心的视图即可(一个视图可以用一个或多个图来描述),所有这些视图组成了大厦的体系结构。至于采用多少个视图,采用什么视图较好,不同的人就有不同的观点了。
在RUP中,是采用如图4-6所示的“4+1”视图模型来描述软件系统的体系结构。
在“4+1”视图模型中,分析人员和测试人员关心的是系统的行为,因此会侧重于用例视图;最终用户关心的是系统的功能,因此会侧重于逻辑视图;程序员关心的是系统的配置、装配等问题,因此会侧重于实现视图;系统集成人员关心的是系统的性能、可伸缩性、吞吐率等问题,因此会侧重于进程视图;系统工程师关心的是系统的发布、安装、拓扑结构等问题,因此会侧重于部署视图。
- $\blacktriangleright$(这里是不是说反了,用户应该会侧重于用例视图,分析人员和测试人员侧重于逻辑视图)
- $\blacktriangleright$(系统的功能不是用例视图体现的嘛)
图4-6 “4+1”视图模型
$\color{green}{\text{迭代与增量}}$
RUP强调要采用迭代和增量的方式来开发软件,把整个项目开发分为多个迭代过程。在每次迭代中,只考虑系统的一部分需求,进行分析、设计、实现、测试和部署等过程,每次迭代是在已完成部分的基础上进行的,每次增加一些新的功能实现,以此进行下去,直至最后项目的完成。软件开发采用迭代和增量的方式有以下好处:
(1)在软件开发的早期就可以对关键的、影响大的风险进行处理。
(2)可以提出一个软件体系结构来指导开发。
(3)可以更好地处理不可避免的需求变更。
(4)可以较早地得到一个可运行的系统,鼓舞开发团队的士气,增强项目成功的信心。
(5)为开发人员提供一个能更有效工作的开发过程。
RUP裁剪
RUP是一个通用的过程模板,包含了很多关于开发指南、开发过程中产生的制品、开发过程中所涉及的各种角色的说明。RUP可用于各种不同类型的软件系统、不同的应用领域、不同类型的开发机构、不同功能级别、不同规模的项目中。RUP非常庞大,没有一个项目会使用RUP中的所有东西,针对具体的开发机构和项目,应用RUP时还要做裁剪,也就是要对RUP进行配置。RUP就像是一个元过程(meta-process),通过对RUP进行裁剪可以得到很多不同的软件开发过程,这些软件开发过程可以看作RUP的具体实例,这些具体的开发过程实例适合于不同的开发机构和项目的需要。
针对一个软件项目,RUP裁剪可分为以下几步:
(1)确定本项目的软件开发过程需要哪些工作流。RUP的9个核心工作流并不总是需要的,可以根据项目的规模、类型等对核心工作流做一些取舍。如嵌入式软件系统项目一般就不需要业务建模这个工作流。
(2)确定每个工作流要产出哪些制品。如规定某个工作流应产出哪些类型的文档。
(3)确定4个阶段之间(初始阶段、细化阶段、构造阶段和移交阶段)如何演进。确定阶段间演进要以风险控制为原则,决定每个阶段要执行哪些工作流,每个工作流执行到什么程度,产出的制品有哪些,每个制品完成到什么程度等。
(4)确定每个阶段内的迭代计划。规划RUP的4个阶段中每次迭代开发的内容有哪些。迭代是RUP非常强调的一个概念,可以进一步降低开发风险。
(5)规划工作流内部结构。工作流不是活动的简单堆积,工作流涉及角色、活动和制品,工作流的复杂程度与项目规模及角色多少等有很大关系,这一步决定裁剪后的RUP要设立哪些角色。最后,规划工作流的内部结构,通常用活动图的形式给出。
在上面的5个步骤中,第(5)步是对RUP进行裁剪的难点。如果从“软件开发过程也是软件”的角度来看,对RUP进行裁剪可以看作是软件过程开发的再工程。
$\color{green}{\text{软件系统工具}}$
软件系统工具的种类繁多,很难有统一的分类方法。通常可以按软件过程活动将软件工具分为 $\color{green}{\text{软件开发工具}}$ 、 $\color{green}{\text{软件维护工具}}$ $\color{green}{\text{、软件管理}}$ 和 $\color{green}{\text{软件支持工具}}$ 。
软件开发工具
对应软件开发过程的各种活动, $\color{red}{\text{软件开发工具}}$ 有 $\color{green}{\text{需求分析工具}}$ 、 $\color{green}{\text{设计工具}}$ 、 $\color{green}{\text{编码与排错工具}}$ 、 $\color{green}{\text{测试工具}}$ 等。
需求分析工具
需求分析工具用以辅助软件需求分析活动,辅助系统分析员从需求定义出发,生成完整的、清晰的、一致的功能规范。功能规范是软件所要完成的功能精确而完整的陈述,描述该软件要做什么及只做什么,是软件开发者和用户间的契约,同时也是软件设计者的和实现者的依据。功能规范应正确、完整地反映用户对软件的功能要求,其表达是清晰的、无歧义的。需求分析工具的目标就是帮助分析员形成这样的功能规范。
按描述需求定义的方法可将需求分析工具分为基于自然语言或图形描述的工具和基于形式化需求定义语言的工具。
基于自然语言或图形描述的工具
这类工具采用分解与抽象等基本手段,对用户问题逐步求精,并在检测机制的辅助下,发现其中可能存在的问题(如一致性),通过对问题描述的修改,逐步形成能正确反映用户需求的功能规范。它能帮助分析员提高需求文档的质量,降低功能规范的维护费用。这里以支持结构化方法的需求分析工具为例介绍。
结构化分析方法采用数据流图的描述方法,分析的主要结果是一套分层的数据流图和一个数据词典。结构化需求分析工具通常由图形编辑器、数据词典管理器和检测机制三部分组成。使用图形编辑器绘制数据流图,该图形编辑器应支持图形的分层结构,以构成分层数据流图。在构造数据流图的同时把数据流图的有关信息(如加工名、数据流名、数据项、文件名等及它们之间的联系)填入数据词典。在填写数据词典的过程中,数据词典管理器即可查出重名等错误。在构造出分层数据流图后,可通过检测机制来检查分层数据流图的合法性,可发现诸如父图与子图不平衡,遗漏的数据流(如无输入数据流或无输出数据流的加工),只有读文件没有写文件或只有写文件没有读文件等错误。然后将修改后的数据流图和词典与用户交流,考察它是否符合用户的功能需求。若不一致,再使用图形编辑器进行修改。需求分析工具还应具备同步修改的功能,即修改数据流图的同时也修改数据词典中的有关信息,以保持数据流图与数据词典的一致性。经过多次反复的交流和修改,使功能规范逐步达到准确、完整和一致,最后形成有效的功能规范。除此以外,该工具还可浏览数据词典,生成各种统计或查询报告。
基于形式化需求定义语言的工具
基于形式化需求定义语言的工具大多以基于知识的需求智能助手的形式出现,并把人工智能技术运用于软件工程。这类工具通常具有一个知识库和一个推理机制。知识库中存放需求分析所需的公共知识,以及特定的应用领域知识。这些知识能用来理解需求定义中的省略写法,能部分消除不完整性和歧义性。推理机制能容忍需求定义的无序性,部分解决描述中的不一致性。这类工具接受用形式化语言书写的功能描述,运用知识库中的知识,通过推理,发现需求定义中的矛盾和不足,经补充、更新知识库中的知识和规则,以及与系统分析员的不断交互,得到完整的功能规范。
其他需求分析工具
可执行规范语言以及原型技术为需求分析工具提供了另一条实现途径,这些工具通过运行可执行规范或原型,将有关的结果显示给用户和系统分析员,以便进行需求确认。
设计工具
设计工具用以辅助软件设计活动,辅助设计人员从软件功能规范出发,得到相应的设计规范。
设计规范是符合功能规范和需求定义中所指定的功能及性能要求,对软件的组织或其组成部分的内部结构的描述。通常设计规范分成概要设计规范和详细设计规范。概要设计规范描述软件的功能模块及其相互关系,说明模块的处理过程和外部行为,同时还应描述数据的逻辑结构。详细设计规范描述每个模块的处理算法及涉及到的全部数据结构。设计规范是程序员进行编程活动的依据。
编码与排错工具
编码工具和排错工具用以辅助程序员进行编码活动。编码工具辅助程序员用某种程序语言编制源程序,并对源程序进行翻译,最终转换成可执行的代码,因此编码工具通常与编码所使用的程序语言密切相关。排错工具用来辅助程序员寻找源程序中错误的性质和原因,并确定其出错的位置。由于源程序一般以正文的形式出现,必须有编辑器将它输入,并进行浏览、编辑和修改。又由于源程序的编写往往不会一次成功,需要不断寻找其中的错误并加以纠正。编码工具和排错工具是编程活动的重要辅助工具,也是最早出现的软件工具。
编码工具
主要有编辑程序、汇编程序、编译程序和生成程序等。
● 编辑程序:编辑程序用以输入源程序,并对其进行增加、删除和修改等操作。除常见的以字符为单位进行编辑的正文编辑程序外,还有面向程序语言语法单位的语法制导编辑程序和混合编辑程序。语法制导编辑程序也称结构化编辑程序,它可根据程序语言的语法规则提供编辑时的语法制导和检查,可以一次扩展或删除一个语法单位,如语句、表达式等,从而确保输入的源程序在语法上是正确的。混合编辑程序兼有正文编辑和语法制导编辑两种方法。
● 汇编程序:汇编程序用以将汇编语言书写的程序翻译成等价的机器语言程序。如果汇编程序所生成的机器指令代码是另一种计算机的机器指令,便称这类汇编程序为交叉汇编程序。
● 编译程序:编译程序用以将高级程序语言书写的程序翻译成等价的低级程序语言程序。
● 生成程序:生成程序通常根据与领域有关的甚高级语言或某种专用语言描述的用户需求,自动生成高级程序语言或低级程序语言描述的程序。例如,词法分析生成程序LEX,它根据正规表达式表示的词法规则,自动生成词法分析程序的代码段,来实现能识别所说明的正规表达式的有限状态自动机。
一般把汇编程序和编译程序看作语言处理程序,生成程序属于软件自动化范围,所以编码工具主要是指编辑程序。
排错工具
已有的排错工具主要有源代码排错程序和排错程序生成程序两类。
● 源代码排错程序:源代码排错程序用以帮助程序员理解程序的执行状态,可通过对程序执行过程中各种状态的判别进行程序错误的识别、定位及改正。
● 排错程序生成程序:排错程序生成程序是一种通用的排错工具。对给定的程序语言,它能生成一个相应的源代码排错程序。
软件维护工具
软件维护工具辅助软件维护过程中的活动,辅助维护人员对软件代码及其文档进行各种维护活动。 $\color{red}{\text{软件维护工具}}$ 主要有 $\color{green}{\text{版本控制工具}}$ 、 $\color{green}{\text{文档分析工具}}$ 、 $\color{green}{\text{开发信息库工具}}$ 、 $\color{green}{\text{逆向工程工具}}$ 和 $\color{green}{\text{再工程工具}}$ 等。
版本控制工具
在软件开发和维护过程中一个软件会有多个版本,版本控制工具用来存储、更新、恢复和管理一个软件的多个版本。UNIX的(Source Code Control System, SCCS)(源代码控制系统)是版本控制工具的典型代表。SCCS能为正文文件的多个版本建立一棵版本树,第一版完整储存文本全文,以后各版只存放它之前版本的不同之处,在任何时刻SCCS只允许对一个当前版本进行修改和提交。通过版本树维护版本的更新历史,并允许恢复到以前的某个版本。
文档分析工具
文档分析工具用以对软件开发过程中形成的文档进行分析,给出软件维护活动所需的维护信息。例如,基于数据流图的需求文档分析工具可给出对数据流图的某个成分(如加工)进行维护时的影响范围及被影响范围,以便在该成分修改的同时考虑其影响范围内的其他成分是否也要修改。基于模块结构图的设计文档分析工具可以给出对模块变量进行维护时的影响及被影响范围。针对程序文档的源代码分析工具可给出模块、全局变量、局部变量的定义、引用情况,它还可以进行程序分片。程序分片是把程序中与指定的数据项或数据结构有关的程序代码抽出来,过滤掉与其无关的代码,以便维护人员高效地理解和把握他所关心的部分。文档分析工具还可得到被分析的文档的有关信息,如文档各种成分的个数、定义及引用情况等。
开发信息库工具
开发信息库工具用来维护软件项目的开发信息,包括对象、模块等。它记录每个对象的修改信息(已确定的错误及重要改动)和其他变形(如抽象数据结构的多种实现);维护对象和与之有关信息之间的关系,包括模块的设计者、新版本中模块的改动及其与错误、测试用例、测试结果之间的联系等;其他必须记录的信息,包括用来生成此软件产品的所有工具的版本信息(如编译程序、连接程序、生成程序的版本号),所采用的命令语言程序和系统库以及测试用例版本和测试报告。
逆向工程工具
在软件生存周期中,将某种形式表示的软件转换成更高抽象形式表示的软件的活动称为逆向工程。例如,用反汇编工具将机器语言代码转换成汇编语言代码,用反编译工具将汇编语言代码或机器语言代码转换成某种高级程序语言源程序,之后再将源程序转换成详细设计的某种表示形式,这都属于逆向工程的范畴。逆向工程工具就是辅助软件人员进行这种逆向工程活动的软件工具。若软件缺乏必要的文档,原先的开发人员又已调离,就需使用逆向工程工具来理解原有的软件。
再工程工具
再工程工具用来支持重构一个功能和性能更为完善的软件系统。目前的再工程工具主要集中在代码重构、程序结构重构和数据结构重构等方面。
代码重构工具可把用一种程序语言书写的程序转换成用另一种程序语言书写的或适用于不同硬件平台的程序,例如FORTRAN到C的转换工具。程序结构重构工具接受一个非结构化或结构化程度较低的源程序,构造出行为等价的结构化程序。数据结构重构工具通过对数据描述的分析,重构新的数据结构。
软件管理和软件支持工具
软件管理过程和软件支持过程往往要涉及到软件生存周期中的多个活动,软件管理和软件支持工具用来辅助管理人员和软件支持人员的管理活动和支持活动,以确保软件高质高效地完成。
辅助 $\color{red}{\text{软件管理和软件支持的工具}}$ 有很多,其中常用的工具有 $\color{green}{\text{项目管理工具}}$ 、 $\color{green}{\text{配置管理工具}}$ 、 $\color{green}{\text{软件评价工具}}$ 等。
项目管理工具
项目管理工具用来辅助软件的项目管理活动。通常项目管理活动包括项目的计划、调度、通信、成本估算、资源分配及质量控制等。一个项目管理工具通常把重点放在某一个或某几个特定的管理环节上,而不提供对管理活动包罗万象的支持。
例如成本估算工具,采用某种成本估算模型(如COCOMO模型)对项目的成本进行估算。它可以通过间接的测量(如对代码行和功能点的测量)来估算项目的规模大小,并描述总的项目特征,如问题的复杂度、开发组经验和过程成熟度等。然后按一定的估算模型估算出项目的工作量、工期和开发人数等。当项目截止期限变更时,可检测它对整个开发成本的影响。
配置管理工具
配置管理工具用以辅助完成软件配置项的标识、版本控制、变化控制、审计和状态统计等基本任务,使各配置项的存取、修改和系统生成易于实现,从而简化审计过程,改进状态统计,减少错误,提高系统的质量。
软件评价工具
软件评价工具用以辅助管理人员进行软件质量保证的有关活动。它通常可按某个软件质量模型(如McCall软件质量模型,ISO软件质量度量模型等)对被评价的软件进行度量,然后得到相关的软件评价报告。目前许多度量指标还不能定量化,需要通过专家评分,再将得分送给软件评价工具。对一些已经定量化的度量指标则可利用评价工具自动获取。有的评价工具还可分析被评价程序的程序结构,根据某种软件复杂性模型(如Mc-Cabe的环路复杂度等)对被评价的程序进行复杂性度量。软件评价工具有助于软件的质量控制,对确保软件的质量有重要的作用。
软件开发工具的评价和选择
现在各类软件开发工具十分丰富,有免费的,有价格便宜的,也有昂贵的。评价和选择适合本人、本单位、本项目的软件开发工具,可以根据以下标准来衡量软件开发工具的优劣。
(1)功能。软件开发工具不仅要实现所遵循的功能需求,支持用户所选定的开发方法,还应能检查与之相关的方法学能否正确执行,并保证产生与方法学一致的输出结果。
(2)易用性。软件开发工具应有十分友好的用户界面,用户乐于使用;工具应能剪裁和定制,以适应特定用户的需要;工具应能提示用户的交互操作,提供简单有效的执行方式;工具还应能检查用户的操作错误,尽可能自动改正错误。
(3)稳健性。一个好的软件开发工具应能长期可靠地使用,并能适应环境或其他条件变化的要求;即使在非法操作或故障情况下,也不应导致严重后果。
(4)硬件要求和性能。软件开发工具的性能(如响应速度、占用存储空间的大小等),将直接影响工具的使用效果。合理的性能和对硬件的要求可以使机器的资源能被有效地加以利用,使用户的投资发挥最大的作用。
(5)服务和支持。软件开发工具的生产厂商应能为该工具提供有效的技术服务(如培训、咨询、版本更新等),工具的文档应该齐全、通俗易懂。
需求管理
软件需求开发的最终文档经过评审批准后,则定义了开发工作的需求基线(baseline)。这个基线在客户和开发者之间构筑了计划产品功能需求和非功能需求的一个约定(agreement)。需求约定是需求开发和需求管理之间的桥梁。
需求管理是一个对系统需求变更、了解和控制的过程。需求管理过程与需求开发过程相互关联,当初始需求导出的同时就启动了需求管理规划,一旦形成了需求文档的初稿,需求管理活动就开始了。需求管理的主要活动如图4-7所示。
$\color{green}{\text{图4-7 需求管理的主要活动}}$
需求管理强调:
(1)控制对需求基线的变动。
(2)保持项目计划与需求一致。
(3)控制单个需求和需求文档的版本情况。
(4)管理需求和联系链,或者管理单个需求和其他项目可交付产品之间的依赖关系。
(5)跟踪基线中的需求状态。
需求管理原则
$\color{green}{\text{过程能力成熟度模型}}$ (Capability Maturity Model, CMM)在软件开发机构中被广泛用来指导软件过程改进。该模型描述了软件处理能力的5个成熟级别。为了达到过程能力成熟度模型的 $\color{green}{\text{第二级}}$ ,组织机构必须具有 $\color{green}{\text{6个关键过程域}}$ (Key Process Areas, KPA)。
$\color{red}{\text{需求管理}}$ 是其中之一,它的目标如下。
(1)为软件需求建立一个 $\color{green}{\text{基线}}$ ,提供给软件工程和管理使用。
(2)软件计划、产品和活动与软件需求保持 $\color{green}{\text{一致}}$ 。
关于需求管理过程域内的原则和策略,可以参考:
(1)需求管理的关键过程领域不涉及收集和分析项目需求,而是假定已收集了软件需求,或者已由更高一级的系统给定了需求。一旦需求获得并且文档化了,软件开发组和有关的团队(例如质量保证和测试组)需要评审文档。发现问题应与客户或者其他需求源协商解决。软件开发计划是基于已确认的需求。
(2)开发人员在向客户以及有关部门承诺(commitment)某些需求之前,应该确认需求和约束条件、风险、偶然因素、假定条件等。也许不得不面对由于技术因素或者进度等原因,承诺一些不现实的需求。但是,决不要承诺任何无法实现的事。
(3)关键处理领域同样建议通过版本控制和变更控制来管理需求文档。版本控制确保随时能知道在项目开发和计划中正在使用的需求的版本情况。变更控制提供了支配下的规范的方式来统一需求变更,并且基于业务和技术的因素来同意或者反对建议的变更。当在开发中修改、增加、减少需求时,软件开发计划应该随时更新,确保与新的需求保持一致。
需求规格说明的版本控制
在软件开发过程中,可能出现测试人员使用已过时的软件规格说明,结果发现了一大堆的错误,为了避免这种情况的发生,需求规格说明的版本管理就显得非常重要了。
版本控制是管理需求的一个必要方面,必须统一确定需求文档的每一个版本。软件开发组的每一个成员必须得到需求的当前版本。当需求发生变更时,应该清楚地把变更写成文档,并且及时通知所有涉及的人员。为了尽量减少困惑、冲突和误传,应该仅允许指定的人员来更新需求。
每一个新版本的需求文档,应该公布其包括修正版本在内的历史情况,例如,变更的内容、变更日期、变更人员的姓名以及变更的原因等。任何新文档的第一版应当标记为“1.0版(草案1)”,下一稿标记为“1.0版(草案2)”,在文档被确认为基线前,草案数可以随着改进逐次增加,当文档被确认为基线后,被标记为“1.0正式版”。以后,如果有较小的修改,可以标记为“1.1版(草案1)”,如果有较大的修改,可以标记为“2.0版(草案1)”。这种方法可以很清楚地区分草稿和文档定稿的版本。
$\color{green}{\text{需求属性}}$
除了文本,每一个功能需求应该有一些相关的信息与它联系,我们把这些信息称为需求属性。对于一个大型的复杂项目来说,丰富的属性类别显得尤为重要。例如,在文档中考虑和明确如下属性:
● 创建需求的时间。
● 需求的版本号。
● 创建需求的作者。
● 负责认可该软件需求的人员。
● 需求状态。
● 需求的原因和根据。
● 需求涉及的子系统。
● 需求涉及的产品版本号。
● 使用的验证方法或者接受的测试标准。
● 产品的优先级或者重要程度。
● $\color{green}{\text{需求的稳定性}}$ 。
需求变更
一个大型软件系统的需求总是有变化的,原因是该系统通常是要解决一些复杂和难度大的问题,而一些问题不可能一次就被完全定义;此外,开发者对问题的理解可能在变化,这些变化也反映到需求中。
对许多项目来说,系统软件总需要不断完善,一些需求的改进是合理的而且不可避免,要使得软件需求完全不变更,也许是不可能的,但毫无控制的变更是项目陷入混乱、不能按进度完成,或者软件质量无法保证的主要原因之一。事实上,迟到的需求变更会对已进行的工作产生非常大的影响。如果不控制范围的扩展,将使我们持续不断地采纳新功能,而且要不断地调整资源、进度或者质量标准,是极为有害的。如果每一个建议的需求变更都采用,该项目将有可能永远不能完成。
软件需求文档应该精确描述要交付的产品,这是一个基本的原则。为了使开发组织能够严格控制软件项目,应该确保以下事项:
● 仔细评估已建议的变更。
● 挑选合适的人选对变更做出决定。
● 变更应及时通知所有涉及的人员。
● 项目要按一定的程序来采纳需求变更。
变更控制过程
一个好的变更控制过程,给项目风险承担者提供了正式的建议需求变更机制。通过这些处理过程,项目负责人可以在信息充分的条件下做出决策。我们可以通过变更控制过程来跟踪已建议变更的状态,使已建议的变更确保不会丢失或疏忽。一旦确定了需求基线,应该使所有已建议的变更都遵循变更控制过程。
需求变更管理过程如图4-8所示。
$\color{green}{\text{图4-8 需求变更管理过程}}$
(1) $\color{green}{\text{问题分析和变更描述}}$ 。这是识别和分析需求问题或者一份明确的变更提议,以检查它的有效性,从而产生一个更明确的需求变更提议。
(2) $\color{green}{\text{变更分析和成本计算}}$ 。使用可追溯性信息和系统需求的一般知识,对需求变更提议进行影响分析和评估。变更成本计算应该包括对需求文档的修改、系统修改的设计和实现的成本。一旦分析完成并且被确认,应该进行是否执行这一变更的决策。
(3) $\color{green}{\text{变更实现}}$ 。这要求需求文档和系统设计以及实现都要同时修改。如果先对系统的程序做变更,然后再修改需求文档,这几乎不可避免地会出现需求文档和程序的不一致。
变更控制过程并不是给变更设置障碍。相反地,它是一个渠道和过滤器,通过它可以确保采纳最合适的变更,使变更产生的负面影响降到最低。变更过程应该做成文档,而且要简单、有效。
控制需求变更与项目的其他配置管理决策也有着密切的联系。项目管理应该达成一个策略,用来描述如何处理需求变更,而且策略具有现实可行性。
我们可以参考以下的需求变更策略:
(1)所有需求变更必须遵循变更控制过程。
(2)对于未获得批准的变更,不应该做设计和实现工作。
(3)变更应该由项目变更控制委员会决定实现哪些变更。
(4)项目风险承担者应该能够了解变更数据库的内容。
(5)决不能从数据库中删除或者修改变更请求的原始文档。
(6)每一个集成的需求变更必须能跟踪到一个经核准的变更请求。
在实际中,人们总是希望使用自动工具来执行变更控制过程。有许多人使用商业问题跟踪工具来收集、存储、管理需求变更。可以使用工具对一系列最近提交的变更建议产生一个列表给变更控制委员会开会时做议程用。 $\color{green}{\text{问题跟踪工具}}$ 也可以随时按变更状态分类报告变更请求的数目。
挑选工具时可以考虑以下几个方面:
(1)可以定义变更请求的数据项。
(2)可以定义变更请求生存期的状态转换图。
(3)可以加强状态转换图使经授权的用户仅能做出所允许的状态变更。
(4)记录每一种状态变更的数据,确认做出变更的人员。
(5)可以定义在提交新请求或请求状态被更新后应该自动通知的设计人员。
(6)可以根据需要生成标准的或定制的报告和图表。
变更控制委员会
变更控制委员会可以帮助我们很好地管理项目,哪怕是一个小项目。一个有效率的变更控制委员会定期地考虑每个变更请求,并且基于由此带来的影响和获益做出及时地决策。
变更控制委员会只要能决定合适的人做正确的事就足够了,不必追求大而全。变更控制委员会负责决定哪些已建议需求变更或者新产品特性付诸应用,决定在哪些版本中纠正哪些错误。广义上,变更控制委员会对项目中任何基线工作产品的变更都可以做出决定,需求变更文档仅是其中之一。
变更控制委员会可以由一个小组担任,也可以由多个不同的组担任。变更控制委员会的成员应能代表变更涉及的团体。变更控制委员会可能包括如下方面的代表:
(1)产品或计划管理部门。
(2)项目管理部门。
(3)开发部门。
(4)测试或质量保证部门。
(5)市场部或客户代表。
(6)制作用户文档的部门。
(7)技术支持部门。
(8)帮助桌面或用户支持热线部门。
(9)配置管理部门。
对于小项目只需几个人充当其中的一些角色就可以,并不一定要面面俱到。组建包含软、硬件两方面的项目的变更控制委员会时,也要包括来自硬件工程、系统工程、制造部门或者硬件质量保证和配置管理的代表。建立变更控制委员会在保证权威性的前提下应尽可能精简人员。
变更控制委员会应该有一个总则,用于描述变更控制委员会的目的、授权范围、成员构成、做出决策的过程及操作步骤。总则也应该说明举行会议的频度和事由。管理范围描述该委员会能做什么样的决策,以及有哪一类决策应上报到高一级的委员会。过程及操作步骤如下。
制定决策
制定决策过程的描述应确认:
● 变更控制委员会必须到会的人数或做出有效决定必须出席的人数。
● 决策的方法(例如投票,一致通过或其他机制)。
● 变更控制委员会主席是否可以否决该集体的决定。
变更控制委员会应该对每个变更权衡利弊后做出决定。“利”包括节省的资金或额外的收入、增强的客户满意度、竞争优势、减少上市时间;“弊”是指接受变更后产生的负面影响,包括增加的开发费用、推迟的交付日期、产品质量的下降、减少的功能、用户不满意。如果估计的费用超过了本级变更控制委员会的管理范围,应上报到高一级的委员会,否则用制订的决策过程来对变更做出决定。
交流情况
一旦变更控制委员会做出决策,指派的人员应及时更新数据库中请求的状态。有的工具可以自动通过电子邮件来通知相关人员。若没有这样的工具,就应该人工通知,以保证他们能充分处理变更。
重新协商约定
变更总是有代价的。即使拒绝的变更也因为决策行为(提交、评估、决策)而耗费了资源。变更对新的产品特性会有很大的影响。如果对一个工程项目增加很多新功能,又要求在原先确定的进度计划、人员安排、资金预算和质量要求限制内完成整个项目是不现实的。
当工程项目接受了重要的需求变更时,为了适应变更情况要与管理部门和客户重新协商约定。协商的内容可能包括推迟交货时间、要求增加人手、推迟实现尚未实现的较低优先级的需求,或者质量上进行折中。要是不能获得一些约定的调整,应该把面临的风险写进风险管理计划中。
需求跟踪
需求跟踪包括编制每个需求同系统元素之间的联系文档,这些元素包括别的需求、体系结构、其他设计部件、源代码模块、测试、帮助文件和文档等。跟踪能力信息使变更影响分析十分便利,有利于确认和评估实现某个建议的需求变更所必须的工作。
跟踪能力(联系)链(traceability link)可以使我们跟踪一个需求使用期限的全过程,也就是从初始需求到实现的前后生存期。跟踪能力是优秀需求规格说明书的一个特征,为了实现可跟踪能力,必须统一地标识出每一个需求,以便能明确地进行查阅。
需求跟踪能力链有4类,如图4-9所示。
图4-9 $\color{red}{\text{需求可跟踪能力}}$
这4类需求跟踪能力链如下:
● 客户需求向前追溯到软件需求。这样就能区分出开发过程中或者开发结束后,由于客户需求变更受到影响的软件需求。这也就可以确保软件需求规格说明包括所有客户需求。
● 从软件需求回溯相应的客户需求。这也就是确认每个软件需求的源头。如果用使用实例的形式来描述客户需求,那么客户需求与软件需求之间的跟踪情况就是使用实例和功能性需求。
● 从软件需求向前追溯到下一级工作产品。由于开发过程中系统需求转变为软件需求、设计、编码等,所以通过定义单个需求和特定的产品元素之间的(联系)链,可以从需求向前追溯到下一级工作产品。这种联系链告诉我们每个需求对应的产品部件(构件),从而确保产品部件满足每个需求。
● 从产品部件回溯到软件需求。说明了每个部件存在的原因。如果不能把设计元素、代码段或测试回溯到一个需求,就可能存在“画蛇添足”的程序。然而,如果这些孤立的元素表明了一个正当的功能,则说明需求规格说明书漏掉了一项需求。
跟踪能力联系链记录了单个需求之间的父层、互连和依赖的关系。当某个需求变更(被删除或修改)后,这种信息能够确保正确的变更传播,并将相应的任务做出正确的调整。一个项目不必拥有所有种类的跟踪能力联系链,要根据具体的情况调整。
需求变更的代价和风险
“变更是免费的”这种误解是造成项目范围延伸的主要原因之一。人们往往只有在知道变更的成本后才能做出理智的选择。变更需求是要付出代价的,只要允许软件需求变更或者添加新特性,一个表面上很简单的变更也可能转变成很复杂的局面。
大部分的开发人员会遇到添加“没有代价且不影响进度的变更”的要求。没有人愿意做一个费时费力还要担心意想不到的需求变更的事情。需求变更对软件的进度、成本、技术和效率都会有不同程度的影响,变更只能在项目时间、预算、资源等的限制内进行协商。
影响分析是需求管理的一个重要组成部分。影响分析可以提供对建议的变更的准确理解,帮助做出信息量充分的变更批准决策。通过对变更内容的检验,确定对现有的系统做出是修改或者抛弃的决定;或者创建新系统以及评估每个任务的工作量。进行影响分析的能力依赖于跟踪能力、数据的质量和完整性。
开发管理
项目的范围、时间、成本
$\color{green}{\text{范围}}$
在初步项目范围说明书中已文档化的主要的可交付物、假设和约束条件的基础上准备详细的项目范围说明书,是项目成功的关键。在项目规划中,知道了更多的项目信息,项目范围应被更详细地进行描述。应检查假设和约束条件的完整性,并根据需要增加必要的补充假设和约束条件。项目团队和其他对项目范围有不同见解的与项目相关的人,可以基于此履行和准备项目分析。
$\color{red}{\text{范围定义的输入}}$ 包括以下内容。
(1) $\color{green}{\text{项目章程}}$ 。如果项目章程或初始的范围说明书没有在项目执行组织中使用,同样的信息需要进一步收集和开发,以产生详细的项目范围说明书。
(2) $\color{green}{\text{项目范围管理计划}}$ 。
(3) $\color{green}{\text{组织过程资产}}$ 。
(4) $\color{green}{\text{批准的变更申请}}$ 。
经核准的需求变更能引发项目质量、范围、成本或进度的变更。变更申请常常在项目进行过程中被确认,变更申请有多种形式:口头的或书面的,直接的或间接的、外在的或内部的,法律、契约要求的或随意的。
时间
项目时间管理包括使项目按时完成所必需的管理过程。进度安排的准确程度可能比成本估计的准确程度更重要。对于成本估计的偏差,软件产品可以靠重新定价或者大量的销售来弥补成本的增加,但如果进度计划不能得到实施则会导致市场机会的丧失或者用户不满意,而且会使成本增加。因此在考虑进度安排时要把人员的工作量与花费的时间联系起来,合理分配工作量,利用进度安排的有效分析方法来严密监视项目的进展情况,以使项目的进度不被拖延。
$\color{red}{\text{项目时间管理}}$ 中的过程包括: $\color{green}{\text{活动定义}}$ 、 $\color{green}{\text{活动排序}}$ 、 $\color{green}{\text{活动的资源估算}}$ 、 $\color{green}{\text{活动历时估算}}$ 、 $\color{green}{\text{制订进度计划}}$ 以及 $\color{green}{\text{进度控制}}$ 。
为了得到工作分解结构(Work Breakdown Structure, WBS)中最底层的交付物,必须执行一系列的活动。对这些活动的识别以及归档的过程就叫做活动定义。毋庸置疑,定义这些活动的最终目的是为了完成项目的目标。
项目提出后比较明确的一般只是项目的目标,为使项目目标得以实现并且制订出比较完善的项目进度计划,则在对项目进行分解的基础上还必须对分解出的具体目标进行定义,只有这样才能使目标更明确,因此对活动定义是非常必要的。
成本
项目成本管理是项目管理的一个重要组成部分,它是指在项目的实施过程中,为了保证完成项目所花费的实际成本不超过其预算成本而展开的项目成本估算、项目预算编制和项目成本控制等方面的管理活动。它包括在批准的预算内完成项目所需要的诸过程,主要有如下一些。
● $\color{green}{\text{成本估算}}$ :编制一个为完成项目各活动所需要的资源成本的近似估算。
● $\color{green}{\text{成本预算}}$ :将总的成本估算分配到各项活动和工作包上,来建立一个成本的基线。
● $\color{green}{\text{成本控制}}$ :控制项目预算的变更。
虽然这里的各个过程是彼此独立、相互间有明确界定的,但在实践中,它们可能会交叉重迭,互相影响,同时与其他知识领域的过程也相互作用。
项目成本管理首先关心的是完成项目活动所需资源的成本,但也应考虑项目决策对项目产品成本的影响。如限制设计审查次数可以降低项目成本,但可能增加顾客的运营成本。项目成本管理的这种广义观点常被称为“全生命周期成本计算”。
在许多应用领域,对项目产品的财务经营状况的预测和分析是在项目之外进行的。但在某些领域(如资金筹措项目),项目成本管理也包括这一工作,这种情况下,项目成本管理将包括一些附加的过程和管理技术,如投资回报、折算现金流、投资回收分析等。
项目成本管理应该考虑项目干系人的信息需求,不同的项目干系人会在不同的时间,以不同的方式检查项目成本。如:采购物品的成本可能在决策结束、订购、发货、收货或会计记账时检查。
为保证项目能够完成预定的目标,必须要加强对项目实际发生成本的控制,一旦项目成本失控,就很难在预算内完成项目,不良的成本控制常常会使项目处于超出预算的危险境地。可是在项目的实际实施过程中,项目超预算的现象还是屡见不鲜。
配置管理、文档管理
$\color{green}{\text{配置管理}}$
配置管理在项目管理中具有重要的地位和作用。近年来,信息系统项目的规模越来越大,复杂性越来越高;管理上的失误给我们的教训也越来越深刻。这都使得人们不得不重视配置管理问题。
配置管理是PMBOK、ISO9000和CMMI中的重要组成元素,它在产品开发的生命周期中,提供了结构化的、有序化的、产品化的管理方法,是项目管理的基础工作。配置管理是通过技术和行政手段对产品及其开发过程和生命周期进行控制、规范的一系列措施和过程。信息系统开发过程中的变更以及相应的返工会对产品的质量有很大的影响。如果不从配置管理方面加以控制,必将导致严重的后果。配置管理的一个重要内容就是对变更加以控制,使变更对成本、工期和质量的影响降到最小。
$\color{red}{\text{产品配置}}$ 是指一个产品在其生命周期各个阶段所产生的各种形式(机器可读或人工可读)和各种版本的文档、计算机程序、部件及数据的集合。该集合中的每一个元素称为该产品配置中的一个 $\color{green}{\text{配置项}}$ (Configuration Item, CI),配置项主要有以下两大类。
● 属于 $\color{red}{\text{产品组成}}$ 部分的工作成果,如 $\color{green}{\text{需求文档}}$ 、 $\color{green}{\text{设计文档}}$ 、 $\color{green}{\text{源代码}}$ 和 $\color{green}{\text{测试用例}}$ 等。
● 属于 $\color{red}{\text{项目管理和机构支撑过程域}}$ 产生的文档,如 $\color{green}{\text{工作计划}}$ 、 $\color{green}{\text{项目质量报告}}$ 、 $\color{green}{\text{项目跟踪报告}}$ 等。这些文档虽然不是产品的组成部分,但是值得保存。
每个配置项的主要属性有名称、标识符、文件状态、版本、作者和日期等。所有配置项都被保存在配置库里,确保不会混淆、丢失。配置项及其历史记录反映了项目产品的演化过程。
置于配置管理之下的工作产品包括将交付给顾客的产品、指定的内部工作产品、采办的产品、工具和其他用于创建和描述这些工作产品的实体。
文档管理
文档是影响软件可维护性的决定因素。由于长期使用的大型软件系统在使用过程中必然会经受多次修改,所以文档比程序代码更重要。
软件系统的文档可以分为 $\color{green}{\text{用户文档}}$ 和 $\color{green}{\text{系统文档}}$ 两类。用户文档主要描述系统功能和使用方法,并不关心这些功能是怎样实现的;系统文档描述系统设计、实现和测试等各方面的内容。
总的说来,软件文档应该满足下述要求:
(1)必须描述如何使用这个系统,没有了这种描述即使是最简单的系统也无法使用。
(2)必须描述怎样安装和管理这个系统。
(3)必须描述系统需求和设计。
(4)必须描述系统的实现和测试,以便使系统成为可维护的。
下面分别讨论用户文档和系统文档。
$\color{green}{\text{用户文档}}$
用户文档是用户了解系统的第一步,它可以让用户获得对系统的准确的初步印象。
用户文档至少应该包括下述5方面的内容。
(1) $\color{green}{\text{功能描述}}$ :说明系统能做什么。
(2) $\color{green}{\text{安装文档}}$ :说明怎样安装这个系统以及怎样使系统适应特定的硬件配置。
(3) $\color{green}{\text{使用手册}}$ :简要说明如何着手使用这个系统(通过丰富的例子说明怎样使用常用的系统功能,并说明用户操作错误时怎样恢复和重新启动)。
(4) $\color{green}{\text{参考手册}}$ :详尽描述用户可以使用的所有系统设施以及它们的使用方法,并解释系统可能产生的各种出错信息的含义(对参考手册最主要的要求是完整,因此通常使用形式化的描述技术)。
(5) $\color{green}{\text{操作员指南}}$ (如果需要有系统操作员的话):说明操作员应如何处理使用中出现的各种情况。
$\color{green}{\text{系统文档}}$
所谓系统文档指从 $\color{green}{\text{问题定义}}$ 、 $\color{green}{\text{需求说明}}$ 到 $\color{green}{\text{验收测试计划}}$ 这样一系列和系统实现有关的文档。 $\color{green}{\text{描述系统设计}}$ 、 $\color{green}{\text{实现}}$ 和 $\color{green}{\text{测试}}$ 的文档对于理解程序和维护程序来说是非常重要的。
软件开发的质量与风险
软件质量
成功的项目管理是在约定的时间和范围、预算的成本以及要求的质量下,达到项目干系人的期望。能否成功地管理一个项目,质量的好坏也非常重要。质量管理是项目管理的重要方面之一,它与范围、成本和时间是项目成功的关键因素。项目质量管理包括为确保项目能够满足所要执行的需求的过程,包括质量管理职能的所有活动。
ISO9000对项目质量的定义是:一组固有特性满足需求的程度。需求指明示的、通常隐含的或必须履行的需求或期望。特性是指可区分的特征,可以是固有的或赋予的、定性的或定量的、有各种类别(物理的、感官的、行为的、时间的、功能的等)。
美国质量管理协会把质量定义为“过程、产品或服务满足明确或隐含的需求能力的特征”。质量与范围、成本和时间是项目成功的关键因素。明确和隐含的需求是制定项目需求的输入。在项目领域,质量管理的一个关键因素是通过项目范围管理转换隐含需求为项目需求。不要把质量和等级相混淆,等级是指具有相同使用功能不同技术特性的产品或服务的类别。质量低说明产品或服务存在问题,没有达到要求,而等级低的产品或服务就不一定存在问题。
软件开发风险
项目是在复杂的自然和社会环境中进行的,受众多因素的影响。对于这些内外因素,从事项目活动的主体往往认识不足或者没有足够的力量加以控制。项目的过程和结果常常出乎人们的意料,有时不但未达到项目主体预期的目的,反而使其蒙受各种各样的损失;而有时又会给他们带来很好的机会。项目同其他经济活动一样带有风险。要避免和减少损失,将威胁化为机会,项目主体就必须了解和掌握项目风险的来源、性质和发生规律,进而施行有效的管理。
对项目风险进行管理,国际上已经成为项目管理的重要方面。如世界银行对每一个贷款项目都进行风险分析,制定风险管理计划,写在有关的文件之中,并付诸行动。
在项目所处的自然、经济、社会和政治环境中,每一个项目都有风险。完全避开或消除风险,或者只享受权益而不承担风险,是不可能的。另一方面,对项目风险进行认真的分析、科学的管理,是能够避开不利条件、少受损失、取得预期的结果并实现项目目标的。
当事件、活动或项目有损失或收益与之相联系,涉及到某种或然性或不确定性和涉及到某种选择时,才称为有风险。以上三条,每一个都是风险定义的必要条件,不是充分条件。具有不确定性的事件不一定是风险。
项目风险是一种不确定的事件或条件,一旦发生,会对项目目标产生某种正面或负面的影响。风险有其成因,同时,如果风险发生,也导致某种后果。举例来说,风险成因可能是需要获取某种许可,或是项目的人力资源受到限制。风险事件本身则是获取许可所花费的时间可能比计划的要长,或是可能没有充足的人员来完成项目工作。以上任何一种不确定事件一旦发生,都会给项目的成本、进度计划或质量带来某种后果。风险条件可能包括组织环境中导致项目风险的某些因素,如不良的项目管理,或对不能控制的外部参与方的依赖。
项目风险既包括对项目目标的威胁,也包括促进项目目标的机会。风险源于所有项目之中的不确定因素。已知风险是那些已经经过识别和分析的风险。对于已知风险,进行相应计划是可能的。虽然项目经理们可以依据以往类似项目的经验,采取一般的应急措施处理未知风险,但未知风险是无法管理的。
设计方法
结构化分析与设计
结构化程序设计的概念最早由E. W. Dijkstra提出,其理由是GOTO语句对程序的可读性、可测试性和可维护性带来极大的危害,应该用更可维护的控制结构替代它。随后,Bohm和Jacopini证明了仅用“顺序”、“分支”和“循环”三种基本的控制构件即能构造任何单入口单出口程序,这个结论奠定了结构程序设计的理论基础。
何谓结构程序设计,目前尚无定论,较流行的定义为:结构程序设计是程序设计技术,它采用自顶向下逐步求精的设计方法和单入口单出口的控制构件。
自顶向下逐步求精的方法是人类解决复杂问题时常用的一种方法,采用这种先整体后局部,先抽象后具体的步骤开发的软件一般具有较清晰的层次。此外,由于仅使用单入口单出口的控制构件,使程序有良好的结构特征,这些都能大大降低程序的复杂性,增强程序的可读性、可维护性和可验证性,从而提高软件的生产率。
另一方面,采用结构程序设计的技术可能会多占用一些时间和空间资源,这也是那些反对从高级语言中排除GOTO语句者的主要依据。实际上,随着硬件技术的飞速发展,因结构程序设计所增加的这点耗费对大多数应用来说已不再是重要的因素。
结构程序设计的思想应该在软件设计中体现出来,但这并不排除为效率或其他原因对结构程序设计做一点修正。随着面向对象、软件重用等新的软件开发方法和技术的发展,更现实、更有效的开发途径可能是自顶向下和自底向上两种方法有机的结合。
$\color{green}{\text{面向对象的分析设计}}$
面向对象的分析模型主要由 $\color{green}{\text{顶层架构图}}$ 、 $\color{green}{\text{用例与用例图}}$ 、 $\color{green}{\text{领域概念模型}}$ 构成;设计模型则包含以 $\color{green}{\text{包图}}$ 表示的软件体系结构图、以 $\color{green}{\text{交互图}}$ 表示的 $\color{green}{\text{用例实现图}}$ 、完整精确的 $\color{green}{\text{类图}}$ 、针对复杂对象的 $\color{green}{\text{状态图}}$ 和用以描述流程化处理过程的 $\color{green}{\text{活动图}}$ 等。为完成这一转换过程,设计人员必须处理以下任务:
(1)针对分析模型中的用例,设计实现方案。实现方案用UML交互图表示。
(2)设计技术支撑设施。在大型软件项目中,往往需要一些技术支撑设施来帮助业务需求层面的类或子系统完成其功能。这些设施本身并非业务需求的一部分,但却为多种业务需求的实现提供公共服务。例如,数据的持久存储服务、安全控制服务和远程访问服务等。在面向对象设计中,需要研究这些技术支撑设施的实现方式以及它们与业务需求层面的类及子系统之间的关系。
设计用户界面。针对分析模型中的领域概念模型以及引进的新类,完整、精确地确定每个类的属性和操作,并完整地标示类之间的关系。此外,为了实现软件重用和强内聚、松耦合等软件设计原则,还可以对已经形成的类图进行各种微调,最终形成足以构成面向对象程序设计的基础和依据的详尽类图。面向对象的软件设计过程如图4-10所示。
图4-10 面向对象的软件设计过程
软件的重用
软件重用是指在两次或多次不同的软件开发过程中重复使用相同或相似软件元素的过程。软件元素包括需求分析文档、设计过程、设计文档、程序代码、测试用例和领域知识等。对于新的软件开发项目而言,它们或者是构成整个目标软件系统的部件,或者在软件开发过程中发挥某种作用。通常将这些软件元素称为软部件。
为了能够在软件开发过程中重用现有的软部件,必须在此之前不断地进行软部件的积累,并将它们组织成软部件库。这就是说,软件重用不仅要讨论如何检索所需的软部件以及如何对它们进行必要的修剪,还要解决如何选取软部件、如何组织软部件库等问题。因此,软件重用方法学通常要求软件开发项目既要考虑重用已有软部件的机制,又要系统地考虑生产可重用软部件的机制。这类项目通常称为软件重用项目。
按照重用活动是否跨越相似性较少的多个应用领域,软件重用可区别为 $\color{green}{\text{横向重用}}$ 和 $\color{green}{\text{纵向重用}}$ 。 $\color{green}{\text{横向重用}}$ (horizontal reuse)是指重用不同应用领域中的软件元素,例如数据结构、分类算法和人机界面构件等。 $\color{green}{\text{标准函数库}}$ 是一种典型的、原始的横向重用机制。纵向重用是指在一类具有较多公共性的应用领域之间进行软部件重用。因为在两个截然不同的应用领域之间实施软件重用的潜力不大,所以纵向重用才广受瞩目,并成为软件重用技术的真正希望所在。不难理解,纵向重用活动的主要关键点即是域分析:根据应用领域的特征及相似性预测软部件的可重用性。一旦根据域分析确认了软部件的重用价值,即可进行软部件的开发,并对具有重用价值的软部件进行一般化,以便它们能够适应新的类似的应用领域。然后,软部件及其文档即可进入软部件库,成为可供后续开发项目使用的可重用资源。这些步骤构成软部件的构造活动。显然,它是一个软部件不断积累、不断完善的渐进过程。随着软部件的不断丰富,软部件库的规模会不断扩大,因此,库的组织结构将直接影响软部件的检索效率,特别是当检索手段并不局限于标准函数库所采用的简单名字匹配方法时。可供候选的软部件从库中被检索出来以后,用户还必须理解其功能或行为,以判别它是否真正适应于当前项目。必要时可考虑对某个与期望的功能/行为匹配程度最佳的软部件进行稍许修改,甚至可以将修改后的软部件加进软部件库以替代原有软部件。当然,这要求修改后的软部件比原有软部件具有更高的重用价值。上述软件重用方法如图4-11所示。
图4-11 软件重用方法原理
使用重用技术可以减少软件开发活动中大量的重复性工作,这样就能够提高软件生产率,降低开发成本,缩短开发周期。同时,由于软部件大都经过严格的质量认证,并在实际运行环境中得到检验,因此重用软部件有助于改善软件质量。此外,大量使用软部件,软件的软件逆工程灵活性和标准化程度也可望得到提高。
逆向工程与重构工程
逆向工程与重构工程是目前预防性维护采用的主要技术。逆向工程术语源于硬件制造业,相互竞争的公司为了了解对方设计和制造工艺的机密,在得不到设计和制造说明书的情况下,通过拆卸实物获取信息,软件的逆向工程也基本类似,不过通常“解剖”的不仅是竞争对手的程序,而且还包括本公司多年前的产品,此时得不到设计“机密”的主要障碍是缺乏文档。因此,所谓软件的逆向工程就是分析已有的程序,寻求比源代码更高级的抽象表现形式。一般认为,凡是在软件生命周期内将软件某种形式的描述转换成更为抽象形式的活动都可称为逆向工程。与之相关的概念是:重构(restructuring),指在同一抽象级别上转换系统描述形式;设计恢复(design recovery),指借助工具从已有程序中抽象出有关数据设计、总体结构设计和过程设计的信息(不一定是原设计);重构工程(re-engineering),也称修复和改造工程,它是在逆向工程所获信息的基础上修改或重构已有的系统,产生系统的一个新版本。
恢复信息的级别
逆向工程导出的信息可分为如下4个抽象层次。
(1) $\color{green}{\text{实现级}}$ :包括程序的抽象语法树、符号表等信息。
(2) $\color{green}{\text{结构级}}$ :包括反映程序分量之间相互依赖关系的信息,例如调用图、结构图等。
(3) $\color{green}{\text{功能级}}$ :包括反映程序段功能及程序段之间关系的信息。
(4) $\color{green}{\text{领域级}}$ :包括反映程序分量或程序诸实体与应用领域概念之间对应关系的信息。
显然,上述信息的抽象级别越高,它与代码的距离就越远,通过逆向工程恢复的难度亦越大,而自动工具支持的可能性相对变小,要求人参与判断和推理的工作增多。
恢复信息的方法
在逆向工程中用于恢复信息的方法有4类。第一类为用户指导下的搜索与变换(User-Directed Search and Transformation)。此类方法用于导出实现级和结构级信息。它要求维护人员在数据库系统的支持下,运用询问语言,针对源代码或与之相近的表示形式,指定待查找的句型(pattern),根据搜索结果析出所需信息或进行特殊变换。
第二类方法为变换式方法(Transformational Approaches),除领域级外所有抽象级别上的信息都可用此类方法推导。变换式方法又细分为不需要维护人员过多干涉的自动分析法(如静态分析和调用图、控制流图生成等)和基于特定库的用户指导变换法两类。变换方法自动化程度越高,得到的设计信息越粗略,因为任何深层次的分析不可避免地要借助人的智力。一般借助变换法得到程序的某种中间表示形式,通过进一步使用其他工具将已获粗略的设计信息精化为完整、一致的软件设计。
第三类方法是基于领域知识的(Domain Knowledge-Based),主要用于恢复功能级和领域级信息。领域知识一般用规则库表示,用已确定或假定的领域概念与代码之间的对应关系推导进一步的假设,最后导出程序的功能。显然该类方法的不确定性最大,因此目前成熟的工具和原型系统还很少见。
最后一类方法称为铅板恢复法,这类方法仅适用于推导实现级和结构级信息。这些方法用于识别程序设计“铅板”或公共结构,“铅板”既可为一个简单算法(如两变量互换值),亦可为相对复杂的成分(如冒泡分类)。因铅板与程序之间可能存在多种匹配形式,所以此类方法还包含大量的推理与决策。各类方法采用的输入形式、搜索策略和推理策略都不尽相同。后两类方法又称为基于知识的方法。
尽管每个软件组织都可能有数百万行代码可供重构,但由于缺乏时机和支持工具或者因为经济上得不偿失,往往只有那些决定或移植、或重新设计、或为重用而需验证正确性的程序才被选择实施逆向工程。
网课
软件开发模型
图片详情
瀑布模型(SDLC)
图片详情
瀑布模型十有八九会失败,需求明确
结构化方法的一种模型
其他经典模型
图片详情
原型:用于需求分析
增量:只做核心的模块,一步步进行
螺旋模型
图片详情
风险分析
V模型
图片详情
和瀑布测试比:测试提到了重要的位置,测试贯穿始终
类似建筑:先拉线再测试
喷泉模型与RAD
喷泉模型是面对对象
构建组装模型(CBSD)
图片详情
旧构建稳定性大于新构建
统一过程(UP)
RUP=UP
图片详情
用例驱动
架构为中心
迭代和增量的特征
敏捷开发方法
图片详情
不需要的文档砍掉
逆向工程
山寨
图片详情
军事:飞机会销毁核心部件
面向对象的基本概念
图片详情
- 实体类:数据相关
- 边界类:跟外部的系统沟通
封装的理念:不能直接操作属性,要用getter,setter
泛化:更多的类
模式:经验
需求的分析
图片详情
业务需求:涉及到哪些角色,功能
用户需求:去用户那边收集
系统需求:软件上技术层面的需求
设计约束:必须用java,oracle
基本需求:表达的需求
期望需求:没有表达都要做好的
兴奋需求:不一定要做
需求的获取
- 收集资料
- $\color{green}{\text{联合需求计划}}$
- 用户访谈(目的,对象,一对一,一对多)
- 书面调查(主观,客观,问卷收不回来)
- 情节串联板(用户有感觉)
- 现场观摩
- 参加业务实践
- 阅读历史文档
- 抽样调查
图片详情
需求分析
《软件设计师教程第5版》 pp.337
结构化分析(结构化分析(Structured Analysis, SA)、结构化设计(Structured Design,SD)和结构化程序设计(Structured Programming Design,SPD)构成了完整的结构化方法。)
ER,数据流图
图片详情
数据流图DFD,分层
外部实体是指存在于软件系统外的人员,组织或物品,还可以是其他的系统。
STD行为模式
ER图
数据字典,用来解释描述相关的信息
业务流程重组(BRP)与业务流程管理(BMP)
业务流程重组(BRP)
业务流程管理(BMP)
人机界面设计
图片详情
流水线:一键XX
结构化设计
图片详情
内聚和耦合
图片详情
测试原则和类型
每次考试必考
图片详情
尚未发现的错误数量与该程序已发现错误数成正比
测试用例设计
图片详情
测试截断
图片详情
系统测试:压力性能,一般不是测试功能
面向对象测试
- √算法层(单元测试)︰包括等价类划分测试、组合功能测试(基于判定表的测试)、递归函数测试和多态消息测试
- √类层(模块测试):包括不变式边界测试、模态类测试和非模态类测试
- √模板层/类树层(集成测试)∶包括多态服务测试和展平测试
- √系统层(系统测试)
测试管理
绩效和什么时候结束测试
图片详情
- 人为植入bug
- 并行测试估算
- e/(e+d)交付之后才能找到
软件调试
图片详情
原因排除法:演绎归纳
系统运行与维护
图片详情
改进性维护:修改运行的时候才发现的bug
适应性:新的服务器(软硬环境)
完善性:性能更高
预防性:将来会出问题,写文档也算
软件能力成熟度模型集成(CMMI)
图片详情
已管理:项目级的经验
已定义级:企业级的经验
定量管理级:量化
优化级:优化
写的太完美,大环境可能不允许
范围管理
图片详情
项目管理
图片详情
单代号网络图
图片详情
FS:A完成B开始(finish start)
FF:A完成B才能完成
SS: A开始B才能开始,同时开始
SF:A开始B才能结束(新老系统切换的时候)
关键路径:最长的路径
双代号网络图
图片详情
虚活动表达一种依赖关系
自由时差
图片详情
图片详情
自由时差影响紧后活动
甘特图
图片详情
成本管理
图片详情
管理储备:储备都是为了应对风险
挣值管理
图片详情
AC:actual value,实际花掉的钱,一般题目直接给出,直接加起来就好了
EV:evaluate value,
CPI:0.75,花了1块钱,完成0.75的任务
- 非典型偏差不考虑之前的进度
质量管理
图片详情
图片详情
图片详情
使用质量:用户体验
如何背:自己先进行划分一次,只需要注意划分不同的就行了
PDCA_质量保证及质量控制的介绍
PDCA
图片详情
质量保证及质量控制
图片详情
- 质量保证: 看过程,包含了质量控制
- 质量控制:看结果
质量管理工具
图片详情
帕累托:解决最需要解决的问题(28定理)
项目管理三角形
图片详情
不用的因素互相影响
配置管理
图片详情
图片详情
变更控制
图片详情
版本控制
图片详情
风险管理
- 关心未来
- 关心变化
- 关心选择
图片详情
机会也是风险,只不过是积极风险