知识拓展:计算机软件工程

计算机软件工程是—门研究计算机软件设计、开发、实施和维护的工程学科。它将计算机科学、工程技术和软件工程原理结合起来,以满足软件开发过程中的技术要求。

1.软件系统基本概念

计算机软件是计算机系统中与硬件相互依存的一部分,软件是程序、数据及相关文档的完整集合。程序是按事先设计的功能和性能要求执行的指令序列,数据是使程序能正常操纵信息的数据结构,文档是与程序开发、维护和使用有关的图文材料。

软件按功能分为应用软件、系统软件、支撑软件或工具软件。

(1)软件的特点

软件在开发、生产、维护和使用方面与硬件有较大差异,软件的主要特点如下。

· 软件是一种逻辑实体,而不是物理实体,具有抽象性。

· 软件的生产与硬件不同,没有明显的制作过程。

· 软件在运行、使用期间不存在磨损、老化问题。

· 软件的开发、运行对计算机系统具有依赖性,受计算机系统的限制,导致了软件移植的问题。

· 软件复杂性高,成本昂贵。

· 软件开发涉及诸多的社会因素。

(2)软件危机

软件危机是指在计算机软件的开发和维护过程中遇到的一系列严重问题。主要解决的问题是如何开发软件,满足用户对软件日益增长的需求,以及如何维护数量不断膨胀的已有软件。软件危机主要表现在以下方面。

· 对软件开发成本和进度的估计不准确。

· 用户对“已完成的”的软件系统不满意的现象经常发生。

· 软件质量不高、可靠性差。

· 软件常常不可维护。

· 软件缺乏适当的文档资料。

· 软件成本占系统总成本的比例逐年上升。

· 软件的开发速度跟不上计算机硬件的发展速度。

(3)软件工程

软件工程是指导计算机软件开发和维护的一门工程学科。采用工程的概念、原理、技术和方法来开发与维护软件,把经过时间检验的、正确的管理技术和当前能够得到的最好的技术方法结合起来,以开发出高质量的软件并有效维护,这就是软件工程。软件工程三要素如下。

· 软件工程过程:将软件工程划分为若干阶段,定义每个阶段的先后顺序和完成标志。

· 软件工程方法:为软件开发提供“如何做”的技术。如怎样制定项目计划、怎样实施需求分析、如何测试等。

· 软件工程工具:为软件工程方法提供自动或半自动软件支撑环境。如软件开发工具、测试工具等。软件开发的不同阶段可使用不同的工具。

(4)软件生命周期

软件生存周期又称为软件生命期或生存期,是指从形成开发软件概念起,经过开发、使用,直到失去使用价值直至消亡的整个过程。

一般来说,整个生存周期包括计划(定义)、开发、运行维护三个时期,每一个时期又划分为若干阶段。每个阶段有明确的任务,这样使规模大、结构复杂和管理复杂的软件开发变得容易控制和管理。

(5)软件工程的目标与原则

软件工程的目的是建造一个优良的软件系统,在给定成本、进度的前提下,开发出具有有效性、可靠性、可理解性、可维护性、可重用性、可适应性、可移植性、可追踪性和可操作性且满足用户需求的产品,它所包含的内容概括为以下两点。

· 软件开发技术主要有软件开发方法学、软件工具、软件工程环境。

· 软件工程管理主要有软件管理、软件工程经济学。

软件工程需要达到的基本目标:付出较低的开发成本;达到要求的软件功能;取得较好的软件性能;开发软件易于移植;能按时完成开发并及时交付使用。

软件工程的原则包括以下几部分。

· 抽象:抽象是事物最基本的特性和行为,忽略非本质细节,采用分层次抽象,自顶向下,逐层细化的办法控制软件开发过程的复杂性。

· 信息隐蔽:采用封装技术,将程序模块的实现细节隐蔽起来,使模块接口尽量简单。

· 模块化:模块是程序中相对独立的成分,一个独立的编程单位应有良好的接口定义。模块的大小要适中,模块过大会使模块内部的复杂性增加,不利于模块的理解和修改,也不利于模块的调试和重用;模块太小会导致整个系统表达过于复杂,不利于控制系统的复杂性。

· 局部化:保证模块间具有松散的耦合关系,模块内部有较强的内聚性。

· 确定性:软件开发过程中所有概念的表达应是确定、无歧义且规范的。

· 一致性:程序内外部接口应保持一致,系统规格说明与系统行为应保持一致。

· 完备性:软件系统不丢失任何重要成分,完全实现系统所需的功能。

· 可验证性:应遵循容易检查、测评、评审的原则,以确保系统的正确性。

(6)软件开发工具与开发环境

软件工程的理论和技术性研究内容主要包括软件开发技术和软件工程管理。

软件开发工具包括需求分析工具、设计工具、编码工具、排错工具和测试工具等。软件开发工具的完善和发展将促使软件开发方法的进步和完善,促进软件开发的高速度和高质量。软件开发工具的发展是从单项工具的开发逐步向集成工具发展的,软件开发工具为软件工程方法提供了自动的或半自动的软件支撑环境。同时,软件开发方法的有效应用也必须得到相应工具的支持,否则方法将难以有效实施。

