软件开发过程概述

第1章 软件开发过程概述

1.1 软件开发过程概述

1.1.1 软件的概念

软件(Software)简单的说就是那些在计算机中能看的着,但摸不着的东西,概念性的说软件也称为“软设备”,广义地说软件是指系统中的程序以及开发、使用程序所需要的所有文档的集合软件分为系统软件和应用软件。

软件并不只是包括可以在计算机上运行的程序,与这些程序相关的文件一般也被认为是软件的一部分。

软件被应用于世界的各个领域,对人们的生活和工作都产生了深远的影响。

1. 系统软件

系统软件是负责管理计算机系统中各种独立的硬件,使得它们可以协调工作。系统软件使得计算机使用者和其他软件将计算机当作一个整体而不需要顾及到底层每个硬件是如何工作的。

一般来讲,系统软件包括操作系统和一系列基本的工具(比如编译器,数据库管理,存储器格式化,文件系统管理,用户身份验证,驱动管理,网络连接等方面的工具)。

2. 应用软件

应用软件是为了某种特定的用途而被开发的软件。它可以是一个特定的程序,比如一个图像浏览器。也可以是一组功能联系紧密,可以互相协作的程序的集合,比如微软的Office软件。也可以是一个由众多独立程序组成的庞大的软件系统,比如数据库管理系统。 较常见的有:文字处理软件 如WPS、Word等;信息管理软件;辅助设计软件 如AutoCAD ;实时控制软件;教育与娱乐软件。

1.1.2 编程与软件开发

软件开发的内容是:需求、设计、编程和测试。

(1)需求:不仅仅是用户需求,应该是开发中遇到的所有的需求。比如,你首先要知道做这个项目是为了解决什么问题;测试案例中应该输入什么数据......为了清楚地知道这些需求,你经常要和客户、项目经理等交流。

(2)设计:编码前,肯定有个计划告诉你要做什么,结构是怎样等等。你一定要按照这个来做,否则可能会一团糟。

(3)编程:如果在项目截止日,你的程序不能跑起来或达不到客户的要求,你就拿不到钱。

(4)测试:目的是让你知道,什么时候算是完成了。如果你聪明,你就应该先写测试,这样可以及时知道你是否真地完成了。否则,你经常会不知道,到底有哪些功能是真正完成了,离预期目标还差多远。

软件开发中,客户和开发人员都有自己的基本权利和义务。

(1)客户:

定义每个用户需求的商业优先级;

制订总体计划,包括用多少投资、经过多长时间、达到什么目的;

在项目开发过程中的每个工作周,都能让投资获得最大的收益;

通过重复运行你所指定的功能测试,准确地掌握项目进展情况;

能随时改变需求、功能或优先级,同时避免昂贵的再投资;能够根据各种变化及时调整项目计划;

能够随时取消项目;项目取消时,以前的开发工作不是一堆垃圾,已开发完的功能是合乎要求的,正在进行或未完成的的工作则应该是不难接手的。

(2)开发人员:

知道要做什么,以及要优先做什么;

工作有效率;

有问题或困难时,能得到客户、同事、上级的回答或帮助;

对工作做评估,并根据周围情况的变化及时重新评估;

积极承担工作,而不是消极接受分配。

1.1.3 软件开发过程

软件开发过程一般分为以下6个阶段:

1. 计划

对所要解决的问题进行总体定义,包括了解用户的要求及现实环境,从技术、经济和社会因素等3个方面研究并论证本软件项目的可行性,编写可行性研究报告,探讨解决问题的方案,并对可供使用的资源(如计算机硬件、系统软件、人力等)成本,可取得的效益和开发进度作出估计。制订完成开发任务的实施计划。

2. 分析

软件需求分析就是回答做什么的问题。它是一个对用户的需求进行去粗取精、去伪存真、正确理解,然后把它用软件工程开发语言(形式功能规约,即需求规格说明书)表达出来的过程。本阶段的基本任务是和用户一起确定要解决的问题,建立软件的逻辑模型,编写需求规格说明书文档并最终得到用户的认可。需求分析的主要方法有结构化分析方法、数据流程图和数据字典等方法。本阶段的工作是根据需求说明书的要求,设计建立相应的软件系统的体系结构,并将整个系统分解成若干个子系统或模块,定义子系统或模块间的接口关系,对各子系统进行具体设计定义,编写软件概要设计和详细设计说明书,数据库或数据结构设计说明书,组装测试计划。

3. 设计

软件设计可以分为概要设计和详细设计两个阶段。实际上软件设计的主要任务就是将软件分解成模块是指能实现某个功能的数据和程序说明、可执行程序的程序单元。可以是一个函数、过程、子程序、一段带有程序说明的独立的程序和数据,也可以是可组合、可分解和可更换的功能单元。模块,然后进行模块设计。概要设计就是结构设计,其主要目标就是给出软件的模块结构,用软件结构图表示。详细设计的首要任务就是设计模块的程序流程、算法和数据结构,次要任务就是设计数据库,常用方法还是结构化程序设计方法。

4. 编码

软件编码是指把软件设计转换成计算机可以接受的程序,即写成以某一程序设计语言表示的"源程序清单"。充分了解软件开发语言、工具的特性和编程风格,有助于开发工具的选择以及保证软件产品的开发质量。

当前软件开发中除在专用场合,已经很少使用二十世纪80年代的高级语言了,取而代之的是面向对象的开发语言。而且面向对象的开发语言和开发环境大都合为一体,大大提高了开发的速度。

5. 测试

软件测试的目的是以较小的代价发现尽可能多的错误。要实现这个目标的关键在于设计一套出色的测试用例(测试数据和预期的输出结果组成了测试用例)。如何才能设计出一套出色的测试用例,关键在于理解测试方法。不同的测试方法有不同的测试用例设计方法。两种常用的测试方法是白盒法测试对象是源程序,依据的是程序内部的的逻辑结构来发现软件的编程错误、结构错误和数据错误。结构错误包括逻辑、数据流、初始化等错误。用例设计的关键是以较少的用例覆盖尽可能多的内部程序逻辑结果。白盒法和黑盒法依据的是软件的功能或软件行为描述,发现软件的接口、功能和结构错误。其中接口错误包括内部/外部接口、资源管理、集成化以及系统错误。黑盒法用例设计的关键同样也是以较少的用例覆盖模块输出和输入接口。黑盒法。

6. 维护

维护是旨在已完成对软件的研制(分析、设计、编码和测试)工作并交付使用以后,对软件产品所进行的一些软件工程的活动。即根据软件运行的情况,对软件进行适当修改,以适应新的要求,以及纠正运行中发现的错误。编写软件问题报告、软件修改报告。

一个中等规模的软件,如果研制阶段需要一年至二年的时间,在它投入使用以后,其运行或工作时间可能持续五年至十年。那么它的维护阶段也是运行的这五年至十年期间。在这段时间,人们几乎需要着手解决研制阶段所遇到的各种问题,同时还要解决某些维护工作本身特有的问题。做好软件维护工作,不仅能排除障碍,使软件能正常工作,而且还可以使它扩展功能,提高性能,为用户带来明显的经济效益。然而遗憾的是,对软件维护工作的重视往往远不如对软件研制工作的重视。而事实上,和软件研制工作相比,软件维

护的工作量和成本都要大得多。

在实际开发过程中,软件开发并不是从第一步进行到最后一步,而是在任何阶段,在进入下一阶段前一般都有一步或几步的回溯。在测试过程中的问题可能要求修改设计,用户可能会提出一些需要来修改需求说明书等。

1.2 软件需求分析

1.2.1 需求获取

需求获取(requirement elicitation)是需求工程的主体。对于所建议的软件产品,获取需求是一个确定和理解不同用户类的需要和限制的过程。获取用户需求位于软件需求三个层次的中间一层。业务需求决定用户需求,它描述了用户利用系统需要完成的任务。从这些任务中,分析者能获得用于描述系统活动的特定的软件功能需求,这些系统活动有助于用户执行他们的任务。

需求获取是在问题及其最终解决方案之间架设桥梁的第一步。获取需求的一个必不可少的结果是对项目中描述的客户需求的普遍理解。一旦理解了需求,分析者、开发者和客户就能探索出描述这些需求的多种解决方案。参与需求获取者只有在他们理解了问题之后才能开始设计系统,否则,对需求定义的任何改进,设计上都必须大量的返工。把需求获取集中在用户任务上—而不是集中在用户接口上—有助于防止开发组由于草率处理设计问题而造成的失误。

需求获取、分析、编写需求规格说明和验证并不遵循线性的顺序,这些活动是相互隔开、增量和反复的。当你和客户合作时,你就将会问一些问题,并且取得他们所提供的信息(需求获取)。同时,你将处理这些信息以理解它们,并把它们分成不同的类别,还要把客户需求同可能的软件需求相联系(分析)。然后,你可以使客户信息结构化,并编写成文档和示意图(说明)。下一步,就可以让客户代表评审文档并纠正存在的错误(验证)。这四个过程贯穿着需求分析的整个阶段。 需求获取可能是软件开发中最困难、最关键、最易出错及最需要交流的方面。需求获取只有通过有效的客户—开发者的合作才能成功。分析者必须建立一个对问题进行彻底探讨的环境,而这些问题与产品有关。为了方便清晰地进行交流,就要列出重要的小组,而不是假想所有的参与者都持有相同的看法。对需求问题的全面考察需要一种技术,利用这种技术不但考虑了问题的功能需求方面,还可讨论项目的非功能需求。确定用户已经理解:对于某些功能的讨论并不意味着即将在产品中实现它。对于想到的需求必须集中处理并设定优先级,以避免一个不能带来任何益处的无限大的项目。

需求获取是一个需要高度合作的活动,而并不是客户所说的需求的简单誊本。作为一个分析者,你必须透过客户所提出的表面需求理解他们的真正需求。询问一个可扩充(open-ended)的问题有助于你更好地理解用户目前的业务过程并且知道新系统如何帮助或改进他们的工作。调查用户任务可能遇到的变更,或者用户需要使用系统其它可能的方式。想像你自己在学习用户的工作,你需要完成什么任务?你有什么问题?从这一角度来指导需求的开发和利用。

还有,探讨例外的情况:什么会妨碍用户顺利完成任务?对系统错误情况的反映,用户是如何想的?询问问题时,以“还有什么能” ,”当?时,将会发生什么”“你有没有曾经想过” ,“有没有人曾经”为开头。记下每一个需求的来源,这样向下跟踪直到发现特定的客户。

有些时候,尝试着问一些“愚蠢”的问题也有助于客户打开话匣子。如果你直接要求客户写出业务是如何实现的,客户十有八九无法完成。但是如果你尝试着问一些实际的问题,例如:“以我的理解,你们收到订单后,会...”。客户立刻就会指出你的错误,并滔滔不绝的开始谈论业务,而你,就在一边仔细的聆听吧。这一招就叫做“抛砖引玉”。

需求讨论会上必须要使用笔记本电脑,还要指定一个打字熟练的人把所有的讨论记录下来,记录的同时还要做一定的整理。如果不这样做,那么你结束会议的时候就会发现,所有的讨论只剩下一个模糊的印象,需求对你来说仍然是一件遥远的事情。在座谈讨论之后,记下所讨论的条目(item),并请参与讨论的用户评论并更正。及早并经常进行座谈讨论是需求获取成功的一个关键途径,因为只有提供需求的人才能确定是否真正获取需求。进行深入收集和分析以消除任何冲突或不一致性。

尽量把客户所持的假设解释清楚,特别是那些发生冲突的部分。从字里行间去理解以明确客户没有表达清楚但又想加入的特性或特征。Gause 和Weinberg(1989)提出使用“上下文无关问题”—这是一个高层次的问题,它可以获取业务问题和可能的解决方案的全部信息。客户对这些问题的回答诸如“产品要求怎样的精确度”或“你能帮我解释一下你为什么不同意某人的回答吗?”这些回答可以更直接地认识问题,而这是封闭(close-end)问题所不能做到的。

需求获取利用了所有可用的信息来源,这些信息描述了问题域或在软件解决方案中合理的特性。一个研究表明:比起不成功的项目,一个成功的项目在开发者和客户之间采用了更多的交流方式(Kiel and Carmel 1995)。与单个客户或潜在的用户组一起座谈,对于业务软件包或信息管理系统(MIS)的应用来说是一种传统的需求来源。直接聘请用户进行获取需求的过程是为项目获得支持和买入(buy-in)的一种方式。

尽量理解用户用于表述他们需求的思维过程。充分研究用户执行任务时作出决策的过程,并提取出潜在的逻辑关系。流程图和决策树是描述这些逻辑决策途径的好方法。

在需求获取的过程中,你可能会发现对项目范围的定义存在误差,不是太大就是太小。如果范围太大,你将要收集比真正需要更多的需求,以传递足够的业务和客户的值,此时获取过程将会拖延。如果项目范围太小,那么客户将会提出很重要的但又在当前产品范围之外的需求。当前的范围太小,以致不能提供一个令人满意的产品。需求的获取将导致修改项目的范围和任务,但作出这样具有深远影响的改变,一定要小心谨慎。

正如经常所说的,需求主要是关于系统做什么,而解决方案如何实现是属于设计的范围。这样说虽然很简洁,但似乎过于简单化。需求的获取应该把重点放在“做什么”上,但在分析和设计之间还是存在一定的距离。你可以使用假设“怎么做”来分类并改善你对用户需求的理解。在需求的获取过程中,分析模型、屏幕图形和原型可以使概念表达得更加清楚,然后提供一个寻找错误和遗漏的办法。把你在需求开发阶段所形成的模型和屏幕效果看成是方便高效交流的概念性建议,而不应该看成是对设计者选择的一种限制。

需求获取讨论会中如果参与者过多,就会减慢进度。人数大致控制在5到7人是最好的。这些人包括客户、系统设计者、开发者和可视化设计者等主要工程角色。相反地,从极少的代表那里收集信息或者只听到呼声最高、最有舆论影响的用户的声音,也会造成问题。这将导致忽视特定用户类的重要的需求,或者其需求不能代表绝大多数用户的需要。最好的权衡在于选择一些授权为他们的用户类发言的产品代表者,他们也被同组用户类的其它代表所支持。

1.2.2 需求分析

1. 定义

所谓“需求分析”,是指对要解决的问题进行详细的分析,弄清楚问题的要求,包括需要输入什么数据,要得到什么结果,最后应输出什么。可以说,“需求分析”就是确定要计算机“做什么”。

在软件工程中,需求分析指的是在建立一个新的或改变一个现存的电脑系统时描写新系统的目的、范围、定义和功能时所要做的所有的工作。需求分析是软件工程中的一个关键过程。在这个过程中,系统分析员和软件工程师确定顾客的需要。只有在确定了这些需要后他们才能够分析和寻求新系统的解决方法。

在软件工程的历史中,很长时间里人们一直认为需求分析是整个软件工程中最简单的一个步骤,但在过去十年中越来越多的人认识到它是整个过程中最关键的一个过程。假如在需求分析时分析者们未能正确地认识到顾客的需要的话,那么最后的软件实际上不可能达到顾客的需要,或者软件无法在规定的时间里完工。

2. 特点

需求分析是一项重要的工作,也是最困难的工作。该阶段工作有以下特点:

(1)用户与开发人员很难进行交流

在软件生存周期中,其它四个阶段都是面向软件技术问题,只有本阶段是面向用户的。需求分析是对用户的业务活动进行分析,明确在用户的业务环境中软件系统应该"做什么"。但是在开始时,开发人员和用户双方都不能准确地提出系统要"做什么?"。因为软件开发人员不是用户问题领域的专家,不熟悉用户的业务活动和业务环境,又不可能在短期内搞清楚;而用户不熟悉计算机应用的有关问题。由于双方互相不了解对方的工作,又缺乏共同语言,所以在交流时存在着隔阂。

(2)用户的需求是动态变化的

对于一个大型而复杂的软件系统,用户很难精确完整地提出它的功能和性能要求。一开始只能提出一个大概、模糊的功能,只有经过长时间的反复认识才逐步明确。有时进入到设计、编程阶段才能明确,更有甚者,到开发后期还在提新的要求。这无疑给软件开发带来困难。

(3)系统变更的代价呈非线性增长

需求分析是软件开发的基础。假定在该阶段发现一个错误,解决它需要用一小时的时

间,到设计、编程、测试和维护阶段解决,则要花2.5、5、25、100倍的时间。

因此,对于大型复杂系统而言,首先要进行可行性研究。开发人员对用户的要求及现实环境进行调查、了解,从技术、经济和社会因素三个方面进行研究并论证该软件项目的可行性,根据可行性研究的结果,决定项目的取舍。

3. 任务

(1)确定对系统的综合要求

虽然功能需求是对软件系统的一项基本需求,但却并不是唯一的需求,通常对软件系统有下述几方面的综合要求。

a、功能需求

b、性能需求

c、可靠性和可用性需求

d、出错处理需求

e、接口需求

f、约束

g、逆向需求

h、将来可能提出的要求

(2)分析系统的数据要求

任何一个软件本质上都是信息处理系统,系统必须处理的信息和系统应该产生的信息很大程度上决定了系统的面貌,对软件设计有深远的影响,因此,必须分析系统的数据要求,这是软件分析的一个重要任务。分析系统的数据要求通常采用建立数据模型的方法。

复杂的数据由许多基本的数据元素组成,数据结构表示数据元素之间的逻辑关系。 利用数据字典可以全面地定义数据,但是数据字典的缺点是不够直观。为了提高可理解性,常常利用图形化工具辅助描述数据结构。用用的图形工具有层次方框图和Warnier图。

(3)导出系统的逻辑模型

综合上述两项分析的结果可以导出系统的详细的逻辑模型,通常用数据流图、E-R图、状态转换图、数据字典和主要的处理算法描述这个逻辑模型。

(4)修正系统开发计划

根据在分析过程中获得的对系统的更深入的了解,可以比较准确地估计系统的成本和进度,修正以前定制的开发计划。

4. 方法

进行需求分析,应注意以下几点:

(1)首先调查组织机构情况

包括了解该组织的部门组成情况,各部门的职能等,为分析信息流程作准备。

(2)然后调查各部门的业务活动情况

包括了解各个部门输入和使用什么数据,如何加工处理这些数据,输出什么信息,输

出到什么部门,输出结果的格式是什么。

(3)协助用户明确对新系统的各种要求

包括信息要求、处理要求、完全性与完整性要求。

(4)确定新系统的边界

确定哪些功能由计算机完成或将来准备让计算机完成,哪些活动由人工完成。由计算机完成的功能就是新系统应该实现的功能。

需求分析常用的调查方法有:

(1)跟班作业

通过亲身参加业务工作来了解业务活动的情况。这种方法可以比较准确地理解用户的需求,但比较耗费时间。

(2)开调查会

通过与用户座谈来了解业务活动情况及用户需求。座谈时,参加者之间可以相互启发。

(3)请专人介绍。

(4)询问

对某些调查中的问题,可以找专人询问。

(5)设计调查表请用户填写

如果调查表设计得合理,这种方法是很有效,也很易于为用户接受的。

(6)查阅记录

即查阅与原系统有关的数据记录,包括原始单据、账簿、报表等。

通过调查了解了用户需求后,还需要进一步分析和表达用户的需求。

分析和表达用户需求的方法主要包括自顶向下和自底向上两类方法。

1.2.3 需求文档的编写

需求的写作形式一般分为两种,面向对象和面向过程。对于不同的受众和应用,采取不同的形式。

面向过程的形式:

主要的思想是IPO的原则,也就是“输出-处理-输出”,文档格式:

(1)首先是对于整体系统的简略介绍:目的,确定文档描述的对象和大体内容

(2)系统上下文,介绍系统和其他系统之间的关系,边界如何划分

(3)系统的需求分解,介绍完成整体系统需要分解的大框架的需求内容

(4)具体需求

对于具体需求很简单,按照如下形式完成:

a、简介

b、输入

c、处理

d、输出

(5)除了具体需求外,还包括其他相关方面的需求:

a、接口需求(与其他系统、子系统、模块的接口,用户接口等)所谓的界面原型,其

实是接口需求中的内容。由于界面原型通常都很重要,所以可以将这一部分拿出来放到具体需求中去。

界面原型不是仅仅一张图,还包括界面元素的描述、范围、错误提示信息等

b、性能需求

c、依赖:依赖的数据库、第三方软件等

d、需求优先级排序,用于衡量开发策略

(6)参考文档

面向对象的形式,整体文档架构是和上面描述的一致,区别只有两点。

(1)在系统的需求分解处,用用例的包图来描述、这个很简单,其实就是上面文字描述的图形化显示。

(2)主要区别是具体需求,通过用例的形式来描述,包括:

a、介绍

b、用户(actor)

c、前置条件

d、后置条件

e、触发条件

f、事件流

g、备选事件流

1.3 软件系统架构设计

软件架构(software architecture)是一系列相关的抽象模式,用于指导大型软件系统各个方面的设计。软件架构是一个系统的草图。软件架构描述的对象是直接构成系统的抽象组件。各个组件之间的连接则明确和相对细致地描述组件之间的通讯。在实现阶段,这些抽象组件被细化为实际的组件,比如具体某个类或者对象。在面向对象领域中,组件之间的连接通常用接口_(计算机科学)来实现。

软件体系结构是构建计算机软件实践的基础。与建筑师设定建筑项目的设计原则和目标,作为绘图员画图的基础一样,一个软件架构师或者系统架构师陈述软件构架以作为满足不同客户需求的实际系统设计方案的基础。

软件构架是一个容易理解的概念,多数工程师(尤其是经验不多的工程师)会从直觉上来认识它,但要给出精确的定义很困难。特别是,很难明确地区分设计和构架:构架属于设计的一方面,它集中于某些具体的特征。

在“软件构架简介”中,David GArlan 和 Mary Shaw 认为软件构架是有关如下问题的设计层次:“在计算的算法和数据结构之外,设计并确定系统整体结构成为了新的问题。结构问题包括总体组织结构和全局控制结构;通信、同步和数据访问的协议;设计元素的功能分配;物理分布;设计元素的组成;定标与性能;备选设计的选择。”

但构架不仅是结构;IEEE Working Group on Architecture 把其定义为“系统在其环境中的最高层概念”。构架还包括“符合”系统完整性、经济约束条件、审美需求和样式。它并不仅注重对内部的考虑,而且还在系统的用户环境和开发环境中对系统进行整体考虑,即

同时注重对外部的考虑。

在 Rational Unified ProcESs 中,软件系统的构架(在某一给定点)是指系统重要构件的组织或结构,这些重要构件通过接口与不断减小的构件与接口所组成的构件进行交互。

从和目的、主题、材料和结构的联系上来说,软件架构可以和建筑物的架构相比拟。一个软件架构师需要有广泛的软件理论知识和相应的经验来事实和管理软件产品的高级设计。软件架构师定义和设计软件的模块化,模块之间的交互,用户界面风格,对外接口方法,创新的设计特性,以及高层事物的对象操作、逻辑和流程。

1.3.1 软件架构的要素

一般而言,软件系统的架构(ArchitECture)有两个要素:

(1)它是一个软件系统从整体到部分的最高层次的划分。

一个系统通常是由元件组成的,而这些元件如何形成、相互之间如何发生作用,则是关于这个系统本身结构的重要信息。

详细地说,就是要包括架构元件(Architecture Component)、联结器(Connector)、任务流(TASk-flow)。所谓架构元素,也就是组成系统的核心"砖瓦",而联结器则描述这些元件之间通讯的路径、通讯的机制、通讯的预期结果,任务流则描述系统如何使用这些元件和联结器完成某一项需求。

(2)建造一个系统所作出的最高层次的、以后难以更改的,商业的和技术的决定。 在建造一个系统之前会有很多的重要决定需要事先作出,而一旦系统开始进行详细设计甚至建造,这些决定就很难更改甚至无法更改。显然,这样的决定必定是有关系统设计成败的最重要决定,必须经过非常慎重的研究和考察。

1.3.2 软件架构的目标

正如同软件本身有其要达到的目标一样,架构设计要达到的目标是什么呢?一般而言,软件架构设计要达到如下的目标:

(1)可靠性(Reliable)。软件系统对于用户的商业经营和管理来说极为重要,因此软件系统必须非常可靠。

(2)安全行(Secure)。软件系统所承担的交易的商业价值极高,系统的安全性非常重要。

(3)可扩展性(SCAlable)。软件必须能够在用户的使用率、用户的数目增加很快的情况下,保持合理的性能。只有这样,才能适应用户的市场扩展得可能性。

(4)可定制化(CuSTomizable)。同样的一套软件,可以根据客户群的不同和市场需求的变化进行调整。

(5)可扩展性(Extensible)。在新技术出现的时候,一个软件系统应当允许导入新技术,从而对现有系统进行功能和性能的扩展。

(6)可维护性(MAIntainable)。软件系统的维护包括两方面,一是排除现有的错误,二是将新的软件需求反映到现有系统中去。一个易于维护的系统可以有效地降低技术支持的花费。

(7)客户体验(Customer Experience)。软件系统必须易于使用。

(8)市场时机(Time to Market)。软件用户要面临同业竞争,软件提供商也要面临同业竞争。以最快的速度争夺市场先机非常重要。

1.3.3 软件架构的种类

根据我们关注的角度不同,可以将架构分成三种:

(1)逻辑架构、软件系统中元件之间的关系,比如用户界面,数据库,外部系统接口,商业逻辑元件,等等。

(2)物理架构、软件元件是怎样放到硬件上的。

(3)系统架构、系统的非功能性特征,如可扩展性、可靠性、强壮性、灵活性、性能等。

系统架构的设计要求架构师具备软件和硬件的功能和性能的过硬知识,这一工作无疑是架构设计工作中最为困难的工作。

此外,从每一个角度上看,都可以看到架构的两要素:元件划分和设计决定。

首先,一个软件系统中的元件首先是逻辑元件。这些逻辑元件如何放到硬件上,以及这些元件如何为整个系统的可扩展性、可靠性、强壮性、灵活性、性能等做出贡献,是非常重要的信息。

其次,进行软件设计需要做出的决定中,必然会包括逻辑结构、物理结构,以及它们如何影响到系统的所有非功能性特征。这些决定中会有很多是一旦作出,就很难更改的。

根据作者的经验,一个基于数据库的系统架构,有多少个数据表,就会有多少页的架构设计文档。比如一个中等的数据库应用系统通常含有一百个左右的数据表,这样的一个系统设计通常需要有一百页左右的架构设计文档。

1.3.4 软件构架的描述

为了讨论和分析软件构架,必须首先定义构架表示方式,即描述构架重要方面的方式。在 Rational Unified Process 中,软件构架文档记录有这种描述。

(1)构架视图

我们决定以多种构架视图来表示软件构架。每种构架视图针对于开发流程中的涉众(例如最终用户、设计人员、管理人员、系统工程师、维护人员等)所关注的特定方面。

构架视图显示了软件构架如何分解为构件,以及构件如何由连接器连接来产生有用的形式,由此记录主要的结构设计决策。这些设计决策必须基于需求以及功能、补充和其他方面的约束。而这些决策又会在较低层次上为需求和将来的设计决策施加进一步的约束。

(2)典型的构架视图集

构架由许多不同的构架视图来表示,这些视图本质上是以图形方式来摘要说明“在构架方面具有重要意义”的模型元素。在 Rational Unified Process 中,您将从一个典型的视图集开始,该视图集称为“4+1 视图模型”。它包括:

用例视图:包括用例和场景,这些用例和场景包括在构架方面具有重要意义的行为、类或技术风险。它是用例模型的子集。逻辑视图:包括最重要的设计类、从这些设计类到

包和子系统的组织形式,以及从这些包和子系统到层的组织形式。它还包括一些用例实现。它是设计模型的子集。实施视图:包括实施模型及其从模块到包和层的组织形式的概览。 同时还描述了将逻辑视图中的包和类向实施视图中的包和模块分配的情况。它是实施模型的子集。进程视图:包括所涉及任务(进程和线程)的描述,它们的交互和配置,以及将设计对象和类向任务的分配情况。只有在系统具有很高程度的并行时,才需要该视图。在 Rational Unified Process 中,它是设计模型的子集。配置视图:包括对最典型的平台配置的各种物理节点的描述以及将任务(来自进程视图)向物理节点分配的情况。只有在分布式系统中才需要该视图。它是部署模型的一个子集。构架视图记录在软件构架文档中。您可以构建其他视图来表达需要特别关注的不同方面:用户界面视图、安全视图、数据视图等等。对于简单系统,可以省略4+1视图模型中的一些视图。

1.3.5 软件架构师

软体设计师中有一些技术水平较高、经验较为丰富的人,他们需要承担软件系统的架构设计,也就是需要设计系统的元件如何划分、元件之间如何发生相互作用,以及系统中逻辑的、物理的、系统的重要决定的作出。

这样的人就是所谓的架构师(Architect)。在很多公司中,架构师不是一个专门的和正式的职务。通常在一个开发小组中,最有经验的程序员会负责一些架构方面的工作。在一个部门中,最有经验的项目经理会负责一些架构方面的工作。

但是,越来越多的公司体认到架构工作的重要性,并且在不同的组织层次上设置专门的架构师位置,由他们负责不同层次上的逻辑架构、物理架构、系统架构的设计、配置、维护等工作。

1.4 软件详细设计

软件详细设计的任务是,是为软件结构图中的每个模块确定所采用的算法和块内数据结构,用某种选定的表达工具给出清晰的描述,表达工具可以自由选择,但工具必须具有描述过程细节的能力,而且能够有利于程序员在编程时便于直接翻译成程序设计语言的源程序。

程序流程图、盒图、PAD图、HIPU图、PDL语言等等都是完成详细设计的工具,选择合适的工具并且正确地使用是十分重要的。面向数据结构设计方法(Jackson方法)是进行详细设计的形式化方法。

在软件详细设计阶段,将生成详细设计说明书,为每个模块确定采用的算法,确定每个模块使用的数据结构,确定每个模块的接口细节。在软件详细设计结束时,软件详细设计说明书通过复审的形成形成正式文档,作为下一个阶段的工作依据。

在概要设计阶段,已经确定了软件系统的总体结构,给出了软件系统中各个组成模块的功能和模块间的接口。作为软件设计的饿第二步,软件详细设计就是在软件概要设计的基础上,考虑如何实现定义的软件系统,直到对系统中的每个模块给出了足够详细的过程描述。在软件详细设计以后,程序员将仍旧根据详细设计的过程编写出实际的程序代码。因此,软件详细设计的结果基本上决定了最终的程序代码质量。

1.5 软件编码

1.5.1 软件开发语言及工具的选择

程序编码阶段的任务是将软件的详细设计转换成用程序设计语言实现的程序代码。因此,程序设计语言的性能和设计风格对于程序设计的效能和质量有着直接的关系。

1. 程序设计语言特性的比较

a、软件心理学的观点

因为从设计到编码的转换基本上是人的活动,因此语言的性能对程序员的心理影响,将对转换产生重大影响。程序员总是希望选择简单易学、使用方便的语言 ,以减少程序出错率,提高软件可靠性 。从心理学的观点,影响程序员心理的语言特性有如下6种: ·一致性:它表示一种语言所使用符号的兼容程度、允许随意规定限制、以及允许对语法或语义破例的程度。同是一个符号,给予多种用途,会引起许多难以察觉的错误。 ·二义性:虽然语言的编译程序总是以一种机械的规则来解释语句,但读者则可能用不同的方式来理解语句。例如,对于一个逻辑表达式 A≥“0”and A≤“9”,读者可能对这个逻辑表达式有不同的理解。

如果一个程序设计语言缺乏一致性和存在二义性,那么用这种语言编写出来的程序可读性就差,同时用这种语言编程也容易出错。

·简洁性(紧凑性):表示程序员为了用该语言编写程序,必须记忆的有关编码的信息量。可用语言支持块结构和结构化程序的能力、可使用的保留字和缩写字的种类、数据类型的种类和缺省说明、算术运算符和逻辑运算符的种类、系统内标准函数的数目等来衡量。 遗憾的是,语言的简洁性与程序的一致性常常是抵触的。

·局部性:指程序设计语言的联想(综合)特性。综合的特性使人们能够对事物从整体上进行记忆和识别 。在编码过程中 ,由语句组合成模块,由模块组装为程序体系结构,并在组装过程中实现模块的高内聚和低耦合,可使程序的局部性加强。

·线性:指程序的联想(顺序)特性。人们总是习惯于按逻辑线性序列理解程序。如果程序中线性序列和逻辑运算较多,会提高可读性。如果存在大量的分支和循环,就会破坏顺序状态,增加理解上的困难。直接实现结构化程序可提高程序的线性特性。

·传统:人们学习一种新的程序设计语言的能力受到传统的影响。具有 Pascal 基础的程序人员在学习 C 语言时不会感到困难,因为C保持了Pascal 所确立的传统语言特性。但是要求同一个人去学习APL或者LISP这样一些语言,传统就中断了。

b、软件工程的观点

从软件工程观点,程序设计语言的特性应着重考虑软件开发项目的需要。为此,对于程序编码,有如下一些工程上的性能要求:

·详细设计应能直接地容易地翻译成代码程序:把设计变为程序的难易程度,反映了程序设计语言与设计说明相接近的程度。所选择的程序设计语言是否具有结构化的构造 ,复杂的数据结构 ,专门的输入/输出能力,位运算和串处理的能力,直接影响到从详细设

计变换到代码程序的难易程度,以及特定软件开发项目的可实现性。

·源程序应具有可移植性:源程序的可移植性通常有三种解释:①对源程序不做修改或少做修改就可以实现处理机上的移植或编译程序上的移植;②即使程序的运行环境改变(例如,改用一个新版本的操作系统),源程序也不用改变;③源程序的许多模块可以不做修改或少做修改就能集成为功能性的各种软件包,以适应不同的需要。

为改善软件的可移植性,主要是使语言标准化。在开发软件时,应严格地遵守ISO或 ANSI、GB的标准,而不要去理会特定编译器提供的非标准特性。

·编译程序应具有较高的效率。

·尽可能应用代码生成的自动工具:有效的软件开发工具是缩短编码时间 ,改善源代码质量的关键因素 。使用带有各种有效的自动化工具的“软件开发环境”,支持从设计到源代码的翻译等各项工作,可以保证软件开发获得成功。

·可维护性:源程序的可读性,语言自身的文档化特性(涉及标识符的允许长度、标号命名、数据类型的丰富程度、控制结构的规定等)是影响到可维护性的重要因素。