软件开发环境(或称软件工程环境)是全面支持软件开发全过程的软件工具集合。计算机辅助软件工程(Computer Aided Software Engineering,CASE)将各种软件工具、开发机器和一个存放开发过程信息的中心数据库组合起来,形成软件工程环境,极大降低软件开发的技术难度并保证软件开发的质量。

2.结构化分析方法

软件开发方法是软件开发所遵循的办法和步骤,以保证得到的运行系统和支持的文档满足质量要求。在软件开发实践中有很多方法可供软件开发人员选择。

(1)需求分析

需求分析是指开发人员要准确理解用户的要求,进行细致的调查分析,将用户非形式的需求陈述转化为完整的需求定义,再由需求定义转换到相应的形式功能规约(需求规格说明)的过程。常见的需求分析方法包括结构化需求分析方法和面向对象的分析方法。需求分析需要进行以下几方面的工作。

· 识别需求:与用户交流,分析问题定义系统的功能需求、性能需求、环境需求、用户界面需求,还有可靠性、安全性、保密性、可移植性、可维护性等方面的需求。

· 分析综合:对获取的需求进行分析,逐步细化软件功能,划分各个子功能,确定系统的构成及主要成分,并用图文结合形式,建立新系统的逻辑模型。

· 编写文档:完成需求规格说明书、初步用户使用手册等,确认测试计划等。

(2)结构化分析方法

结构化分析方法是结构化程序设计理论在软件需求分析阶段的应用,结构化分析方法的实质:着眼于数据流,自顶向下,逐层分解,建立系统的处理流程,以数据流图和数据字典为主要工具,建立系统的逻辑模型。其基本步骤如下。

· 构造数据流模型:根据用户需求,在创建实体关系图的基础上,依据数据流图构造数据流模型。

· 构建控制流模型:一些应用系统除了要求用数据流建模外,通过构造控制流图,构建控制流模型。

· 生成数据字典:对所有数据元素的输入/输出、存储结构,甚至是中间计算结果进行有组织的列表。目前一般采用CASE的“结构化分析和设计工具”来完成。

· 生成可选方案,建立需求规约:确定各种方案的成本和风险等级,据此对各种方案进行分析,然后从中选择一种方案,建立完整的需求规约。

(3)结构化分析常用工具

数据流图(Data Flow Diagram,DFD)以图形的方式描绘数据在系统中流动和处理的过程,反映系统必须完成的逻辑功能,是结构化分析方法中用于表示系统逻辑模型的一种工具。数据流图中的主要元素如图1-9所示。

图1-9

· 加工(转换):输入数据经加工变换产生输出。

· 数据流:沿箭头方向传送数据的通道,一般在旁边标注数据流名。

· 存储文件(数据源):表示处理过程中存放各种数据的文件。

· 数据源点和终点:表示系统和环境的接口,属系统之外的实体。

画数据流图的基本步骤:自外向内,自顶向下,逐层细化,完善求精。

知识拓展

数据字典是对所有与系统相关的数据元素的一个有组织的列表,以及精确的、严格的定义,使得用户和系统分析员对于输入/输出、存储成分和中间计算结果有共同的理解。数据字典的作用是对数据流图中出现的被命名的图形元素的确切解释。数据字典是结构化分析方法的核心。

3.结构化设计方法

需求分析主要解决“做什么”的问题,而软件设计主要解决“怎么做”的问题。

(1)软件设计基础

从技术观点来看,软件设计包括软件结构设计、数据设计、接口设计、过程设计。

· 结构设计:定义软件系统各主要部件之间的关系。

· 数据设计:将分析时创建的模型转化为数据结构的定义。

· 接口设计:描述软件内部、软件和协作系统之间以及软件与人之间如何通信。

· 过程设计:将系统结构部件转换成软件的过程性描述。

从工程角度来看,软件设计分两步完成,即概要设计和详细设计。

· 概要设计:又称结构设计,将软件需求转化为软件体系结构,确定系统级接口、全局数据结构或数据库模式。

· 详细设计:确定每个模块的实现算法和局部数据结构,用适当方法表示算法和数据结构的细节。

(2)软件设计基本原理

软件设计的基本原理包括抽象、模块化、信息隐蔽和模块独立性。

· 抽象:抽象是一种思维工具,把事物本质的共同特性提取出来而不考虑其他细节。

· 模块化:解决一个复杂问题时,自顶向下逐步把软件系统划分成一个个较小的、相对独立但又相互关联的模块的过程。

· 信息隐蔽:每个模块的实施细节对于其他模块来说是隐蔽的。

· 模块独立性:软件系统中每个模块只涉及软件要求的具体的子功能,而和软件系统中其他的模块的接口是简单的。

知识拓展

在结构化程序设计中,模块划分的原则:模块内具有高内聚度,模块间具有低耦合度。

(3)概要设计任务

软件概要设计的基本任务如下。

· 设计软件系统结构。

· 数据结构及数据库设计。