c、程序设计语言的技术性能

在计划阶段,极少考虑程序语言的技术特性。但在选定资源时,要规划将要使用的支撑工具,就要确定一个具体的编译器或者确定一个程序设计环境。如果软件开发组的成员对所要使用的语言不熟悉,那么在成本及进度估算时必须把学习的工作量估算在内。

一旦确定了软件需求,待选用的程序语言的技术特性就显得非常重要了。如果需要复杂的数据结构,就要仔细衡量有哪些语言能提供这些复杂的数据结构。如果首要的是高性能及实时处理的能力,就可选用适合于实时应用的语言或效率高的语言。如果该应用有许多输出报告或繁杂的文件处理,最好是根据软件的要求,选定一种适合于该项工作的语言。

软件的设计质量 与程序设计语言 的技术性能无关(面向对象设计例外)。但在实现软件设计转化为程序代码时,转化的质量往往受语言性能的影响。因而也会影响到设计方法。

语言的技术性能对测试和维护的影响是多种多样的。例如,直接提供结构化构造的语言有利于减少循环带来的复杂性(即McCabe复杂性),使程序易读、易测试、易维护。另一方面,语言的某些技术特性却会妨碍测试。例如,在面向对象的语言程序中,由于实行了数据封装,使得监控这些数据的执行状态变得比较困难;由于建立了对象类的继承结构,使得高内聚、低耦合的要求受到破坏,增加了测试的困难。此外,只要语言程序的可读性强,而且可以减少程序的复杂性,这样的程序设计语言对于软件的维护就是有利的。

总之,通过仔细地分析和比较,选择一种功能强而又适用的语言,对成功地实现从软件设计到编码的转换,提高软件的质量,改善软件的可测试性和可维护性是至关重要的。

2. 程序设计语言的分类

目前,用于软件开发的程序设计语言已经有数百种之多,对这些程序设计语言的分类有不少争议。同一种语言可以归到不同的类中。从软件工程的角度,根据程序设计语言发展的历程,可以把它们大致分为4类。

b、从属于机器的语言(第一代语言)

它是由机器指令代码组成的语言。对于不同的机器就有相应的一套机器语言。用这种

语言编写的程序,都是二进制代码的形式,且所有的地址分配都是以绝对地址的形式处理。存储空间的安排,寄存器、变址的使用都由程序员自己计划。因此使用机器语言编写的程序很不直观,在计算机内的运行效率很高但编写出的机器语言程序其出错率也高。

b、汇编语言(第二代语言)

汇编语言比机器语言直观,它的每一条符号指令与相应的机器指令有对应关系,同时又增加了一些诸如宏、符号地址等功能。存储空间的安排可由机器解决。不同指令集的处理器系统就有自己相应的汇编语言。从软件工程的角度来看,汇编语言只是在高级语言无法满足设计要求时,或者不具备支持某种特定功能(例如特殊的输入/输出)的技术性能时,才被使用。

c、高级程序设计语言(第三代语言)

·传统的高级程序设计语言:如FORTRAN、COBOL、ALGOL、BASIC等。这些程序语言曾得到广泛应用。目前,它们都已有多种版本。有的语言得到较大的改进,甚至形成了可视的开发环境 ,具有图形设计工具 、结构化的事件驱动编程模式 、开放的环境 ,使用户可以既快又简便地编制出windows下的各种应用程序。

·通用的结构化程序设计语言:它具有很强的过程功能和数据结构功能,并提供结构化的逻辑构造。这一类语言的代表是PL/1,PASCAL,C和Ada。此外,COBOL78、Turbo BASIC等也应归入第三代程序语言范围。

·专用语言:专用语言是为特殊的应用而设计的语言。通常具有自己特殊的语法形式,面对特定的问题,输入结构及词汇表与该问题的相应范围密切相关。有代表性的专用语言有APL 、Lisp、PROLOG 、Smalltalk、C++、FORTH等。从软件工程的角度来看,专用语言支持了特殊的应用,将特定的设计要求翻译成可执行的代码。但是它们的可移植性和可维护性比较差。

d、第四代语言(4GL)

4GL 用不同的文法表示程序结构和数据结构,但是它是在更高一级抽象的层次上表示这些结构 ,它不再需要规定算法的细节 。4GL 兼有过程性和非过程性的两重特性。程序员规定条件和相应的动作这是过程性的部分,并且指出想要的结果,这是非过程部分 。然后由4GL语言系统运用它的专门领域的知识来填充过程细节。

Martin把第四代语言分为以下几种类型:

·查询语言:用户可利用查询语言对预先定义在数据库中的信息进行较复杂的操作。 ·程序生成器:只需很少的语句就能生成完整的第三代语言程序,它不必依赖预先定义的数据库作为它的着手点。

·其它4GL:如判定支持语言、原型语言、形式化规格说明语言等。

3. 程序设计语言的选择

为某个特定开发项目选择程序设计语言时,既要从技术角度、工程角度 、心理学角度评价和比较各种语言的适用程度 ,又必须考虑现实可能性。有时需要作出某种合理的折衷。

在选择与评价语言时,首先要从问题入手,确定它的要求是什么?这些要求的相对重要性如何?再根据这些要求和相对重要性来衡量能采用的语言。

通常考虑的因素有:①项目的应用范围;②算法和计算复杂性;③软件执行的环境;④性能上的考虑与实现的条件;⑤数据结构的复杂性;⑥软件开发人员的知识水平和心理因素等。其中,项目的应用范围是最关键的因素。

针对计算机的 4个主要应用领域,为语言做一个粗略的分类。例如,在科学与工程计算领域内,C,C++ 语言得到了广泛的应用,但FORTRAN仍然是应用最广泛的语言。在商业数据处理领域中,通常采用COBOL,RPG语言编写程序,当然也可选用SQL 语言或其它专用语言。在系统程序设计和实时应用领域中,汇编语言或一些新的派生语言,如BLISS,PL/S,Ada,C++等得到了广泛的应用。在人工智能领域以及问题求解,组合应用领域,主要采用LISP和PROLOG语言。

新的更强有力的语言,虽然对于应用有很强的吸引力,但是因为已有的语言已经积累了大量的久经使用的程序,具有完整的资料、支撑软件和软件开发工具,程序设计人员比较熟悉,而且有过类似项目的开发经验和成功的先例,由于心理因素,人们往往宁愿选用原有的语种。所以应当彻底地分析,评价,介绍新的语言,以便从原有语言过渡到新的语言。

1.5.2 编码规范与编程风格

编写代码时,保持良好的编码习惯是十分重要的,这样写出的代码既能被编译器正确地识别,又能增强程序的可读性和可维护性。一般来说,不同的编程语言的编码规则是不相同的,下面介绍编写Visual C# 2005程序时应当遵循的一些规则。

1. 分号与分行

C# 语句使用“;”结束,即编译器遇到“;”便认为该条语句结束,因此编写代码时可以在一行中编写多条C# 语句。然而并不提倡这么做,一行中只编写一条语句可以让代码的结构更清晰,从而提高其可读性和可维护性。

当一条语句太长,不适合单行显示时,可以分成多行来编写。但分行时不能随意,应当遵循下面的原则:

(1)在一个逗号后换行。

(2)在一个操作符后换行。

(3)在表达式的高层次处换行。

(4)新行与前一行在同一层次,并与表达式的起始对齐。

下面看两个分行例子:

//************************************************************************************* boolYear = (year % 4 == 0 && year % 100 != 0)

|| (year % 400 == 0);

num = a * b / (c – d + e)

+ 4 * f;

//************************************************************************************* 上面的分行方法是不错的,在表达式的“)”号后面开始分行,显得结构清晰,容易读懂,是值得提倡的做法。

再看下面的分行例子:

//************************************************************************************* boolYear = (year % 4 == 0 && year % 100 != 0)|| (year

% 400 == 0);

num = a * b / (c - d

+ e) + 4 * f;

//************************************************************************************* 显然这样的分行是难于被人接受的,它违背了分行的高层次规则,在编程的过程中,应当避免这样做。

2. 注释

注释是编写程序代码时不可缺少的,经验表明:成熟的源代码中包含三分之一到二分之一的注释。这样,可以提高程序的可读性,方便对源代码的阅读和修改。因此,在程序适当的位置加上注释语句是一种良好的编码习惯。

(1)行注释

C# 中的行注释(即注释内容写在同一行)通常用来注释掉一行代码,也可以用它注释掉代码块。当然也可以作为代码的单行解释且单独成一行时,书写行注释时必须要将其缩进到与代码对齐。

行注释的格式如下:

//

例如:

// 下面代码定义一个整型变量maxNum

int maxNum;

或者:

int maxNum; // 定义一个整型变量maxNum

(2)块注释

C# 中的块注释(即多行注释,注释内容写在多个代码行)通常用来注释掉一个代码块,当然也可以作为代码的解释。编码时,通常要尽量避免使用块注释。实际上块注释是很少使用到的,一般仅在需要注释掉一段代码或注释内容很多时使用。

Visual C# 2005中的块注释格式如下:

/*

„„

*/

例如下面是自定义方法maxNum方法的注释:

/************************************************************************************* 方法名:maxNum

方法的参数:两个整型参数

方法功能:求两个数中的最大者

方法返回值的数据类型:整型数据

创建日期:2007-8-25

*************************************************************************************/

3. 空格、空行与括号

在代码中合理地加入空格、空行以及人为添加一些括号是一位优秀的程序员所必须做到的,这样可以很大程度上提高编程的效率以及程序的可读性。由于Visual C# 2005 编译器对输入的代码有自动对齐、退格的功能,所以对于空格的使用实际上已经没有讨论的必要,下面看看空行和括号的使用。

(1)空行

在成熟的源代码中,存在着很多的空行,这些空行很好地显示了代码块的结构。一般来说,在下列元素之间,应当插入空行:

a、构造函数。

b、属性。

c、方法。

d、方法内的逻辑块。

下面看一个关于空行使用的示例(代码中包含了方法内的几个逻辑块):

//************************************************************************************* int x;

int y;

int result;

x = 2;

y = 3;

result = x + y;

Console.WriteLine(result);

//************************************************************************************* 上面的代码中,使用了两个空行把代码分成3个部分(即3个逻辑块),这样的代码看起来简单明了,结构清晰。第1部分:声明变量;第2部分:给变量赋值;第3部分:计算并输出结果。

当然,在如此简单的代码中不使用空行是完全可以的,然而在大型的程序中合理地使用空行是必不可少的。

(2)括号

当代码或者表达式很长时,聪明的程序员会在编写的代码中人为地加入一些小括号,如下面的代码:

//************************************************************************************* int year;

bool boolYear;

bool boolYear = (year % 4 ==0 && year % 100 != 0) || (year % 400 == 0);

//************************************************************************************* 参照C# 运算符的优先级可知,表示闰年的表达式:

(year % 4 ==0 && year % 100 != 0) || (year % 400 == 0)

不加括号完全可以正确计算,然而去掉括号后该表达式看起来结构不如现在清晰。因此,在比较长的表达式中人为地加入一些必要的括号可增强程序的可读性。

1.5.3 命名规则

编写代码时,使用良好的风格对标识符命名是一个优秀的程序员必须养成的习惯。变量、函数、结构、枚举、类、属性、事件、方法等的命名都遵循这些规则,这样可以大大地提高程序的可读性,并可方便开发团队中各人员之间的合作。

1. 标识符的书写风格

标识符的书写通常有以下几种风格:

(1)Pascal风格。

大写每一个单词的第一个字符,如WindowsApplication1、MaxNum。

(2)Camel风格。

除了第一个单词,大写其他单词的第一个字符,如maxNum、userName。

(3)全部大写。

如果标识符包含的字符数较少,可以采用全部大写的方法,一般用于常量的命名,如PI、MAX、MIN。

2. 类、结构、枚举和命名空间的命名

类(class)、结构(struct)、枚举(enum)和命名空间(namespace)的命名一般采用Pascal风格,由名词或名词短语构成,且不要使用任何前缀。

例如:Form1、StudentInformation、WeekDays、TxtWelcome等。

3. 参数、变量的命名

参数、变量的命名采用Camel风格,使用描述性的名字,使它能够充分地表示出参数或变量的含义。

例如:maxNumber、userName等。

如果变量仅用来在循环中计数,即作为循环变量,则优先使用i、j、k、l、m、n等。

4. 方法的命名

方法的命名采用Pascal风格,使用动词或动词短语命名。例如:Click、DoubleClick、FormClosing等。

5. 属性的命名

属性的命名采用Pascal风格,使用名词或名词短语命名。例如:BackColor、ReadOnly、ControlBox等。

6. 控件的命名

控件的命名采用Camel风格(Form除外),即首字母小写,而每个后面连接的单词的首字母都大写,命名的形式为:控件名的简写+英文描述(英文描述首字母大写)。

例如:btnOk、lblShow、txtInputNum等。

Visual C# 2008常用控件的简写及应用举例如表1-1所示。

表1-1 常用控件的简写及应用举例

1.6 软件测试

1.6.1 软件测试的内容

不论是对软件的模块还是整个系统,总有共同的内容要测试,如正确性测试,容错性测试,性能与效率测试,易用性测试,文档测试等。

1. 正确性测试

正确性测试又称功能测试,它检查软件的功能是否符合规格说明。由于正确性是软件最重要的质量因素,所以其测试也最重要。

基本的方法是构造一些合理输入,检查是否得到期望的输出。这是一种枚举方法。倘若枚举空间是无限的,那可惨了,还不如回家种土豆有盼头。测试人员一定要设法减少枚举的次数,否则没好日子过。关键在于寻找等价区间,因为在等价区间中,只需用任意值测试一次即可。等价区间的概念可表述如下:

记(A, B)是命题f(x) 的一个等价区间,在(A, B)中任意取x1进行测试。

如果f (x1) 错误,那么f (x) 在整个(A, B)区间都将出错。

如果f (x1) 正确,那么f (x) 在整个(A, B)区间都将正确。

还有一种有效的测试方法是边界值测试。即采用定义域或者等价区间的边界值进行测试。因为程序员容易疏忽边界情况,程序也“喜欢”在边界值处出错。

例如测试 的一段程序。凭直觉等价区间应是(0, 1)和(1, +∞)。可取x=0.5以及x=2.0进行等价测试。再取 x=0以及x=1进行边界值测试。

有一些复杂的程序,我们难以凭直觉与经验找到等价区间和边界值,这时枚举测试就相当有难度。

2. 容错性测试项目经理圈子

容错性测试是检查软件在异常条件下的行为。容错性好的软件能确保系统不发生无法意料的事故。

比较温柔的容错性测试通常构造一些不合理的输入来引诱软件出错,例如:

(1)输入错误的数据类型,如“猴”年“马”月。

(2)输入定义域之外的数值,上海人常说的“十三点”也算一种。

3. 性能与效率测试

性能与效率测试主要是测试软件的运行速度和对资源的利用率。有时人们关心测试的“绝对值”,如数据送输速率是每秒多少比特。有时人们关心测试的“相对值”,如某个软件比另一个软件快多少倍。

在获取测试的“绝对值”时,我们要充分考虑并记录运行环境对测试的影响。例如计算机主频,总线结构和外部设备都可能影响软件的运行速度;若与多个计算机共享资源,

软件运行可能慢得像蜗牛爬行。

在获取测试的“相对值”时,我们要确保被测试的几个软件运行于完全一致的环境中。硬件环境的一致性比较容易做到(用同一台计算机即可)。但软件环境的因素较多,除了操作系统,程序设计语言和编译系统对软件的性能也会产生较大的影响。如果是比较几个算法的性能,就要求编程语言和编译器也完全一致。

性能与效率测试中很重要的一项是极限测试,因为很多软件系统会在极限测试中崩溃。例如,连续不停地向服务器发请求,测试服务器是否会陷入死锁状态不能自拔;给程序输入特别大的数据,看看它是否吃得消。

4. 易用性测试

易用性测试没有一个量化的指标,主观性较强。调查表明,当用户不理解软件中的某个特性时,大多数人首先会向同事、朋友请教。要是再不起作用,就向产品支持部门打电话。只有30%的用户会查阅用户手册。

一般认为,如果用户不翻阅手册就能使用软件,那么表明这个软件具有较好的易用性。

5. 文档测试

文档测试主要检查文档的正确性、完备性和可理解性。好多人甚至不知道文档是软件的一个组成部分。

正确性是指不要把软件的功能和操作写错,也不允许文档内容前后矛盾。完备性是指文档不可以“虎头蛇尾”,更不许漏掉关键内容。有些学生在证明数学题时,喜欢用“显然”两字蒙混过关。文档中很多内容对开发者可能是“显然”的,但对用户而言不见得都是“显然”的。

1.6.2 软件测试的常用方法

软件测试的方法和技术是多种多样的。对于软件测试技术,可以从不同的角度加以分类:从是否需要执行被测软件的角度,可分为静态测试和动态测试。从测试是否针对系统的内部结构和具体实现算法的角度来看,可分为白盒测试和黑盒测试。

1. 黑盒测试

黑盒测试也称功能测试或数据驱动测试,它是在已知产品所应具有的功能,通过测试来检测每个功能是否都能正常使用,在测试时,把程序看作一个不能打开的黑盆子,在完全不考虑程序内部结构和内部特性的情况下,测试者在程序接口进行测试,它只检查程序功能是否按照需求规格说明书的规定正常使用,程序是否能适当地接收输入数锯而产生正确的输出信息,并且保持外部信息(如数据库或文件)的完整性。黑盒测试方法主要有等价类划分、边值分析、因—果图、错误推测等,主要用于软件确认测试。 “黑盒”法着眼于程序外部结构、不考虑内部逻辑结构、针对软件界面和软件功能进行测试。“黑盒”法是穷举输入测试,只有把所有可能的输入都作为测试情况使用,才能以这种方法查出程序中所有的错误。实际上测试情况有无穷多个,人们不仅要测试所有合法的输入,而且还要对

那些不合法但是可能的输入进行测试。

2. 白盒测试

白盒测试也称结构测试或逻辑驱动测试,它是知道产品内部工作过程,可通过测试来检测产品内部动作是否按照规格说明书的规定正常进行,按照程序内部的结构测试程序,检验程序中的每条通路是否都有能按预定要求正确工作,而不顾它的功能,白盒测试的主要方法有逻辑驱动、基路测试等,主要用于软件验证。

“白盒”法全面了解程序内部逻辑结构、对所有逻辑路径进行测试。“白盒”法是穷举路径测试。在使用这一方案时,测试者必须检查程序的内部结构,从检查程序的逻辑着手,得出测试数据。贯穿程序的独立路径数是天文数字。但即使每条路径都测试了仍然可能有错误。第一,穷举路径测试决不能查出程序违反了设计规范,即程序本身是个错误的程序。第二,穷举路径测试不可能查出程序中因遗漏路径而出错。第三,穷举路径测试可能发现不了一些与数据相关的错误。

1.6.3 软件测试的常用工具

随着软件测试的地位逐步提高,测试的重要性逐步显现,测试工具的应用已经成为了普遍的趋势。目前用于测试的工具已经比较多了,测试工具的应用可以提高测试的质量、测试的效率、减少测试过程中的重复劳动、实现测试自动化,这些测试工具一般可分为白盒测试工具、黑盒测试工具、性能测试工具,另外还有用于测试管理的工具,本文对常用的测试工具作一个分析比较。

1. 白盒测试工具

白盒测试工具一般是针对代码进行测试,测试中发现的缺陷可以定位到代码级,根据测试工具原理的不同,又可以分为静态测试工具和动态测试工具。静态测试工具直接对代码进行分析,不需要运行代码,也不需要对代码编译链接,生成可执行文件。静态测试工具一般是对代码进行语法扫描,找出不符合编码规范的地方,根据某种质量模型评价代码的质量,生成系统的调用关系图等;动态测试工具与静态测试工具不同,动态测试工具的一般采用“插桩”的方式,向代码生成的可执行文件中插入一些监测代码,用来统计程序运行时的数据。其与静态测试工具最大的不同就是动态测试工具要求被测系统实际运行。

(1) Jtest

是一个代码分析和动态类、组件测试工具,是一个集成的、易于使用和自动化的Java单元测试工具。它增强代码的稳定性,防止软件错误。

(2) Jcontract

Jcontract在系统级验证类/部件是否正确工作并被正确使用。Jcontract 是个独立工具,在功能上是Jtest 的补充。可以用Jcontract插装按DbC注解的Java代码。当您将类/部件组装成系统时,Jcontract 在运行时监视并报告错用和功能性问题。Jcontract 帮助每个开发人员有效地考核类/部件的系统级行为。

(3) C++ Test

C++Test可以帮助开发人员防止软件错误,保证代码的健全性、可靠性、可维护性和可移植性。 C++Test自动测试C和C++类、函数或组件,而无需编写单个测试实例、测试驱动程序或桩调用。

(4) CodeWizard

CodeWizard 代码静态分析工具,先进的C/C++源代码分析工具,使用超过500 个编码规范自动化地标明危险的,但是编译器不能检查到的代码结构。

(5) Insure++

Insure++是一个基于C/C++的自动化的内存错误、内存泄漏的精确检测工具。 Insure++能够可视化实时内存操作,准确检测出内存泄漏产生的根源。Insure++还能执行覆盖性分析,清楚地指示那些代码已经测试过。

(6) .test .TEST是专为.NET开发而推出的使用方便的自动化单元级测试与静态分析工具。使用超过2002条的工业标准代码规则对所写代码自动执行静态分析。这些规则立即应用.NET 工业专家深入、全面的编程知识到你的代码当中,迅速、彻底地防止错误的出现。自动测试代码构造与功能。 .TEST非常智能。他能提取刚完成的代码,对其进行读取,并提出如何对这些代码进行单元测试,不需要任何的人为干涉。所有由.TEST产生的单元测试都是可以用户自定义的。

(7) BoundsChecker

BoundsChecker Visual C++ Edition 是针对 Visual C++开发人员的首选的运行时的错误检测和调试工具。它通过驻留在 Visual C++ 开发环境内部的自动调试处理程序来加速应用程序的开发,缩短产品发布的时间。BoundsChecker 对于编程中的错误,大多数是 C++中特有的提供了清晰的详细的分析。它能够检测和诊断出在静态,堆栈内存中的错误以及内存和资源泄漏问题。在运行状态下,BoundsChecker 验证超过 8,700 APIs 和 OLE 方法,包括最新的 Windows APIs, ODBC, ActiveX,DirectX, COM 和 Internet APIs。

(8) TrueTime

代码运行缓慢是开发过程中一个重要问题。一个应用程序运行速度较慢,程序员不容易找到 到底是在哪里出现了问题,如果不能解决应用程序的性能将降低并极大的影响应用程序的质量,于是查找和修改性能瓶颈是调整整个代码性能的关键。如何快速的查找性能瓶颈呢?TrueTime 的出现就使这个问题变得很容易了。当我们在测试程序时,每完成一次应用话路,TrueTime 都能提供这次对话中函数的调用时间,提供详细的应用程序和组件性能的分析,并自动定位到运行缓慢的代码。这样就能帮助程序员尽快地调整应用程序的性能。TrueTime 支持C++, JAVA, Visual Basic语言环境。

(9) FailSafe FailSafe

是Visual Basic语言环境下的自动错误处理和恢复工具,FailSafe将插入额外的代码对你的程序进行插装,当程序执行时,FailSafe通过这些插装的代码捕获、记录错误信息。

(10) Jcheck Jcheck

是DevPartner Studio开发调试工具的一个组件,他使用事件调试技术,可以收集Java程序运行中准确的实时信息。我们在Java程序中经常要使用线程,而关于线程的常见错误有死锁、系统崩溃、同步问题等。JCheck 通过监视和分析当前内存中所有线程的运行状况,

找到出错的根源,并且可以定位到具体是程序中的哪个方法出错,错误位于程序的哪一行。

(11) TrueCoverage

TrueCoverage是一个代码覆盖率统计工具,在开发过程中,对一个应用程序通过手工测试,总会有一部分代码功能没有被检测到,或者说逐个检测每一个函数的调用是相当费时间的;未被检测的代码我们不能保证它的可靠性,以后程序的失败可能往往就是由这部分未检测的代码造成的。 现在我们可以用TrueCoverage 来帮助我们解决这些问题,我们在测试程序时,每完成一次应用话路,TrueCoverage 就能够列出在这次对话中所有函数被调用次数、所占比率等,并可以直接定位到源代码,当然我们也可以合并多个应用话路来进行检测。所以说TrueCoverage 能通过衡量和跟踪代码执行及代码稳定性,帮助开发团队节省时间和改善代码可靠性。TrueCoverage支持C++, JAVA,Visual Basic语言环境。

(12) SmartCheck

SmartCheck 是针对 Visual Basic的主要的自动错误检测和调试工具。它能够自动检测和诊断 VB运行时的错误,并将一些表达不清楚的错误信息转换为确切的错误描述。它的EventDebugging 特性为 Visual Basic开发小组和独立的开发人员解决最棘手的问题提供了简便的方法。它可以进行致命错误的分析、兼容性检查、定位到源代码。 不是 Visual Basic 中所有的问题都是运行时或系统的错误。许多的问题来自于未预期的程序流程的结果。如果没有 EventDebugging,将问题分离出来是相当困难,甚至不可能的。当简单的动作比如设置控件的属性发生时,会触发一些编程人员想象不到的事件的发生,从而使的错误检测和调试边的更加复杂。SmartCheck 显示使用时的属性,方法和事件以便于将这些事件驱动的问题隔离出来。SmartCheck EventDebugging 跟踪事件以简化错误的定位。举个例子,SmartCheck 在事件被设置或只读时将其方法和属性全部显示,连同由这些事件触发的形式。

(13) CodeReview

对于Visual Basic开发人员来说,CodeReview是最好的自动源代码分析工具,它对应用程序的组件、逻辑、Windows和Vb自身潜在的数百个问题进行严格地源代码检查。CodeReview分析的类型包括Y2K 问题,逻辑错误,应用程序性能和可用性问题,Windows API调用和标准一致性问题等。可以检测整个的VB工程或指定的模块,并能定制检错的种类;对检测的结果有详细的说明,提供帮助和推荐解决方案,而且能够直接的链接到源代码。CodeReview 系统还提供了两个子模块,一个是Metrics:通过对VB工程(vbp)的执行,计算出代码的长度、复杂度、理解度、语言的使用等级、出错的可能性等数据;另一个是Namer:它调用一个VB工程,自动并规则地对其中的对象重新命名,并备份原来没有规则命名的工程文件,使开发人员对程序能够有条理地管理。

2. 黑盒测试工具

黑盒测试工具适用于黑盒测试的场合,黑盒测试工具包括功能测试工具和性能测试工具。黑盒测试工具的一般原理是利用脚本的录制(Record)/回放(Playback),模拟用户的操作,然后将被测系统的输出记录下来同预先给定的标准结果比较。黑盒测试工具可以大大减轻黑盒测试的工作量,在迭代开发的过程中,能够很好地进行回归测试。

(1) WinRunner

Mercury Interactive 公司的WinRunner 是一种企业级的功能测试工具,用于检测应用程序是否能够达到预期的功能及正常运行。通过自动录制、检测和回放用户的应用操作,WinRunner能够有效地帮助测试人员对复杂的企业级应用的不同发布版进行测试,提高测试人员的工作效率和质量,确保跨平台的、复杂的企业级应用无故障发布及长期稳定运行。 企业级应用可能包括Web 应用系统,ERP 系统,CRM 系统等等。这些系统在发布之前,升级之后都要经过测试,确保所有功能都能正常运行,没有任何错误。如何有效地测试不断升级更新且不同环境的应用系统,是每个公司都会面临的问题。如果时间或资源有限,这个问题会更加棘手。人工测试的工作量太大,还要额外的时间来培训新的测试人员等等。为了确保那些复杂的企业级应用在不同环境下都能正常可靠地运行,你需要一个能简单操作的测试工具来自动完成应用程序的功能性测试,WinRunner能够做到这点。

(2) Astra Quicktest 4

(3) Robot Robot是IBM Rational公司的功能测试工具,通过Script 自动模拟输入输出。

(4) QARun QARun

Compuware 公司的软件功能测试工具,为客户/服务器、电子商务到企业资源_____计划提供重要的商务功能测试。通过将耗时的测试脚本开发和执行任务自动化,QARun 帮助测试人员和QA管理人员更有效地工作,以加速应用开发,它提供快速、有效地创建和执行测试脚本,验证测试并分析测试结果的功能。它能够通过加快运行周期来保持测试同步,提高测试投资回报和质量,该工具的功能有:创建测试和执行测试、测试验证、测试结果分析、可改进的数据函数、广泛的支持、集中式知识库、网站分析、智能化测试脚本、自动同步。

(5) SilkTest SilkTest International

Segue公司的标准的、面向多语种企业级应用的功能和回归测试工具。让用户能跨语种、跨平台和跨Web浏览器,高效率地进行各种类型的应用可靠性测试。

(6) e-Test e-Test 是Empirix公司的软件功能测试工具,功能很强大,由于不是采用Post URL的方式回放脚本,所以可以支持多内码的测试数据(当然要程序支持)。基本上可以应付大部分的Web Site。

(7) WAS Microsoft的Web Application Stress Tool(WAS,Web应用负载测试工具)是Microsoft的可以免费下载的软件性能测试工具。WAS要求Windows NT 4.0 SP4或者更高,或者Windows 2000。 为了对网站进行负载测试,WAS 可以通过一台或者多台客户机模拟大量用户的活动。WAS 支持身份验证、加密和Cookies,也能够模拟各种浏览器类型和Modem速度,它的功能和性能可以与数万美元的产品相媲美。WAS 只能用于B/S构架的软件性能测试。

(8) LoadRunner

LoadRunner是MI公司的预测系统行为和性能的负载测试工具,它通过以模拟上千万用户实施并发负载及实时性能监测的方式来确认和查找问题。LoadRunner 是一种适用于各种体系架构的自动负载测试工具,它能预测系统行为并优化系统性能。LoadRunner 的测试对象是整个企业的系统,它通过模拟实际用户的操作行为和实行实时性能监测,来帮助您更快的查找和发现问题,LoadRunner 能支持广范的协议和技术。

(9) Qaload

QALoad是Compuware公司开发的并发性能压力测试工具。软件针对各种测试目标提供了MS SQLServer、 Oracle、ODBC、WWW、NetLoad、Winsock 等不同的测试接口(Session),应用范围相当广泛。例如在测试基于C/S运行模式、客户端通过DBLib访问服务器端SQLServer数据库的系统时,QALoad 通过模拟客户端大数据量并发对服务器端进行查询、更新等操作,从而达到监控系统并 发性能和服务器端性能指标的目的。

(10) Webload

Webload 是RadView 公司推出的一个性能测试和分析工具,它让web 应用程序开发者自动执行压力测试;webload 通过模拟真实用户的操作,生成压力负载来测试web 的性能用户创建的是基于javascript的测试脚本,称为议程agenda,用它来模拟客户的行为,通过执行该脚本来衡量web应用程序在真实环境下的性能。 5webload 提供巡航控制器cruise control的功能,利用巡航控制器,可以预定义web 应用程序应该满足的性能指标,然后测试系统是否满足这些需求指标;cruise control 能够自动把负载加到web应用程序,并将在此负荷下能够访问程序的客户数量生成报告,webload能够在测试会话执行期间对监测的系统性能生成实时的报告,这些测试结果通过一个易读的图形界面显示出来,并可以导出到excel和其他文件里。

(11) Silkperformer

SilkPerformer 是业界最先进的企业级负载测试工具,和Loadrunner 是同种类型的测试工具。它能够模拟成千上万的用户在多协议和多种计算环境下工作。SilkPerformer 可以让你在使用前,就能够预测企业电子商务环境的行为—不受电子商务应用规模和复杂性影响。可视化的用户化、负载条件下可视化的内容校验、实时的性能监视和强大的管理报告可以帮助您迅速将问题隔离,这样,通过最小化测试周期、优化性能以及确保可伸缩性,加快了投入市场的时间,并保证了系统的可靠性。

(12) OpenSTA

OpenSTA 是专用于B/S 构架的、免费的性能测试工具。它的优点除了免费、源代码开放的优点外,还能对录制的测试脚本进行,按指定的语法进行编辑。测试工程师在录制完测试脚本后,只需要了解该脚本语言的特定语法知识,就可以对测试脚本进行编辑,以便于再次执行性能测试时获得所需要的参数,之后进行特定的性能指标分析。OpenSTA以最简单的方式让大家对性能测试的原理有较深的了解,其较为丰富的图形化测试结果大大提高了测试报告的可阅读性。

3. 其他测试工具

除了上述的测试工具外,还有一些专用的测试工具,例如,针对数据库测试的TestBytes,对应用性能进行优化的EcoScope等工具。

4. 测试管理工具

测试管理工具用于对测试进行管理。一般而言,测试管理工具对测试计划、测试用例、测试实施进行管理,并且,测试管理工具还包括对缺陷的跟踪管理。

第1章 软件开发过程概述

1.1 软件开发过程概述

1.1.1 软件的概念

软件(Software)简单的说就是那些在计算机中能看的着,但摸不着的东西,概念性的说软件也称为“软设备”,广义地说软件是指系统中的程序以及开发、使用程序所需要的所有文档的集合软件分为系统软件和应用软件。

软件并不只是包括可以在计算机上运行的程序,与这些程序相关的文件一般也被认为是软件的一部分。

软件被应用于世界的各个领域,对人们的生活和工作都产生了深远的影响。

1. 系统软件

系统软件是负责管理计算机系统中各种独立的硬件,使得它们可以协调工作。系统软件使得计算机使用者和其他软件将计算机当作一个整体而不需要顾及到底层每个硬件是如何工作的。

一般来讲,系统软件包括操作系统和一系列基本的工具(比如编译器,数据库管理,存储器格式化,文件系统管理,用户身份验证,驱动管理,网络连接等方面的工具)。

2. 应用软件

应用软件是为了某种特定的用途而被开发的软件。它可以是一个特定的程序,比如一个图像浏览器。也可以是一组功能联系紧密,可以互相协作的程序的集合,比如微软的Office软件。也可以是一个由众多独立程序组成的庞大的软件系统,比如数据库管理系统。 较常见的有:文字处理软件 如WPS、Word等;信息管理软件;辅助设计软件 如AutoCAD ;实时控制软件;教育与娱乐软件。

1.1.2 编程与软件开发

软件开发的内容是:需求、设计、编程和测试。