· 编写概要设计文档。

· 概要设计文档评审。

常用的软件结构设计工具是结构图,也称程序结构图。程序结构图的基本符号如图1-10所示。

图1-10

模块用矩形表示,箭头表示模块间的调用关系。在结构图中,带注释的箭头表示模块调用过程中来回传递的信息,带实心圆的箭头表示传递的是控制信息,带空心圆箭头表示传递的是数据信息。

经常使用的结构图有四种模块类型:传入模块、传出模块、变换模块和协调模块,如图1-11所示。

图1-11

· 传入模块:从下属模块取得数据,经处理再将其传送给上级模块。

· 传出模块:从上级模块取得数据,经处理再将其传送给下属模块。

· 变换模块:从上级模块取得数据,进行特定的处理,转换成其他形式,再传送给上级模块。

· 协调模块:对所有下属模块进行协调和管理的模块。

(4)面向数据流的结构化设计方法

面向数据流的设计方法定义了一些不同的映射方法,利用这些方法可以把数据流图变换成结构图来表示软件的结构。数据流的类型大致可以分为两种:变换型和事务型。

· 变换型:变换型数据处理问题的工作过程大致分为三步,即取得数据、变换数据和输出数据。变换型系统结构图由输入、中心变换、输出三部分组成。

· 事务型:事务型数据处理问题的工作机理是接受一项事务,根据事务处理的特点和性质,选择分派一个适当的处理单元,然后给出结果。

(5)详细设计

详细设计是为软件结构图中的每一个模块确定实现算法和局部数据结构,用某种选定的表达工具表示算法和数据结构的细节。详细设计的任务是确定实现算法和局部数据结构,不同于编码或编程。

4.软件测试

软件测试是使用人工或自动手段来运行或测定某个系统的过程,其目的在于检验软件是否满足规定的需求,或是弄清预期结果与实际结果之间的差别。软件测试的目的:尽可能地发现程序中的错误,不能也不可能证明程序没有错误。软件测试的关键是设计测试用例,一个好的测试用例能找到迄今为止尚未发现的错误。

软件测试方法包括静态测试和动态测试。

· 静态测试:包括代码检查、静态结构分析、代码质量度量。不实际运行软件,主要通过人工进行。

· 动态测试:是基于实际运行的测试,包括白盒测试方法和黑盒测试方法。

软件测试一般按照以下过程进行。

(1)单元测试

单元测试是对软件设计的最小单位——模块(程序单元)进行正确性检测的测试,目的是发现各模块内部可能存在的各种错误。单元测试根据程序的内部结构设计测试用例,其依据是详细设计说明书和源程序。单元测试的技术可以采用静态分析和动态测试。对动态测试通常以白盒测试为主,辅之以黑盒测试。单元测试内容包括模块接口测试、局部数据结构测试、错误处理测试和边界测试。

(2)集成测试

集成测试是测试和组装软件的过程,是把模块按照设计要求组装起来的同时进行测试,主要目的是发现与接口有关的错误。集成测试的依据是概要设计说明书。集成测试所涉及的内容包括软件单元的接口测试、全局数据结构测试、边界条件和非法输入的测试等。集成测试通常采用两种方式:非增量方式组装与增量方式组装。

(3)确认测试

确认测试的任务是验证软件的有效性,即验证软件的功能和性能及其他特性是否与用户的要求一致。确认测试的主要依据是软件需求规格说明书。确认测试主要运用黑盒测试法。

(4)系统测试

系统测试的目的在于通过与系统的需求定义进行比较,发现软件与系统定义不符合或与之矛盾的地方。系统测试的测试用例应根据需求分析规格说明来设计,并在实际使用环境下来运行。

知识拓展

系统测试的具体实施一般包括功能测试、性能测试、操作测试、配置测试、外部接口测试、安全性测试等。

5.程序的调试

程序调试的任务是诊断和改正程序中的错误,主要在开发阶段进行,调试程序应该由编制源程序的程序员完成。程序调试的基本步骤包括错误定位、纠正错误和回归测试。软件调试可分为静态调试和动态调试。静态调试主要是指测试人员主观分析源程序代码和排错,是主要的调试手段,而动态调试是辅助静态调试。软件的调试方法可以采用①强行排错法,主要手段:通过内存全部打印来排错,在程序特定部位设置打印语句,自动调试工具;②回溯法,发现错误,分析错误征兆,确定发现“症状”的位置,一般用于小程序;③原因排除法,通过演绎法、归纳法和二分法来实现。

· 演绎法:根据已有的测试用例,设想及枚举出所有可能出错的原因作为假设;然后再用原始测试数据或新的测试,从中逐个排除不可能正确的假设;最后,再用测试数据验证余下的假设,确定出错的原因。

· 归纳法:从错误征兆着手,通过分析它们之间的关系找出错误。大致分四步:收集有关的数据、组织数据、提出假设、证明假设。

· 二分法:在程序的关键点给变量赋正确值,然后运行程序并检查程序的输出。如果输出结果正确,则错误原因在程序的前半部分;反之,错误原因在程序的后半部分。