(1)需求:不仅仅是用户需求,应该是开发中遇到的所有的需求。比如,你首先要知道做这个项目是为了解决什么问题;测试案例中应该输入什么数据......为了清楚地知道这些需求,你经常要和客户、项目经理等交流。

(2)设计:编码前,肯定有个计划告诉你要做什么,结构是怎样等等。你一定要按照这个来做,否则可能会一团糟。

(3)编程:如果在项目截止日,你的程序不能跑起来或达不到客户的要求,你就拿不到钱。

(4)测试:目的是让你知道,什么时候算是完成了。如果你聪明,你就应该先写测试,这样可以及时知道你是否真地完成了。否则,你经常会不知道,到底有哪些功能是真正完成了,离预期目标还差多远。

软件开发中,客户和开发人员都有自己的基本权利和义务。

(1)客户:

定义每个用户需求的商业优先级;

制订总体计划,包括用多少投资、经过多长时间、达到什么目的;

在项目开发过程中的每个工作周,都能让投资获得最大的收益;

通过重复运行你所指定的功能测试,准确地掌握项目进展情况;

能随时改变需求、功能或优先级,同时避免昂贵的再投资;能够根据各种变化及时调整项目计划;

能够随时取消项目;项目取消时,以前的开发工作不是一堆垃圾,已开发完的功能是合乎要求的,正在进行或未完成的的工作则应该是不难接手的。

(2)开发人员:

知道要做什么,以及要优先做什么;

工作有效率;

有问题或困难时,能得到客户、同事、上级的回答或帮助;

对工作做评估,并根据周围情况的变化及时重新评估;

积极承担工作,而不是消极接受分配。

1.1.3 软件开发过程

软件开发过程一般分为以下6个阶段:

1. 计划

对所要解决的问题进行总体定义,包括了解用户的要求及现实环境,从技术、经济和社会因素等3个方面研究并论证本软件项目的可行性,编写可行性研究报告,探讨解决问题的方案,并对可供使用的资源(如计算机硬件、系统软件、人力等)成本,可取得的效益和开发进度作出估计。制订完成开发任务的实施计划。

2. 分析

软件需求分析就是回答做什么的问题。它是一个对用户的需求进行去粗取精、去伪存真、正确理解,然后把它用软件工程开发语言(形式功能规约,即需求规格说明书)表达出来的过程。本阶段的基本任务是和用户一起确定要解决的问题,建立软件的逻辑模型,编写需求规格说明书文档并最终得到用户的认可。需求分析的主要方法有结构化分析方法、数据流程图和数据字典等方法。本阶段的工作是根据需求说明书的要求,设计建立相应的软件系统的体系结构,并将整个系统分解成若干个子系统或模块,定义子系统或模块间的接口关系,对各子系统进行具体设计定义,编写软件概要设计和详细设计说明书,数据库或数据结构设计说明书,组装测试计划。

3. 设计

软件设计可以分为概要设计和详细设计两个阶段。实际上软件设计的主要任务就是将软件分解成模块是指能实现某个功能的数据和程序说明、可执行程序的程序单元。可以是一个函数、过程、子程序、一段带有程序说明的独立的程序和数据,也可以是可组合、可分解和可更换的功能单元。模块,然后进行模块设计。概要设计就是结构设计,其主要目标就是给出软件的模块结构,用软件结构图表示。详细设计的首要任务就是设计模块的程序流程、算法和数据结构,次要任务就是设计数据库,常用方法还是结构化程序设计方法。

4. 编码

软件编码是指把软件设计转换成计算机可以接受的程序,即写成以某一程序设计语言表示的"源程序清单"。充分了解软件开发语言、工具的特性和编程风格,有助于开发工具的选择以及保证软件产品的开发质量。

当前软件开发中除在专用场合,已经很少使用二十世纪80年代的高级语言了,取而代之的是面向对象的开发语言。而且面向对象的开发语言和开发环境大都合为一体,大大提高了开发的速度。

5. 测试

软件测试的目的是以较小的代价发现尽可能多的错误。要实现这个目标的关键在于设计一套出色的测试用例(测试数据和预期的输出结果组成了测试用例)。如何才能设计出一套出色的测试用例,关键在于理解测试方法。不同的测试方法有不同的测试用例设计方法。两种常用的测试方法是白盒法测试对象是源程序,依据的是程序内部的的逻辑结构来发现软件的编程错误、结构错误和数据错误。结构错误包括逻辑、数据流、初始化等错误。用例设计的关键是以较少的用例覆盖尽可能多的内部程序逻辑结果。白盒法和黑盒法依据的是软件的功能或软件行为描述,发现软件的接口、功能和结构错误。其中接口错误包括内部/外部接口、资源管理、集成化以及系统错误。黑盒法用例设计的关键同样也是以较少的用例覆盖模块输出和输入接口。黑盒法。

6. 维护

维护是旨在已完成对软件的研制(分析、设计、编码和测试)工作并交付使用以后,对软件产品所进行的一些软件工程的活动。即根据软件运行的情况,对软件进行适当修改,以适应新的要求,以及纠正运行中发现的错误。编写软件问题报告、软件修改报告。

一个中等规模的软件,如果研制阶段需要一年至二年的时间,在它投入使用以后,其运行或工作时间可能持续五年至十年。那么它的维护阶段也是运行的这五年至十年期间。在这段时间,人们几乎需要着手解决研制阶段所遇到的各种问题,同时还要解决某些维护工作本身特有的问题。做好软件维护工作,不仅能排除障碍,使软件能正常工作,而且还可以使它扩展功能,提高性能,为用户带来明显的经济效益。然而遗憾的是,对软件维护工作的重视往往远不如对软件研制工作的重视。而事实上,和软件研制工作相比,软件维

护的工作量和成本都要大得多。

在实际开发过程中,软件开发并不是从第一步进行到最后一步,而是在任何阶段,在进入下一阶段前一般都有一步或几步的回溯。在测试过程中的问题可能要求修改设计,用户可能会提出一些需要来修改需求说明书等。

1.2 软件需求分析

1.2.1 需求获取

需求获取(requirement elicitation)是需求工程的主体。对于所建议的软件产品,获取需求是一个确定和理解不同用户类的需要和限制的过程。获取用户需求位于软件需求三个层次的中间一层。业务需求决定用户需求,它描述了用户利用系统需要完成的任务。从这些任务中,分析者能获得用于描述系统活动的特定的软件功能需求,这些系统活动有助于用户执行他们的任务。

需求获取是在问题及其最终解决方案之间架设桥梁的第一步。获取需求的一个必不可少的结果是对项目中描述的客户需求的普遍理解。一旦理解了需求,分析者、开发者和客户就能探索出描述这些需求的多种解决方案。参与需求获取者只有在他们理解了问题之后才能开始设计系统,否则,对需求定义的任何改进,设计上都必须大量的返工。把需求获取集中在用户任务上—而不是集中在用户接口上—有助于防止开发组由于草率处理设计问题而造成的失误。

需求获取、分析、编写需求规格说明和验证并不遵循线性的顺序,这些活动是相互隔开、增量和反复的。当你和客户合作时,你就将会问一些问题,并且取得他们所提供的信息(需求获取)。同时,你将处理这些信息以理解它们,并把它们分成不同的类别,还要把客户需求同可能的软件需求相联系(分析)。然后,你可以使客户信息结构化,并编写成文档和示意图(说明)。下一步,就可以让客户代表评审文档并纠正存在的错误(验证)。这四个过程贯穿着需求分析的整个阶段。 需求获取可能是软件开发中最困难、最关键、最易出错及最需要交流的方面。需求获取只有通过有效的客户—开发者的合作才能成功。分析者必须建立一个对问题进行彻底探讨的环境,而这些问题与产品有关。为了方便清晰地进行交流,就要列出重要的小组,而不是假想所有的参与者都持有相同的看法。对需求问题的全面考察需要一种技术,利用这种技术不但考虑了问题的功能需求方面,还可讨论项目的非功能需求。确定用户已经理解:对于某些功能的讨论并不意味着即将在产品中实现它。对于想到的需求必须集中处理并设定优先级,以避免一个不能带来任何益处的无限大的项目。

需求获取是一个需要高度合作的活动,而并不是客户所说的需求的简单誊本。作为一个分析者,你必须透过客户所提出的表面需求理解他们的真正需求。询问一个可扩充(open-ended)的问题有助于你更好地理解用户目前的业务过程并且知道新系统如何帮助或改进他们的工作。调查用户任务可能遇到的变更,或者用户需要使用系统其它可能的方式。想像你自己在学习用户的工作,你需要完成什么任务?你有什么问题?从这一角度来指导需求的开发和利用。

还有,探讨例外的情况:什么会妨碍用户顺利完成任务?对系统错误情况的反映,用户是如何想的?询问问题时,以“还有什么能” ,”当?时,将会发生什么”“你有没有曾经想过” ,“有没有人曾经”为开头。记下每一个需求的来源,这样向下跟踪直到发现特定的客户。

有些时候,尝试着问一些“愚蠢”的问题也有助于客户打开话匣子。如果你直接要求客户写出业务是如何实现的,客户十有八九无法完成。但是如果你尝试着问一些实际的问题,例如:“以我的理解,你们收到订单后,会...”。客户立刻就会指出你的错误,并滔滔不绝的开始谈论业务,而你,就在一边仔细的聆听吧。这一招就叫做“抛砖引玉”。

需求讨论会上必须要使用笔记本电脑,还要指定一个打字熟练的人把所有的讨论记录下来,记录的同时还要做一定的整理。如果不这样做,那么你结束会议的时候就会发现,所有的讨论只剩下一个模糊的印象,需求对你来说仍然是一件遥远的事情。在座谈讨论之后,记下所讨论的条目(item),并请参与讨论的用户评论并更正。及早并经常进行座谈讨论是需求获取成功的一个关键途径,因为只有提供需求的人才能确定是否真正获取需求。进行深入收集和分析以消除任何冲突或不一致性。

尽量把客户所持的假设解释清楚,特别是那些发生冲突的部分。从字里行间去理解以明确客户没有表达清楚但又想加入的特性或特征。Gause 和Weinberg(1989)提出使用“上下文无关问题”—这是一个高层次的问题,它可以获取业务问题和可能的解决方案的全部信息。客户对这些问题的回答诸如“产品要求怎样的精确度”或“你能帮我解释一下你为什么不同意某人的回答吗?”这些回答可以更直接地认识问题,而这是封闭(close-end)问题所不能做到的。

需求获取利用了所有可用的信息来源,这些信息描述了问题域或在软件解决方案中合理的特性。一个研究表明:比起不成功的项目,一个成功的项目在开发者和客户之间采用了更多的交流方式(Kiel and Carmel 1995)。与单个客户或潜在的用户组一起座谈,对于业务软件包或信息管理系统(MIS)的应用来说是一种传统的需求来源。直接聘请用户进行获取需求的过程是为项目获得支持和买入(buy-in)的一种方式。

尽量理解用户用于表述他们需求的思维过程。充分研究用户执行任务时作出决策的过程,并提取出潜在的逻辑关系。流程图和决策树是描述这些逻辑决策途径的好方法。

在需求获取的过程中,你可能会发现对项目范围的定义存在误差,不是太大就是太小。如果范围太大,你将要收集比真正需要更多的需求,以传递足够的业务和客户的值,此时获取过程将会拖延。如果项目范围太小,那么客户将会提出很重要的但又在当前产品范围之外的需求。当前的范围太小,以致不能提供一个令人满意的产品。需求的获取将导致修改项目的范围和任务,但作出这样具有深远影响的改变,一定要小心谨慎。

正如经常所说的,需求主要是关于系统做什么,而解决方案如何实现是属于设计的范围。这样说虽然很简洁,但似乎过于简单化。需求的获取应该把重点放在“做什么”上,但在分析和设计之间还是存在一定的距离。你可以使用假设“怎么做”来分类并改善你对用户需求的理解。在需求的获取过程中,分析模型、屏幕图形和原型可以使概念表达得更加清楚,然后提供一个寻找错误和遗漏的办法。把你在需求开发阶段所形成的模型和屏幕效果看成是方便高效交流的概念性建议,而不应该看成是对设计者选择的一种限制。

需求获取讨论会中如果参与者过多,就会减慢进度。人数大致控制在5到7人是最好的。这些人包括客户、系统设计者、开发者和可视化设计者等主要工程角色。相反地,从极少的代表那里收集信息或者只听到呼声最高、最有舆论影响的用户的声音,也会造成问题。这将导致忽视特定用户类的重要的需求,或者其需求不能代表绝大多数用户的需要。最好的权衡在于选择一些授权为他们的用户类发言的产品代表者,他们也被同组用户类的其它代表所支持。

1.2.2 需求分析

1. 定义

所谓“需求分析”,是指对要解决的问题进行详细的分析,弄清楚问题的要求,包括需要输入什么数据,要得到什么结果,最后应输出什么。可以说,“需求分析”就是确定要计算机“做什么”。

在软件工程中,需求分析指的是在建立一个新的或改变一个现存的电脑系统时描写新系统的目的、范围、定义和功能时所要做的所有的工作。需求分析是软件工程中的一个关键过程。在这个过程中,系统分析员和软件工程师确定顾客的需要。只有在确定了这些需要后他们才能够分析和寻求新系统的解决方法。

在软件工程的历史中,很长时间里人们一直认为需求分析是整个软件工程中最简单的一个步骤,但在过去十年中越来越多的人认识到它是整个过程中最关键的一个过程。假如在需求分析时分析者们未能正确地认识到顾客的需要的话,那么最后的软件实际上不可能达到顾客的需要,或者软件无法在规定的时间里完工。

2. 特点

需求分析是一项重要的工作,也是最困难的工作。该阶段工作有以下特点:

(1)用户与开发人员很难进行交流

在软件生存周期中,其它四个阶段都是面向软件技术问题,只有本阶段是面向用户的。需求分析是对用户的业务活动进行分析,明确在用户的业务环境中软件系统应该"做什么"。但是在开始时,开发人员和用户双方都不能准确地提出系统要"做什么?"。因为软件开发人员不是用户问题领域的专家,不熟悉用户的业务活动和业务环境,又不可能在短期内搞清楚;而用户不熟悉计算机应用的有关问题。由于双方互相不了解对方的工作,又缺乏共同语言,所以在交流时存在着隔阂。

(2)用户的需求是动态变化的

对于一个大型而复杂的软件系统,用户很难精确完整地提出它的功能和性能要求。一开始只能提出一个大概、模糊的功能,只有经过长时间的反复认识才逐步明确。有时进入到设计、编程阶段才能明确,更有甚者,到开发后期还在提新的要求。这无疑给软件开发带来困难。

(3)系统变更的代价呈非线性增长

需求分析是软件开发的基础。假定在该阶段发现一个错误,解决它需要用一小时的时

间,到设计、编程、测试和维护阶段解决,则要花2.5、5、25、100倍的时间。

因此,对于大型复杂系统而言,首先要进行可行性研究。开发人员对用户的要求及现实环境进行调查、了解,从技术、经济和社会因素三个方面进行研究并论证该软件项目的可行性,根据可行性研究的结果,决定项目的取舍。

3. 任务

(1)确定对系统的综合要求

虽然功能需求是对软件系统的一项基本需求,但却并不是唯一的需求,通常对软件系统有下述几方面的综合要求。

a、功能需求

b、性能需求

c、可靠性和可用性需求

d、出错处理需求

e、接口需求

f、约束

g、逆向需求

h、将来可能提出的要求

(2)分析系统的数据要求

任何一个软件本质上都是信息处理系统,系统必须处理的信息和系统应该产生的信息很大程度上决定了系统的面貌,对软件设计有深远的影响,因此,必须分析系统的数据要求,这是软件分析的一个重要任务。分析系统的数据要求通常采用建立数据模型的方法。

复杂的数据由许多基本的数据元素组成,数据结构表示数据元素之间的逻辑关系。 利用数据字典可以全面地定义数据,但是数据字典的缺点是不够直观。为了提高可理解性,常常利用图形化工具辅助描述数据结构。用用的图形工具有层次方框图和Warnier图。

(3)导出系统的逻辑模型

综合上述两项分析的结果可以导出系统的详细的逻辑模型,通常用数据流图、E-R图、状态转换图、数据字典和主要的处理算法描述这个逻辑模型。

(4)修正系统开发计划

根据在分析过程中获得的对系统的更深入的了解,可以比较准确地估计系统的成本和进度,修正以前定制的开发计划。

4. 方法

进行需求分析,应注意以下几点:

(1)首先调查组织机构情况

包括了解该组织的部门组成情况,各部门的职能等,为分析信息流程作准备。

(2)然后调查各部门的业务活动情况

包括了解各个部门输入和使用什么数据,如何加工处理这些数据,输出什么信息,输

出到什么部门,输出结果的格式是什么。

(3)协助用户明确对新系统的各种要求

包括信息要求、处理要求、完全性与完整性要求。

(4)确定新系统的边界

确定哪些功能由计算机完成或将来准备让计算机完成,哪些活动由人工完成。由计算机完成的功能就是新系统应该实现的功能。

需求分析常用的调查方法有:

(1)跟班作业

通过亲身参加业务工作来了解业务活动的情况。这种方法可以比较准确地理解用户的需求,但比较耗费时间。

(2)开调查会

通过与用户座谈来了解业务活动情况及用户需求。座谈时,参加者之间可以相互启发。

(3)请专人介绍。

(4)询问

对某些调查中的问题,可以找专人询问。

(5)设计调查表请用户填写

如果调查表设计得合理,这种方法是很有效,也很易于为用户接受的。

(6)查阅记录

即查阅与原系统有关的数据记录,包括原始单据、账簿、报表等。

通过调查了解了用户需求后,还需要进一步分析和表达用户的需求。

分析和表达用户需求的方法主要包括自顶向下和自底向上两类方法。

1.2.3 需求文档的编写

需求的写作形式一般分为两种,面向对象和面向过程。对于不同的受众和应用,采取不同的形式。

面向过程的形式:

主要的思想是IPO的原则,也就是“输出-处理-输出”,文档格式:

(1)首先是对于整体系统的简略介绍:目的,确定文档描述的对象和大体内容

(2)系统上下文,介绍系统和其他系统之间的关系,边界如何划分

(3)系统的需求分解,介绍完成整体系统需要分解的大框架的需求内容

(4)具体需求

对于具体需求很简单,按照如下形式完成:

a、简介

b、输入

c、处理

d、输出

(5)除了具体需求外,还包括其他相关方面的需求:

a、接口需求(与其他系统、子系统、模块的接口,用户接口等)所谓的界面原型,其

实是接口需求中的内容。由于界面原型通常都很重要,所以可以将这一部分拿出来放到具体需求中去。

界面原型不是仅仅一张图,还包括界面元素的描述、范围、错误提示信息等

b、性能需求

c、依赖:依赖的数据库、第三方软件等

d、需求优先级排序,用于衡量开发策略

(6)参考文档

面向对象的形式,整体文档架构是和上面描述的一致,区别只有两点。

(1)在系统的需求分解处,用用例的包图来描述、这个很简单,其实就是上面文字描述的图形化显示。

(2)主要区别是具体需求,通过用例的形式来描述,包括:

a、介绍

b、用户(actor)

c、前置条件

d、后置条件

e、触发条件

f、事件流

g、备选事件流

1.3 软件系统架构设计

软件架构(software architecture)是一系列相关的抽象模式,用于指导大型软件系统各个方面的设计。软件架构是一个系统的草图。软件架构描述的对象是直接构成系统的抽象组件。各个组件之间的连接则明确和相对细致地描述组件之间的通讯。在实现阶段,这些抽象组件被细化为实际的组件,比如具体某个类或者对象。在面向对象领域中,组件之间的连接通常用接口_(计算机科学)来实现。

软件体系结构是构建计算机软件实践的基础。与建筑师设定建筑项目的设计原则和目标,作为绘图员画图的基础一样,一个软件架构师或者系统架构师陈述软件构架以作为满足不同客户需求的实际系统设计方案的基础。

软件构架是一个容易理解的概念,多数工程师(尤其是经验不多的工程师)会从直觉上来认识它,但要给出精确的定义很困难。特别是,很难明确地区分设计和构架:构架属于设计的一方面,它集中于某些具体的特征。

在“软件构架简介”中,David GArlan 和 Mary Shaw 认为软件构架是有关如下问题的设计层次:“在计算的算法和数据结构之外,设计并确定系统整体结构成为了新的问题。结构问题包括总体组织结构和全局控制结构;通信、同步和数据访问的协议;设计元素的功能分配;物理分布;设计元素的组成;定标与性能;备选设计的选择。”

但构架不仅是结构;IEEE Working Group on Architecture 把其定义为“系统在其环境中的最高层概念”。构架还包括“符合”系统完整性、经济约束条件、审美需求和样式。它并不仅注重对内部的考虑,而且还在系统的用户环境和开发环境中对系统进行整体考虑,即

同时注重对外部的考虑。

在 Rational Unified ProcESs 中,软件系统的构架(在某一给定点)是指系统重要构件的组织或结构,这些重要构件通过接口与不断减小的构件与接口所组成的构件进行交互。

从和目的、主题、材料和结构的联系上来说,软件架构可以和建筑物的架构相比拟。一个软件架构师需要有广泛的软件理论知识和相应的经验来事实和管理软件产品的高级设计。软件架构师定义和设计软件的模块化,模块之间的交互,用户界面风格,对外接口方法,创新的设计特性,以及高层事物的对象操作、逻辑和流程。

1.3.1 软件架构的要素

一般而言,软件系统的架构(ArchitECture)有两个要素:

(1)它是一个软件系统从整体到部分的最高层次的划分。

一个系统通常是由元件组成的,而这些元件如何形成、相互之间如何发生作用,则是关于这个系统本身结构的重要信息。

详细地说,就是要包括架构元件(Architecture Component)、联结器(Connector)、任务流(TASk-flow)。所谓架构元素,也就是组成系统的核心"砖瓦",而联结器则描述这些元件之间通讯的路径、通讯的机制、通讯的预期结果,任务流则描述系统如何使用这些元件和联结器完成某一项需求。

(2)建造一个系统所作出的最高层次的、以后难以更改的,商业的和技术的决定。 在建造一个系统之前会有很多的重要决定需要事先作出,而一旦系统开始进行详细设计甚至建造,这些决定就很难更改甚至无法更改。显然,这样的决定必定是有关系统设计成败的最重要决定,必须经过非常慎重的研究和考察。

1.3.2 软件架构的目标

正如同软件本身有其要达到的目标一样,架构设计要达到的目标是什么呢?一般而言,软件架构设计要达到如下的目标:

(1)可靠性(Reliable)。软件系统对于用户的商业经营和管理来说极为重要,因此软件系统必须非常可靠。

(2)安全行(Secure)。软件系统所承担的交易的商业价值极高,系统的安全性非常重要。

(3)可扩展性(SCAlable)。软件必须能够在用户的使用率、用户的数目增加很快的情况下,保持合理的性能。只有这样,才能适应用户的市场扩展得可能性。

(4)可定制化(CuSTomizable)。同样的一套软件,可以根据客户群的不同和市场需求的变化进行调整。

(5)可扩展性(Extensible)。在新技术出现的时候,一个软件系统应当允许导入新技术,从而对现有系统进行功能和性能的扩展。

(6)可维护性(MAIntainable)。软件系统的维护包括两方面,一是排除现有的错误,二是将新的软件需求反映到现有系统中去。一个易于维护的系统可以有效地降低技术支持的花费。

(7)客户体验(Customer Experience)。软件系统必须易于使用。

(8)市场时机(Time to Market)。软件用户要面临同业竞争,软件提供商也要面临同业竞争。以最快的速度争夺市场先机非常重要。

1.3.3 软件架构的种类

根据我们关注的角度不同,可以将架构分成三种:

(1)逻辑架构、软件系统中元件之间的关系,比如用户界面,数据库,外部系统接口,商业逻辑元件,等等。

(2)物理架构、软件元件是怎样放到硬件上的。

(3)系统架构、系统的非功能性特征,如可扩展性、可靠性、强壮性、灵活性、性能等。

系统架构的设计要求架构师具备软件和硬件的功能和性能的过硬知识,这一工作无疑是架构设计工作中最为困难的工作。

此外,从每一个角度上看,都可以看到架构的两要素:元件划分和设计决定。

首先,一个软件系统中的元件首先是逻辑元件。这些逻辑元件如何放到硬件上,以及这些元件如何为整个系统的可扩展性、可靠性、强壮性、灵活性、性能等做出贡献,是非常重要的信息。

其次,进行软件设计需要做出的决定中,必然会包括逻辑结构、物理结构,以及它们如何影响到系统的所有非功能性特征。这些决定中会有很多是一旦作出,就很难更改的。

根据作者的经验,一个基于数据库的系统架构,有多少个数据表,就会有多少页的架构设计文档。比如一个中等的数据库应用系统通常含有一百个左右的数据表,这样的一个系统设计通常需要有一百页左右的架构设计文档。

1.3.4 软件构架的描述

为了讨论和分析软件构架,必须首先定义构架表示方式,即描述构架重要方面的方式。在 Rational Unified Process 中,软件构架文档记录有这种描述。

(1)构架视图

我们决定以多种构架视图来表示软件构架。每种构架视图针对于开发流程中的涉众(例如最终用户、设计人员、管理人员、系统工程师、维护人员等)所关注的特定方面。

构架视图显示了软件构架如何分解为构件,以及构件如何由连接器连接来产生有用的形式,由此记录主要的结构设计决策。这些设计决策必须基于需求以及功能、补充和其他方面的约束。而这些决策又会在较低层次上为需求和将来的设计决策施加进一步的约束。

(2)典型的构架视图集

构架由许多不同的构架视图来表示,这些视图本质上是以图形方式来摘要说明“在构架方面具有重要意义”的模型元素。在 Rational Unified Process 中,您将从一个典型的视图集开始,该视图集称为“4+1 视图模型”。它包括:

用例视图:包括用例和场景,这些用例和场景包括在构架方面具有重要意义的行为、类或技术风险。它是用例模型的子集。逻辑视图:包括最重要的设计类、从这些设计类到

包和子系统的组织形式,以及从这些包和子系统到层的组织形式。它还包括一些用例实现。它是设计模型的子集。实施视图:包括实施模型及其从模块到包和层的组织形式的概览。 同时还描述了将逻辑视图中的包和类向实施视图中的包和模块分配的情况。它是实施模型的子集。进程视图:包括所涉及任务(进程和线程)的描述,它们的交互和配置,以及将设计对象和类向任务的分配情况。只有在系统具有很高程度的并行时,才需要该视图。在 Rational Unified Process 中,它是设计模型的子集。配置视图:包括对最典型的平台配置的各种物理节点的描述以及将任务(来自进程视图)向物理节点分配的情况。只有在分布式系统中才需要该视图。它是部署模型的一个子集。构架视图记录在软件构架文档中。您可以构建其他视图来表达需要特别关注的不同方面:用户界面视图、安全视图、数据视图等等。对于简单系统,可以省略4+1视图模型中的一些视图。

1.3.5 软件架构师

软体设计师中有一些技术水平较高、经验较为丰富的人,他们需要承担软件系统的架构设计,也就是需要设计系统的元件如何划分、元件之间如何发生相互作用,以及系统中逻辑的、物理的、系统的重要决定的作出。

这样的人就是所谓的架构师(Architect)。在很多公司中,架构师不是一个专门的和正式的职务。通常在一个开发小组中,最有经验的程序员会负责一些架构方面的工作。在一个部门中,最有经验的项目经理会负责一些架构方面的工作。

但是,越来越多的公司体认到架构工作的重要性,并且在不同的组织层次上设置专门的架构师位置,由他们负责不同层次上的逻辑架构、物理架构、系统架构的设计、配置、维护等工作。

1.4 软件详细设计

软件详细设计的任务是,是为软件结构图中的每个模块确定所采用的算法和块内数据结构,用某种选定的表达工具给出清晰的描述,表达工具可以自由选择,但工具必须具有描述过程细节的能力,而且能够有利于程序员在编程时便于直接翻译成程序设计语言的源程序。

程序流程图、盒图、PAD图、HIPU图、PDL语言等等都是完成详细设计的工具,选择合适的工具并且正确地使用是十分重要的。面向数据结构设计方法(Jackson方法)是进行详细设计的形式化方法。

在软件详细设计阶段,将生成详细设计说明书,为每个模块确定采用的算法,确定每个模块使用的数据结构,确定每个模块的接口细节。在软件详细设计结束时,软件详细设计说明书通过复审的形成形成正式文档,作为下一个阶段的工作依据。

在概要设计阶段,已经确定了软件系统的总体结构,给出了软件系统中各个组成模块的功能和模块间的接口。作为软件设计的饿第二步,软件详细设计就是在软件概要设计的基础上,考虑如何实现定义的软件系统,直到对系统中的每个模块给出了足够详细的过程描述。在软件详细设计以后,程序员将仍旧根据详细设计的过程编写出实际的程序代码。因此,软件详细设计的结果基本上决定了最终的程序代码质量。

1.5 软件编码

1.5.1 软件开发语言及工具的选择

程序编码阶段的任务是将软件的详细设计转换成用程序设计语言实现的程序代码。因此,程序设计语言的性能和设计风格对于程序设计的效能和质量有着直接的关系。

1. 程序设计语言特性的比较

a、软件心理学的观点

因为从设计到编码的转换基本上是人的活动,因此语言的性能对程序员的心理影响,将对转换产生重大影响。程序员总是希望选择简单易学、使用方便的语言 ,以减少程序出错率,提高软件可靠性 。从心理学的观点,影响程序员心理的语言特性有如下6种: ·一致性:它表示一种语言所使用符号的兼容程度、允许随意规定限制、以及允许对语法或语义破例的程度。同是一个符号,给予多种用途,会引起许多难以察觉的错误。 ·二义性:虽然语言的编译程序总是以一种机械的规则来解释语句,但读者则可能用不同的方式来理解语句。例如,对于一个逻辑表达式 A≥“0”and A≤“9”,读者可能对这个逻辑表达式有不同的理解。

如果一个程序设计语言缺乏一致性和存在二义性,那么用这种语言编写出来的程序可读性就差,同时用这种语言编程也容易出错。

·简洁性(紧凑性):表示程序员为了用该语言编写程序,必须记忆的有关编码的信息量。可用语言支持块结构和结构化程序的能力、可使用的保留字和缩写字的种类、数据类型的种类和缺省说明、算术运算符和逻辑运算符的种类、系统内标准函数的数目等来衡量。 遗憾的是,语言的简洁性与程序的一致性常常是抵触的。

·局部性:指程序设计语言的联想(综合)特性。综合的特性使人们能够对事物从整体上进行记忆和识别 。在编码过程中 ,由语句组合成模块,由模块组装为程序体系结构,并在组装过程中实现模块的高内聚和低耦合,可使程序的局部性加强。

·线性:指程序的联想(顺序)特性。人们总是习惯于按逻辑线性序列理解程序。如果程序中线性序列和逻辑运算较多,会提高可读性。如果存在大量的分支和循环,就会破坏顺序状态,增加理解上的困难。直接实现结构化程序可提高程序的线性特性。

·传统:人们学习一种新的程序设计语言的能力受到传统的影响。具有 Pascal 基础的程序人员在学习 C 语言时不会感到困难,因为C保持了Pascal 所确立的传统语言特性。但是要求同一个人去学习APL或者LISP这样一些语言,传统就中断了。

b、软件工程的观点

从软件工程观点,程序设计语言的特性应着重考虑软件开发项目的需要。为此,对于程序编码,有如下一些工程上的性能要求:

·详细设计应能直接地容易地翻译成代码程序:把设计变为程序的难易程度,反映了程序设计语言与设计说明相接近的程度。所选择的程序设计语言是否具有结构化的构造 ,复杂的数据结构 ,专门的输入/输出能力,位运算和串处理的能力,直接影响到从详细设

计变换到代码程序的难易程度,以及特定软件开发项目的可实现性。

·源程序应具有可移植性:源程序的可移植性通常有三种解释:①对源程序不做修改或少做修改就可以实现处理机上的移植或编译程序上的移植;②即使程序的运行环境改变(例如,改用一个新版本的操作系统),源程序也不用改变;③源程序的许多模块可以不做修改或少做修改就能集成为功能性的各种软件包,以适应不同的需要。

为改善软件的可移植性,主要是使语言标准化。在开发软件时,应严格地遵守ISO或 ANSI、GB的标准,而不要去理会特定编译器提供的非标准特性。

·编译程序应具有较高的效率。

·尽可能应用代码生成的自动工具:有效的软件开发工具是缩短编码时间 ,改善源代码质量的关键因素 。使用带有各种有效的自动化工具的“软件开发环境”,支持从设计到源代码的翻译等各项工作,可以保证软件开发获得成功。

·可维护性:源程序的可读性,语言自身的文档化特性(涉及标识符的允许长度、标号命名、数据类型的丰富程度、控制结构的规定等)是影响到可维护性的重要因素。

c、程序设计语言的技术性能

在计划阶段,极少考虑程序语言的技术特性。但在选定资源时,要规划将要使用的支撑工具,就要确定一个具体的编译器或者确定一个程序设计环境。如果软件开发组的成员对所要使用的语言不熟悉,那么在成本及进度估算时必须把学习的工作量估算在内。

一旦确定了软件需求,待选用的程序语言的技术特性就显得非常重要了。如果需要复杂的数据结构,就要仔细衡量有哪些语言能提供这些复杂的数据结构。如果首要的是高性能及实时处理的能力,就可选用适合于实时应用的语言或效率高的语言。如果该应用有许多输出报告或繁杂的文件处理,最好是根据软件的要求,选定一种适合于该项工作的语言。

软件的设计质量 与程序设计语言 的技术性能无关(面向对象设计例外)。但在实现软件设计转化为程序代码时,转化的质量往往受语言性能的影响。因而也会影响到设计方法。

语言的技术性能对测试和维护的影响是多种多样的。例如,直接提供结构化构造的语言有利于减少循环带来的复杂性(即McCabe复杂性),使程序易读、易测试、易维护。另一方面,语言的某些技术特性却会妨碍测试。例如,在面向对象的语言程序中,由于实行了数据封装,使得监控这些数据的执行状态变得比较困难;由于建立了对象类的继承结构,使得高内聚、低耦合的要求受到破坏,增加了测试的困难。此外,只要语言程序的可读性强,而且可以减少程序的复杂性,这样的程序设计语言对于软件的维护就是有利的。

总之,通过仔细地分析和比较,选择一种功能强而又适用的语言,对成功地实现从软件设计到编码的转换,提高软件的质量,改善软件的可测试性和可维护性是至关重要的。

2. 程序设计语言的分类

目前,用于软件开发的程序设计语言已经有数百种之多,对这些程序设计语言的分类有不少争议。同一种语言可以归到不同的类中。从软件工程的角度,根据程序设计语言发展的历程,可以把它们大致分为4类。

b、从属于机器的语言(第一代语言)

它是由机器指令代码组成的语言。对于不同的机器就有相应的一套机器语言。用这种

语言编写的程序,都是二进制代码的形式,且所有的地址分配都是以绝对地址的形式处理。存储空间的安排,寄存器、变址的使用都由程序员自己计划。因此使用机器语言编写的程序很不直观,在计算机内的运行效率很高但编写出的机器语言程序其出错率也高。

b、汇编语言(第二代语言)

汇编语言比机器语言直观,它的每一条符号指令与相应的机器指令有对应关系,同时又增加了一些诸如宏、符号地址等功能。存储空间的安排可由机器解决。不同指令集的处理器系统就有自己相应的汇编语言。从软件工程的角度来看,汇编语言只是在高级语言无法满足设计要求时,或者不具备支持某种特定功能(例如特殊的输入/输出)的技术性能时,才被使用。

c、高级程序设计语言(第三代语言)

·传统的高级程序设计语言:如FORTRAN、COBOL、ALGOL、BASIC等。这些程序语言曾得到广泛应用。目前,它们都已有多种版本。有的语言得到较大的改进,甚至形成了可视的开发环境 ,具有图形设计工具 、结构化的事件驱动编程模式 、开放的环境 ,使用户可以既快又简便地编制出windows下的各种应用程序。

·通用的结构化程序设计语言:它具有很强的过程功能和数据结构功能,并提供结构化的逻辑构造。这一类语言的代表是PL/1,PASCAL,C和Ada。此外,COBOL78、Turbo BASIC等也应归入第三代程序语言范围。

·专用语言:专用语言是为特殊的应用而设计的语言。通常具有自己特殊的语法形式,面对特定的问题,输入结构及词汇表与该问题的相应范围密切相关。有代表性的专用语言有APL 、Lisp、PROLOG 、Smalltalk、C++、FORTH等。从软件工程的角度来看,专用语言支持了特殊的应用,将特定的设计要求翻译成可执行的代码。但是它们的可移植性和可维护性比较差。

d、第四代语言(4GL)

4GL 用不同的文法表示程序结构和数据结构,但是它是在更高一级抽象的层次上表示这些结构 ,它不再需要规定算法的细节 。4GL 兼有过程性和非过程性的两重特性。程序员规定条件和相应的动作这是过程性的部分,并且指出想要的结果,这是非过程部分 。然后由4GL语言系统运用它的专门领域的知识来填充过程细节。

Martin把第四代语言分为以下几种类型:

·查询语言:用户可利用查询语言对预先定义在数据库中的信息进行较复杂的操作。 ·程序生成器:只需很少的语句就能生成完整的第三代语言程序,它不必依赖预先定义的数据库作为它的着手点。

·其它4GL:如判定支持语言、原型语言、形式化规格说明语言等。

3. 程序设计语言的选择

为某个特定开发项目选择程序设计语言时,既要从技术角度、工程角度 、心理学角度评价和比较各种语言的适用程度 ,又必须考虑现实可能性。有时需要作出某种合理的折衷。

在选择与评价语言时,首先要从问题入手,确定它的要求是什么?这些要求的相对重要性如何?再根据这些要求和相对重要性来衡量能采用的语言。

通常考虑的因素有:①项目的应用范围;②算法和计算复杂性;③软件执行的环境;④性能上的考虑与实现的条件;⑤数据结构的复杂性;⑥软件开发人员的知识水平和心理因素等。其中,项目的应用范围是最关键的因素。

针对计算机的 4个主要应用领域,为语言做一个粗略的分类。例如,在科学与工程计算领域内,C,C++ 语言得到了广泛的应用,但FORTRAN仍然是应用最广泛的语言。在商业数据处理领域中,通常采用COBOL,RPG语言编写程序,当然也可选用SQL 语言或其它专用语言。在系统程序设计和实时应用领域中,汇编语言或一些新的派生语言,如BLISS,PL/S,Ada,C++等得到了广泛的应用。在人工智能领域以及问题求解,组合应用领域,主要采用LISP和PROLOG语言。

新的更强有力的语言,虽然对于应用有很强的吸引力,但是因为已有的语言已经积累了大量的久经使用的程序,具有完整的资料、支撑软件和软件开发工具,程序设计人员比较熟悉,而且有过类似项目的开发经验和成功的先例,由于心理因素,人们往往宁愿选用原有的语种。所以应当彻底地分析,评价,介绍新的语言,以便从原有语言过渡到新的语言。

1.5.2 编码规范与编程风格

编写代码时,保持良好的编码习惯是十分重要的,这样写出的代码既能被编译器正确地识别,又能增强程序的可读性和可维护性。一般来说,不同的编程语言的编码规则是不相同的,下面介绍编写Visual C# 2005程序时应当遵循的一些规则。

1. 分号与分行

C# 语句使用“;”结束,即编译器遇到“;”便认为该条语句结束,因此编写代码时可以在一行中编写多条C# 语句。然而并不提倡这么做,一行中只编写一条语句可以让代码的结构更清晰,从而提高其可读性和可维护性。

当一条语句太长,不适合单行显示时,可以分成多行来编写。但分行时不能随意,应当遵循下面的原则:

(1)在一个逗号后换行。

(2)在一个操作符后换行。

(3)在表达式的高层次处换行。

(4)新行与前一行在同一层次,并与表达式的起始对齐。

下面看两个分行例子:

//************************************************************************************* boolYear = (year % 4 == 0 && year % 100 != 0)

|| (year % 400 == 0);

num = a * b / (c – d + e)

+ 4 * f;

//************************************************************************************* 上面的分行方法是不错的,在表达式的“)”号后面开始分行,显得结构清晰,容易读懂,是值得提倡的做法。

再看下面的分行例子:

//************************************************************************************* boolYear = (year % 4 == 0 && year % 100 != 0)|| (year

% 400 == 0);

num = a * b / (c - d

+ e) + 4 * f;

//************************************************************************************* 显然这样的分行是难于被人接受的,它违背了分行的高层次规则,在编程的过程中,应当避免这样做。

2. 注释

注释是编写程序代码时不可缺少的,经验表明:成熟的源代码中包含三分之一到二分之一的注释。这样,可以提高程序的可读性,方便对源代码的阅读和修改。因此,在程序适当的位置加上注释语句是一种良好的编码习惯。

(1)行注释

C# 中的行注释(即注释内容写在同一行)通常用来注释掉一行代码,也可以用它注释掉代码块。当然也可以作为代码的单行解释且单独成一行时,书写行注释时必须要将其缩进到与代码对齐。

行注释的格式如下:

//

例如:

// 下面代码定义一个整型变量maxNum

int maxNum;

或者:

int maxNum; // 定义一个整型变量maxNum

(2)块注释

C# 中的块注释(即多行注释,注释内容写在多个代码行)通常用来注释掉一个代码块,当然也可以作为代码的解释。编码时,通常要尽量避免使用块注释。实际上块注释是很少使用到的,一般仅在需要注释掉一段代码或注释内容很多时使用。

Visual C# 2005中的块注释格式如下:

/*

„„

*/

例如下面是自定义方法maxNum方法的注释:

/************************************************************************************* 方法名:maxNum

方法的参数:两个整型参数

方法功能:求两个数中的最大者

方法返回值的数据类型:整型数据

创建日期:2007-8-25

*************************************************************************************/

3. 空格、空行与括号

在代码中合理地加入空格、空行以及人为添加一些括号是一位优秀的程序员所必须做到的,这样可以很大程度上提高编程的效率以及程序的可读性。由于Visual C# 2005 编译器对输入的代码有自动对齐、退格的功能,所以对于空格的使用实际上已经没有讨论的必要,下面看看空行和括号的使用。

(1)空行

在成熟的源代码中,存在着很多的空行,这些空行很好地显示了代码块的结构。一般来说,在下列元素之间,应当插入空行:

a、构造函数。

b、属性。

c、方法。

d、方法内的逻辑块。

下面看一个关于空行使用的示例(代码中包含了方法内的几个逻辑块):

//************************************************************************************* int x;

int y;

int result;

x = 2;

y = 3;

result = x + y;

Console.WriteLine(result);

//************************************************************************************* 上面的代码中,使用了两个空行把代码分成3个部分(即3个逻辑块),这样的代码看起来简单明了,结构清晰。第1部分:声明变量;第2部分:给变量赋值;第3部分:计算并输出结果。

当然,在如此简单的代码中不使用空行是完全可以的,然而在大型的程序中合理地使用空行是必不可少的。

(2)括号

当代码或者表达式很长时,聪明的程序员会在编写的代码中人为地加入一些小括号,如下面的代码:

//************************************************************************************* int year;

bool boolYear;

bool boolYear = (year % 4 ==0 && year % 100 != 0) || (year % 400 == 0);

//************************************************************************************* 参照C# 运算符的优先级可知,表示闰年的表达式:

(year % 4 ==0 && year % 100 != 0) || (year % 400 == 0)

不加括号完全可以正确计算,然而去掉括号后该表达式看起来结构不如现在清晰。因此,在比较长的表达式中人为地加入一些必要的括号可增强程序的可读性。

1.5.3 命名规则

编写代码时,使用良好的风格对标识符命名是一个优秀的程序员必须养成的习惯。变量、函数、结构、枚举、类、属性、事件、方法等的命名都遵循这些规则,这样可以大大地提高程序的可读性,并可方便开发团队中各人员之间的合作。

1. 标识符的书写风格

标识符的书写通常有以下几种风格:

(1)Pascal风格。

大写每一个单词的第一个字符,如WindowsApplication1、MaxNum。

(2)Camel风格。

除了第一个单词,大写其他单词的第一个字符,如maxNum、userName。

(3)全部大写。

如果标识符包含的字符数较少,可以采用全部大写的方法,一般用于常量的命名,如PI、MAX、MIN。

2. 类、结构、枚举和命名空间的命名

类(class)、结构(struct)、枚举(enum)和命名空间(namespace)的命名一般采用Pascal风格,由名词或名词短语构成,且不要使用任何前缀。

例如:Form1、StudentInformation、WeekDays、TxtWelcome等。

3. 参数、变量的命名

参数、变量的命名采用Camel风格,使用描述性的名字,使它能够充分地表示出参数或变量的含义。

例如:maxNumber、userName等。

如果变量仅用来在循环中计数,即作为循环变量,则优先使用i、j、k、l、m、n等。

4. 方法的命名

方法的命名采用Pascal风格,使用动词或动词短语命名。例如:Click、DoubleClick、FormClosing等。

5. 属性的命名

属性的命名采用Pascal风格,使用名词或名词短语命名。例如:BackColor、ReadOnly、ControlBox等。

6. 控件的命名

控件的命名采用Camel风格(Form除外),即首字母小写,而每个后面连接的单词的首字母都大写,命名的形式为:控件名的简写+英文描述(英文描述首字母大写)。

例如:btnOk、lblShow、txtInputNum等。

Visual C# 2008常用控件的简写及应用举例如表1-1所示。

表1-1 常用控件的简写及应用举例

1.6 软件测试

1.6.1 软件测试的内容

不论是对软件的模块还是整个系统,总有共同的内容要测试,如正确性测试,容错性测试,性能与效率测试,易用性测试,文档测试等。

1. 正确性测试

正确性测试又称功能测试,它检查软件的功能是否符合规格说明。由于正确性是软件最重要的质量因素,所以其测试也最重要。

基本的方法是构造一些合理输入,检查是否得到期望的输出。这是一种枚举方法。倘若枚举空间是无限的,那可惨了,还不如回家种土豆有盼头。测试人员一定要设法减少枚举的次数,否则没好日子过。关键在于寻找等价区间,因为在等价区间中,只需用任意值测试一次即可。等价区间的概念可表述如下:

记(A, B)是命题f(x) 的一个等价区间,在(A, B)中任意取x1进行测试。

如果f (x1) 错误,那么f (x) 在整个(A, B)区间都将出错。

如果f (x1) 正确,那么f (x) 在整个(A, B)区间都将正确。

还有一种有效的测试方法是边界值测试。即采用定义域或者等价区间的边界值进行测试。因为程序员容易疏忽边界情况,程序也“喜欢”在边界值处出错。

例如测试 的一段程序。凭直觉等价区间应是(0, 1)和(1, +∞)。可取x=0.5以及x=2.0进行等价测试。再取 x=0以及x=1进行边界值测试。

有一些复杂的程序,我们难以凭直觉与经验找到等价区间和边界值,这时枚举测试就相当有难度。

2. 容错性测试项目经理圈子

容错性测试是检查软件在异常条件下的行为。容错性好的软件能确保系统不发生无法意料的事故。

比较温柔的容错性测试通常构造一些不合理的输入来引诱软件出错,例如:

(1)输入错误的数据类型,如“猴”年“马”月。

(2)输入定义域之外的数值,上海人常说的“十三点”也算一种。

3. 性能与效率测试

性能与效率测试主要是测试软件的运行速度和对资源的利用率。有时人们关心测试的“绝对值”,如数据送输速率是每秒多少比特。有时人们关心测试的“相对值”,如某个软件比另一个软件快多少倍。

在获取测试的“绝对值”时,我们要充分考虑并记录运行环境对测试的影响。例如计算机主频,总线结构和外部设备都可能影响软件的运行速度;若与多个计算机共享资源,

软件运行可能慢得像蜗牛爬行。

在获取测试的“相对值”时,我们要确保被测试的几个软件运行于完全一致的环境中。硬件环境的一致性比较容易做到(用同一台计算机即可)。但软件环境的因素较多,除了操作系统,程序设计语言和编译系统对软件的性能也会产生较大的影响。如果是比较几个算法的性能,就要求编程语言和编译器也完全一致。

性能与效率测试中很重要的一项是极限测试,因为很多软件系统会在极限测试中崩溃。例如,连续不停地向服务器发请求,测试服务器是否会陷入死锁状态不能自拔;给程序输入特别大的数据,看看它是否吃得消。

4. 易用性测试

易用性测试没有一个量化的指标,主观性较强。调查表明,当用户不理解软件中的某个特性时,大多数人首先会向同事、朋友请教。要是再不起作用,就向产品支持部门打电话。只有30%的用户会查阅用户手册。

一般认为,如果用户不翻阅手册就能使用软件,那么表明这个软件具有较好的易用性。

5. 文档测试

文档测试主要检查文档的正确性、完备性和可理解性。好多人甚至不知道文档是软件的一个组成部分。

正确性是指不要把软件的功能和操作写错,也不允许文档内容前后矛盾。完备性是指文档不可以“虎头蛇尾”,更不许漏掉关键内容。有些学生在证明数学题时,喜欢用“显然”两字蒙混过关。文档中很多内容对开发者可能是“显然”的,但对用户而言不见得都是“显然”的。

1.6.2 软件测试的常用方法

软件测试的方法和技术是多种多样的。对于软件测试技术,可以从不同的角度加以分类:从是否需要执行被测软件的角度,可分为静态测试和动态测试。从测试是否针对系统的内部结构和具体实现算法的角度来看,可分为白盒测试和黑盒测试。

1. 黑盒测试

黑盒测试也称功能测试或数据驱动测试,它是在已知产品所应具有的功能,通过测试来检测每个功能是否都能正常使用,在测试时,把程序看作一个不能打开的黑盆子,在完全不考虑程序内部结构和内部特性的情况下,测试者在程序接口进行测试,它只检查程序功能是否按照需求规格说明书的规定正常使用,程序是否能适当地接收输入数锯而产生正确的输出信息,并且保持外部信息(如数据库或文件)的完整性。黑盒测试方法主要有等价类划分、边值分析、因—果图、错误推测等,主要用于软件确认测试。 “黑盒”法着眼于程序外部结构、不考虑内部逻辑结构、针对软件界面和软件功能进行测试。“黑盒”法是穷举输入测试,只有把所有可能的输入都作为测试情况使用,才能以这种方法查出程序中所有的错误。实际上测试情况有无穷多个,人们不仅要测试所有合法的输入,而且还要对

那些不合法但是可能的输入进行测试。

2. 白盒测试

白盒测试也称结构测试或逻辑驱动测试,它是知道产品内部工作过程,可通过测试来检测产品内部动作是否按照规格说明书的规定正常进行,按照程序内部的结构测试程序,检验程序中的每条通路是否都有能按预定要求正确工作,而不顾它的功能,白盒测试的主要方法有逻辑驱动、基路测试等,主要用于软件验证。

“白盒”法全面了解程序内部逻辑结构、对所有逻辑路径进行测试。“白盒”法是穷举路径测试。在使用这一方案时,测试者必须检查程序的内部结构,从检查程序的逻辑着手,得出测试数据。贯穿程序的独立路径数是天文数字。但即使每条路径都测试了仍然可能有错误。第一,穷举路径测试决不能查出程序违反了设计规范,即程序本身是个错误的程序。第二,穷举路径测试不可能查出程序中因遗漏路径而出错。第三,穷举路径测试可能发现不了一些与数据相关的错误。

1.6.3 软件测试的常用工具

随着软件测试的地位逐步提高,测试的重要性逐步显现,测试工具的应用已经成为了普遍的趋势。目前用于测试的工具已经比较多了,测试工具的应用可以提高测试的质量、测试的效率、减少测试过程中的重复劳动、实现测试自动化,这些测试工具一般可分为白盒测试工具、黑盒测试工具、性能测试工具,另外还有用于测试管理的工具,本文对常用的测试工具作一个分析比较。

1. 白盒测试工具

白盒测试工具一般是针对代码进行测试,测试中发现的缺陷可以定位到代码级,根据测试工具原理的不同,又可以分为静态测试工具和动态测试工具。静态测试工具直接对代码进行分析,不需要运行代码,也不需要对代码编译链接,生成可执行文件。静态测试工具一般是对代码进行语法扫描,找出不符合编码规范的地方,根据某种质量模型评价代码的质量,生成系统的调用关系图等;动态测试工具与静态测试工具不同,动态测试工具的一般采用“插桩”的方式,向代码生成的可执行文件中插入一些监测代码,用来统计程序运行时的数据。其与静态测试工具最大的不同就是动态测试工具要求被测系统实际运行。

(1) Jtest

是一个代码分析和动态类、组件测试工具,是一个集成的、易于使用和自动化的Java单元测试工具。它增强代码的稳定性,防止软件错误。

(2) Jcontract

Jcontract在系统级验证类/部件是否正确工作并被正确使用。Jcontract 是个独立工具,在功能上是Jtest 的补充。可以用Jcontract插装按DbC注解的Java代码。当您将类/部件组装成系统时,Jcontract 在运行时监视并报告错用和功能性问题。Jcontract 帮助每个开发人员有效地考核类/部件的系统级行为。

(3) C++ Test

C++Test可以帮助开发人员防止软件错误,保证代码的健全性、可靠性、可维护性和可移植性。 C++Test自动测试C和C++类、函数或组件,而无需编写单个测试实例、测试驱动程序或桩调用。

(4) CodeWizard

CodeWizard 代码静态分析工具,先进的C/C++源代码分析工具,使用超过500 个编码规范自动化地标明危险的,但是编译器不能检查到的代码结构。

(5) Insure++

Insure++是一个基于C/C++的自动化的内存错误、内存泄漏的精确检测工具。 Insure++能够可视化实时内存操作,准确检测出内存泄漏产生的根源。Insure++还能执行覆盖性分析,清楚地指示那些代码已经测试过。

(6) .test .TEST是专为.NET开发而推出的使用方便的自动化单元级测试与静态分析工具。使用超过2002条的工业标准代码规则对所写代码自动执行静态分析。这些规则立即应用.NET 工业专家深入、全面的编程知识到你的代码当中,迅速、彻底地防止错误的出现。自动测试代码构造与功能。 .TEST非常智能。他能提取刚完成的代码,对其进行读取,并提出如何对这些代码进行单元测试,不需要任何的人为干涉。所有由.TEST产生的单元测试都是可以用户自定义的。

(7) BoundsChecker

BoundsChecker Visual C++ Edition 是针对 Visual C++开发人员的首选的运行时的错误检测和调试工具。它通过驻留在 Visual C++ 开发环境内部的自动调试处理程序来加速应用程序的开发,缩短产品发布的时间。BoundsChecker 对于编程中的错误,大多数是 C++中特有的提供了清晰的详细的分析。它能够检测和诊断出在静态,堆栈内存中的错误以及内存和资源泄漏问题。在运行状态下,BoundsChecker 验证超过 8,700 APIs 和 OLE 方法,包括最新的 Windows APIs, ODBC, ActiveX,DirectX, COM 和 Internet APIs。

(8) TrueTime

代码运行缓慢是开发过程中一个重要问题。一个应用程序运行速度较慢,程序员不容易找到 到底是在哪里出现了问题,如果不能解决应用程序的性能将降低并极大的影响应用程序的质量,于是查找和修改性能瓶颈是调整整个代码性能的关键。如何快速的查找性能瓶颈呢?TrueTime 的出现就使这个问题变得很容易了。当我们在测试程序时,每完成一次应用话路,TrueTime 都能提供这次对话中函数的调用时间,提供详细的应用程序和组件性能的分析,并自动定位到运行缓慢的代码。这样就能帮助程序员尽快地调整应用程序的性能。TrueTime 支持C++, JAVA, Visual Basic语言环境。

(9) FailSafe FailSafe

是Visual Basic语言环境下的自动错误处理和恢复工具,FailSafe将插入额外的代码对你的程序进行插装,当程序执行时,FailSafe通过这些插装的代码捕获、记录错误信息。

(10) Jcheck Jcheck

是DevPartner Studio开发调试工具的一个组件,他使用事件调试技术,可以收集Java程序运行中准确的实时信息。我们在Java程序中经常要使用线程,而关于线程的常见错误有死锁、系统崩溃、同步问题等。JCheck 通过监视和分析当前内存中所有线程的运行状况,

找到出错的根源,并且可以定位到具体是程序中的哪个方法出错,错误位于程序的哪一行。

(11) TrueCoverage

TrueCoverage是一个代码覆盖率统计工具,在开发过程中,对一个应用程序通过手工测试,总会有一部分代码功能没有被检测到,或者说逐个检测每一个函数的调用是相当费时间的;未被检测的代码我们不能保证它的可靠性,以后程序的失败可能往往就是由这部分未检测的代码造成的。 现在我们可以用TrueCoverage 来帮助我们解决这些问题,我们在测试程序时,每完成一次应用话路,TrueCoverage 就能够列出在这次对话中所有函数被调用次数、所占比率等,并可以直接定位到源代码,当然我们也可以合并多个应用话路来进行检测。所以说TrueCoverage 能通过衡量和跟踪代码执行及代码稳定性,帮助开发团队节省时间和改善代码可靠性。TrueCoverage支持C++, JAVA,Visual Basic语言环境。

(12) SmartCheck

SmartCheck 是针对 Visual Basic的主要的自动错误检测和调试工具。它能够自动检测和诊断 VB运行时的错误,并将一些表达不清楚的错误信息转换为确切的错误描述。它的EventDebugging 特性为 Visual Basic开发小组和独立的开发人员解决最棘手的问题提供了简便的方法。它可以进行致命错误的分析、兼容性检查、定位到源代码。 不是 Visual Basic 中所有的问题都是运行时或系统的错误。许多的问题来自于未预期的程序流程的结果。如果没有 EventDebugging,将问题分离出来是相当困难,甚至不可能的。当简单的动作比如设置控件的属性发生时,会触发一些编程人员想象不到的事件的发生,从而使的错误检测和调试边的更加复杂。SmartCheck 显示使用时的属性,方法和事件以便于将这些事件驱动的问题隔离出来。SmartCheck EventDebugging 跟踪事件以简化错误的定位。举个例子,SmartCheck 在事件被设置或只读时将其方法和属性全部显示,连同由这些事件触发的形式。

(13) CodeReview

对于Visual Basic开发人员来说,CodeReview是最好的自动源代码分析工具,它对应用程序的组件、逻辑、Windows和Vb自身潜在的数百个问题进行严格地源代码检查。CodeReview分析的类型包括Y2K 问题,逻辑错误,应用程序性能和可用性问题,Windows API调用和标准一致性问题等。可以检测整个的VB工程或指定的模块,并能定制检错的种类;对检测的结果有详细的说明,提供帮助和推荐解决方案,而且能够直接的链接到源代码。CodeReview 系统还提供了两个子模块,一个是Metrics:通过对VB工程(vbp)的执行,计算出代码的长度、复杂度、理解度、语言的使用等级、出错的可能性等数据;另一个是Namer:它调用一个VB工程,自动并规则地对其中的对象重新命名,并备份原来没有规则命名的工程文件,使开发人员对程序能够有条理地管理。

2. 黑盒测试工具

黑盒测试工具适用于黑盒测试的场合,黑盒测试工具包括功能测试工具和性能测试工具。黑盒测试工具的一般原理是利用脚本的录制(Record)/回放(Playback),模拟用户的操作,然后将被测系统的输出记录下来同预先给定的标准结果比较。黑盒测试工具可以大大减轻黑盒测试的工作量,在迭代开发的过程中,能够很好地进行回归测试。

(1) WinRunner

Mercury Interactive 公司的WinRunner 是一种企业级的功能测试工具,用于检测应用程序是否能够达到预期的功能及正常运行。通过自动录制、检测和回放用户的应用操作,WinRunner能够有效地帮助测试人员对复杂的企业级应用的不同发布版进行测试,提高测试人员的工作效率和质量,确保跨平台的、复杂的企业级应用无故障发布及长期稳定运行。 企业级应用可能包括Web 应用系统,ERP 系统,CRM 系统等等。这些系统在发布之前,升级之后都要经过测试,确保所有功能都能正常运行,没有任何错误。如何有效地测试不断升级更新且不同环境的应用系统,是每个公司都会面临的问题。如果时间或资源有限,这个问题会更加棘手。人工测试的工作量太大,还要额外的时间来培训新的测试人员等等。为了确保那些复杂的企业级应用在不同环境下都能正常可靠地运行,你需要一个能简单操作的测试工具来自动完成应用程序的功能性测试,WinRunner能够做到这点。

(2) Astra Quicktest 4

(3) Robot Robot是IBM Rational公司的功能测试工具,通过Script 自动模拟输入输出。

(4) QARun QARun

Compuware 公司的软件功能测试工具,为客户/服务器、电子商务到企业资源_____计划提供重要的商务功能测试。通过将耗时的测试脚本开发和执行任务自动化,QARun 帮助测试人员和QA管理人员更有效地工作,以加速应用开发,它提供快速、有效地创建和执行测试脚本,验证测试并分析测试结果的功能。它能够通过加快运行周期来保持测试同步,提高测试投资回报和质量,该工具的功能有:创建测试和执行测试、测试验证、测试结果分析、可改进的数据函数、广泛的支持、集中式知识库、网站分析、智能化测试脚本、自动同步。

(5) SilkTest SilkTest International

Segue公司的标准的、面向多语种企业级应用的功能和回归测试工具。让用户能跨语种、跨平台和跨Web浏览器,高效率地进行各种类型的应用可靠性测试。

(6) e-Test e-Test 是Empirix公司的软件功能测试工具,功能很强大,由于不是采用Post URL的方式回放脚本,所以可以支持多内码的测试数据(当然要程序支持)。基本上可以应付大部分的Web Site。

(7) WAS Microsoft的Web Application Stress Tool(WAS,Web应用负载测试工具)是Microsoft的可以免费下载的软件性能测试工具。WAS要求Windows NT 4.0 SP4或者更高,或者Windows 2000。 为了对网站进行负载测试,WAS 可以通过一台或者多台客户机模拟大量用户的活动。WAS 支持身份验证、加密和Cookies,也能够模拟各种浏览器类型和Modem速度,它的功能和性能可以与数万美元的产品相媲美。WAS 只能用于B/S构架的软件性能测试。

(8) LoadRunner

LoadRunner是MI公司的预测系统行为和性能的负载测试工具,它通过以模拟上千万用户实施并发负载及实时性能监测的方式来确认和查找问题。LoadRunner 是一种适用于各种体系架构的自动负载测试工具,它能预测系统行为并优化系统性能。LoadRunner 的测试对象是整个企业的系统,它通过模拟实际用户的操作行为和实行实时性能监测,来帮助您更快的查找和发现问题,LoadRunner 能支持广范的协议和技术。

(9) Qaload

QALoad是Compuware公司开发的并发性能压力测试工具。软件针对各种测试目标提供了MS SQLServer、 Oracle、ODBC、WWW、NetLoad、Winsock 等不同的测试接口(Session),应用范围相当广泛。例如在测试基于C/S运行模式、客户端通过DBLib访问服务器端SQLServer数据库的系统时,QALoad 通过模拟客户端大数据量并发对服务器端进行查询、更新等操作,从而达到监控系统并 发性能和服务器端性能指标的目的。

(10) Webload

Webload 是RadView 公司推出的一个性能测试和分析工具,它让web 应用程序开发者自动执行压力测试;webload 通过模拟真实用户的操作,生成压力负载来测试web 的性能用户创建的是基于javascript的测试脚本,称为议程agenda,用它来模拟客户的行为,通过执行该脚本来衡量web应用程序在真实环境下的性能。 5webload 提供巡航控制器cruise control的功能,利用巡航控制器,可以预定义web 应用程序应该满足的性能指标,然后测试系统是否满足这些需求指标;cruise control 能够自动把负载加到web应用程序,并将在此负荷下能够访问程序的客户数量生成报告,webload能够在测试会话执行期间对监测的系统性能生成实时的报告,这些测试结果通过一个易读的图形界面显示出来,并可以导出到excel和其他文件里。

(11) Silkperformer

SilkPerformer 是业界最先进的企业级负载测试工具,和Loadrunner 是同种类型的测试工具。它能够模拟成千上万的用户在多协议和多种计算环境下工作。SilkPerformer 可以让你在使用前,就能够预测企业电子商务环境的行为—不受电子商务应用规模和复杂性影响。可视化的用户化、负载条件下可视化的内容校验、实时的性能监视和强大的管理报告可以帮助您迅速将问题隔离,这样,通过最小化测试周期、优化性能以及确保可伸缩性,加快了投入市场的时间,并保证了系统的可靠性。

(12) OpenSTA

OpenSTA 是专用于B/S 构架的、免费的性能测试工具。它的优点除了免费、源代码开放的优点外,还能对录制的测试脚本进行,按指定的语法进行编辑。测试工程师在录制完测试脚本后,只需要了解该脚本语言的特定语法知识,就可以对测试脚本进行编辑,以便于再次执行性能测试时获得所需要的参数,之后进行特定的性能指标分析。OpenSTA以最简单的方式让大家对性能测试的原理有较深的了解,其较为丰富的图形化测试结果大大提高了测试报告的可阅读性。

3. 其他测试工具

除了上述的测试工具外,还有一些专用的测试工具,例如,针对数据库测试的TestBytes,对应用性能进行优化的EcoScope等工具。

4. 测试管理工具

测试管理工具用于对测试进行管理。一般而言,测试管理工具对测试计划、测试用例、测试实施进行管理,并且,测试管理工具还包括对缺陷的跟踪管理。


相关文章

  • Z软件研制总结报告
  • 密级: 保存年限:XX 年 [文档控制号:VOL.X/Y(多卷情况)] [编制/修订日期:yyyy-mm-dd] 合同号: 用户单位: 签约机构: 编制单位: 编写: 校对: 审核: 批准: 系统名]的[CSCI 名]的 软件研制总结报告 ...查看


  • 操作手册模板
  • ×××软件系统操作手册 V1.0 小组名称:×××(如 iustc) 小组口号:×××(如 全心全意为人民服务) 指导教师:×××(如 张*** 老师) 文档撰写人:×××(如 李××) 文档撰写时间:×××(如 1970年1月1日) 团队 ...查看


  • 软件开发实施方案
  • 1 软件开发实施方案 系统开发严格按照软件工程的方法进行组织,系统的开发过程按照需求分析.系统分析与设计要求.系统编码.系统测试几个过程有序推进.下表所示系统开发流程图,采用原型及迭代方式开发,根据用户需求持续改进,直到最终用户确认满意. ...查看


  • 电气控制实训报告1 1
  • 电气自动控制 实训报告 实训时间: 指导老师: 班 级: 姓 名: 学 号: 同组成员: 二. 三. 实训任务 ................................................................ ...查看


  • 触摸屏教学大纲
  • 第1章 K-TP 178Micro型触摸屏及其操作软件WinCC flexible 1.1 编程软件WinCC flexible的安装和卸载 1.2 使用WinCC flexible创建项目与创建画面 1.3 触摸屏画面组态 1.4 触摸屏 ...查看


  • 用户需求说明书
  • 用户需求说明书 版本 1.0 编制: 审核: 批准: 版本变更记录 目 录 1 引言 ............................................................................. ...查看


  • [网络安全技术]课程教案
  • <网络安全技术>课程教案 一.课程定位 网络的安全使用是企事业单位应用网络的基本需求.网络应用包括"建网"."管网"和"用网"三个部分.如果用一棵树形容网络应用,&qu ...查看


  • 浪潮账务软件
  • 第一部分 产品介绍 一.财务会计 (一)应用价值 可以有效地帮助企业解决以下问题: „ 效率低:财务核算效率.准确率低,财务数据反应不及时 „ 风险高:资金管理松懈,收付款业务管理混乱 „ 内控难:无法实现有效的内部控制和业务协同 „ 分析 ...查看


  • 工商管理专业知识与实务(初级)考试大纲
  • 工商管理专业知识与实务(初级) 考试大纲 一.工商企业及其管理概论 考试目的 测查应考试人员是否理解工商企业的概念.特点和发展状况,工商企业管理的主要职能.基础工作等基本内容,以及是否具有运用工商企业及其管理的基本原理分析工商企业履行社会责 ...查看


  • 软件测试方法概述
  • [摘 要]软件在开发过程中不可避免的要出现各种错误,为了最大限度地确保其质量必须进行软件测试.文章即对软件测试的主要方法进行了介绍与说明,以供参考. [关键词]软件质量:软件测试:黑盒测试:白盒测试 1.引言 随着计算机技术的迅速发展和越来 ...查看


热门内容