软件工程—— 理论与实践

297
完善的理论和充分实践的有机结合 实际的案例贯穿软件开发的各过程 丰富的软件工程课程设计可选题目 吕云翔 王昕鹏 邱玉龙 编著 Theory and Practice of Software Engineering 精品系列 21st Century University Planned Textbooks of Computer Science 21世纪高等学校计算机规划教材 软件工程 —— 理论与实践

Transcript of 软件工程—— 理论与实践

21世纪高等学校计算机规划教材

封面设计:董志桢

教材服务热线:010-67170985

反馈 / 投稿 / 推荐信箱:[email protected]

人民邮电出版社教学服务与资源网:www.ptpedu.com.cn

免费提供PPT等教学相关资料

人民邮电出版社

教学服务与资源网

软件工程——理论与实践

Theory and Practice of Software Engineering

■ 完善的理论和充分实践的有机结合

■ 实际的案例贯穿软件开发的各过程

■ 丰富的软件工程课程设计可选题目

吕云翔 王昕鹏 邱玉龙 编著

Theory and Practice of Software Engineering

精品系列

软件工程—

理论与实践

21st Century University Planned Textbooks of Computer Science

21世纪高等学校计算机规划教材

这是一本理论与实践并重的实用软件工程教材,书中不仅介绍了与软件工程相关的基本概念、方法和原理,而且还在此

基础上讲述了可以实际用于软件开发实践的各种技能。各章分为“理论部分”和“实践部分”。“理论部分”组织合理、

切中要点、详略得当;“实践部分”贴近实际,以具体的一个完整案例(贯穿全文)为示范,指导读者利用相关的工具

对所学内容进行具体的运用。此外,还有多个软件工程课程设计题目可供选择,配合丰富的习题,可帮助读者检验各章

的学习效果。

本书旨在使读者在有限的课时内,不仅能对软件工程的原理有所认识,而且能够具备实际的软件开发技能,并且可以熟

练地使用相关的软件工程工具,学会按照标准和规范编写文档等。

软件工程——理论与实践

本教材的结构框图

软件工程理论与实践

其他相关内容

软件工程的其他相关内容

综合实践

课程设计

理论概述

软件工程概述

可行性及需求

可行性研究及需求分析

设计实现及测试

软件测试

软件设计

编码及实现

精品-FM28228软件工程——理论与实践.indd 1 12-6-21 下午1:47

人 民 邮 电 出 版 社

北 京

精品系列

21st Century University Planned Textbooks of Computer Science

21世纪高等学校计算机规划教材

Theory and Practice of Software Engineering

软件工程——理论与实践吕云翔 王昕鹏 邱玉龙 编著

精品-28228软件工程——理论与实践-F.indd 1 12-6-21 下午12:35

内 容 提 要

本书从结构化方法和面向对象方法两方面介绍软件工程的基本概念、原理和方法,并用一个案例贯穿每一章

的实践部分,让读者在认识软件工程原理的基础上,能进一步利用相关的工具对所学内容进行实践,从而实际掌

握进行软件开发的各种技能。本书理论与实践相结合,内容翔实,可操作性强。 本书是高等院校计算机科学、软件工程及相关专业“软件工程”课程的理想教材。

21 世纪高等学校计算机规划教材—精品系列

软件工程—理论与实践

♦ 编 著 吕云翔 王昕鹏 邱玉龙 责任编辑 武恩玉 ♦ 人民邮电出版社出版发行 北京市崇文区夕照寺街 14 号

邮编 100061 电子邮件 [email protected] 网址 http://www.ptpress.com.cn 北京艺辉印刷有限公司印刷 ♦ 开本:787×1092 1/16 印张:18.5 2012 年 8 月第 1 版 字数:489 千字 2012 年 8 月北京第 1 次印刷

ISBN 978-7-115-28228-6

定价:36.00 元 读者服务热线:(010)67170985 印装质量热线:(010)67129223

反盗版热线:(010)67171154

前 言

软件工程是应用计算机科学技术、数学、管理学的原理,运用工程科学的理论、

方法和技术,研究和指导软件开发和演化的一门交叉学科。随着科技的发展,软件

工程已成为计算机科学及其相关专业的一门重要的必修课。软件工程的教学目的在

于使学生掌握其基本概念和原理,培养学生使用工程化的方法高效开发高质量软件

的能力以及进行项目管理的能力。

软件工程是一门理论与实践并重的课程。本书在讲述软件工程的基本概念、原

理和方法的基础上,详细而全面地介绍可以实际用于软件开发实践的各种技能,旨

在使学生通过有限课时的学习后,不仅能对软件工程的原理有所了解,而且能具备

实际开发软件的各种技能,比如熟练使用各种软件工程工具,按照标准和规范编写

文档等。

本书共分为 7章,内容涉及软件工程的基本原理和概念、软件开发生命周期的

各个阶段、项目管理的相关内容、使用各种自动化工具来辅助软件开发的过程以及

课程设计和一些课程设计题目。每章分为理论部分和实践部分。理论部分从理论学

习的角度阐述软件工程的基本概念、原理和方法,在内容的安排上详略得当,使读

者在有限的时间内能领会软件工程的精髓。实践部分配合理论部分的学习内容,指

导读者利用相关的工具对所学内容进行运用。理论与实践的紧密结合,不仅有利于

读者巩固和掌握知识,还能提高实践能力。此外,本书使用一个案例(网上书店系

统)贯穿于各章的实践部分,使读者能通过实例对软件开发过程有一个系统的了解。

本书总结了我们多年软件工程教学与实践的经验,在编写的过程中得到了王明

华、张航、陈捷、于承东和曹科的支持,在此对他们表示感谢。

由于软件工程是一门新兴学科,软件工程的教学方法本身还在探索之中,加之我

们的水平和能力有限,本书难免有疏漏之处,恳请各位同仁和广大读者批评指正,也

希望各位能将实践过程中的经验和心得与我们交流(邮箱:[email protected])。

吕云翔 王昕鹏 邱玉龙 2012年4月于北京航空航天大学软件学院

1

目 录

第 1章 软件工程概述 ..............................1

1.1 软件 ............................................................1 1.1.1 软件的概念.........................................1 1.1.2 软件的特点.........................................2 1.1.3 软件的分类.........................................3

1.2 软件危机 ....................................................4 1.2.1 软件危机的表现 .................................4 1.2.2 软件危机的原因 .................................5

1.3 软件工程 ....................................................6 1.3.1 软件工程的概念 .................................6 1.3.2 软件工程的基本内容 .........................6 1.3.3 软件工程的知识体系 .........................8

1.4 软件生命周期 ..........................................13 1.4.1 软件生命周期的概念 .......................13 1.4.2 传统软件生命周期的各个阶段 .......14

1.5 软件开发模型及其发展 ..........................15 1.5.1 瀑布模型...........................................15 1.5.2 演化模型...........................................16 1.5.3 原型模型...........................................17 1.5.4 增量模型...........................................18 1.5.5 螺旋模型...........................................19 1.5.6 喷泉模型...........................................19 1.5.7 形式化方法模型 ...............................20 1.5.8 基于组件的开发模型 .......................20 1.5.9 统一软件开发过程模型 ...................21 1.5.10 敏捷模型.........................................22

1.6 软件工程的相关工具 ..............................28 1.7 软件工程的常用信息源 ..........................28 1.8 Visio的功能及使用方法介绍 .................29 1.9 Rose的功能及使用方法介绍 .................35 小结 ...................................................................41 习题 ...................................................................41

第 2章 可行性研究及需求分析 ........ 43

2.1 可行性研究 ............................................. 43 2.1.1 可行性研究的目的与意义 .............. 43 2.1.2 可行性研究的内容 .......................... 43 2.1.3 可行性研究的步骤 .......................... 44

2.2 需求分析 ................................................. 45 2.2.1 需求分析的目的与意义 .................. 45 2.2.2 需求分析的步骤 .............................. 46

2.3 结构化需求分析的方法.......................... 48 2.4 结构化需求分析的工具.......................... 48

2.4.1 数据流图 .......................................... 48 2.4.2 数据字典 .......................................... 50 2.4.3 E-R图............................................... 51

2.5 面向对象的软件工程方法...................... 51 2.5.1 面向对象的基本概念 ...................... 51 2.5.2 面向对象的软件工程方法的

特征与优势 ...................................... 53 2.6 面向对象需求分析方法.......................... 55 2.7 UML简介................................................ 56

2.7.1 类图和对象图 .................................. 58 2.7.2 用例图 .............................................. 62 2.7.3 顺序图 .............................................. 63 2.7.4 状态图 .............................................. 64 2.7.5 活动图 .............................................. 65 2.7.6 通信图 .............................................. 66 2.7.7 交互概况图 ...................................... 67 2.7.8 时序图 .............................................. 67 2.7.9 组件图 .............................................. 67 2.7.10 部署图 ............................................ 68 2.7.11 包图 ................................................ 68

2.8 利用 Visio绘制网上书店系统的

数据流图 ................................................. 69 2.9 利用 Rose创建网上书店系统的

用例模型 ................................................ 73

软件工程——理论与实践

2

2.10 需求规格说明书编写指南 ....................77 2.11 网上书店系统的需求规格说明书 ........82 小结...................................................................96 习题...................................................................97

第 3章 软件设计 ......................................98

3.1 软件设计的基本概念 ..............................98 3.1.1 软件设计的分类...............................98 3.1.2 软件设计的原则...............................99

3.2 结构化软件设计方法 ............................102 3.2.1 面向数据流的设计方法.................102 3.2.2 面向数据结构的设计方法 .............105

3.3 结构化软件设计工具 ............................107 3.3.1 流程图 ............................................107 3.3.2 N-S图 .............................................108 3.3.3 PAD图 ............................................109

3.4 面向对象软件设计方法 ........................109 3.5 数据库结构设计 .................................... 112 3.6 软件的体系结构 .................................... 113

3.6.1 软件的体系结构概述.....................113 3.6.2 软件系统的设计模式.....................114

3.7 分布式系统结构 .................................... 118 3.7.1 多处理器体系结构.........................119 3.7.2 客户机/服务器体系结构................119 3.7.3 分布式对象体系结构.....................121 3.7.4 对等端体系结构.............................122 3.7.5 代理 ................................................122

3.8 体系结构框架 ........................................123 3.8.1 模型-视图-控制器.........................123 3.8.2 模型-视图-表示器.........................125 3.8.3 J2EE体系结构框架 .......................125 3.8.4 PCMEF ...........................................126 3.8.5 PCBMER ........................................127

3.9 利用 Visio绘制网上书店系统的

结构图 ....................................................128 3.10 利用 Rose绘制网上书店系统的

顺序图 ..................................................130 3.11 软件设计说明书编写指南 ..................132 3.12 网上书店系统的软件设计说明书 ......135 小结.................................................................149

习题 ................................................................ 150

第 4章 编码及实现............................... 152

4.1 编程语言 ............................................... 152 4.1.1 编程语言的发展与分类 ................ 152 4.1.2 选择编程语言需考虑的因素 ........ 156

4.2 编程风格 ............................................... 156 4.3 Visual Studio的使用方法介绍 ............. 158

4.3.1 Visual Studio概述 ......................... 158 4.3.2 利用 Visual Studio进行开发......... 161 4.3.3 利用 Visual Studio调试................. 168 4.3.4 Visual Studio的进程调试.............. 170

4.4 使用 Visual Studio实现网上书店

系统的用户登录模块 ............................ 172 4.4.1 登录模块描述 ................................ 172 4.4.2 建立数据库和表 ............................ 173 4.4.3 编写数据库操作代码 .................... 174 4.4.4 编写页面和逻辑代码 .................... 176

小结 ................................................................ 178 习题 ................................................................ 179

第 5章 软件测试.................................... 180

5.1 软件测试的基本概念 ........................... 180 5.1.1 软件测试的原则 ............................ 181 5.1.2 软件测试模型 ................................ 182

5.2 软件测试的分类 ................................... 184 5.3 软件测试的方法 ................................... 185

5.3.1 等价类划分法 ................................ 186 5.3.2 逻辑覆盖法 .................................... 188

5.4 软件测试的一般步骤 ........................... 190 5.5 单元测试 ............................................... 191

5.5.1 单元测试的目的 ............................ 191 5.5.2 单元测试和集成测试、系统

测试的区别 .................................... 191 5.5.3 单元测试的几个误区 .................... 191 5.5.4 单元测试的策略 ............................ 192 5.5.5 单元测试的原则 ............................ 193

5.6 集成测试 ............................................... 193 5.6.1 集成测试和系统测试的区别 ........ 193 5.6.2 集成测试考虑的问题 .................... 193

目 录

3

5.6.3 集成测试的层次和策略 .................194 5.6.4 集成测试的过程 .............................195 5.6.5 集成测试的原则 .............................198

5.7 系统测试 ................................................198 5.7.1 功能测试.........................................199 5.7.2 性能测试.........................................200 5.7.3 安全测试.........................................201 5.7.4 GUI测试.........................................202

5.8 面向对象的软件测试 ............................204 5.9 利用 Visual Studio中的工具进行

单元测试 ................................................206 5.9.1 UnitTest使用初步 ..........................206 5.9.2 使用 UnitTest 的自动化数据

驱动测试.........................................213 5.10 其他单元测试工具 ..............................216 5.11 利用 Visual Studio中的工具进行

界面测试 ..............................................218 5.11.1 CodedUITest 使用初步 ...............218 5.11.2 使用 CodedUITest的自动化

数据驱动界面测试 ........................221 5.12 利用 Visual Studio对网上书店系统的

用户登录模块进行单元测试 ..............224 5.13 测试分析报告编写指南 ......................226 5.14 网上书店系统的测试分析报告 ..........228 小结 .................................................................240 习题 .................................................................241

第 6章 软件工程的其他

相关内容.....................................243

6.1 软件维护 ................................................243 6.1.1 软件维护的过程 .............................244 6.1.2 软件维护的分类 .............................245 6.1.3 软件的可维护性 .............................246 6.1.4 软件维护的副作用 .........................247

6.2 软件质量保证 ........................................248 6.2.1 软件质量的基本概念 .....................248 6.2.2 软件质量保证的措施 .....................249

6.3 软件配置管理概述 ................................250

6.3.1 软件配置管理术语 ........................ 251 6.3.2 配置管理的过程 ............................ 253 6.3.3 配置管理的角色划分 .................... 253

6.4 软件估算 ............................................... 254 6.4.1 软件估算的概念 ............................ 254 6.4.2 软件估算的方法 ............................ 256 6.4.3 软件估算的原则与技巧 ................ 257

6.5 软件过程能力成熟度模型.................... 258 6.6 软件项目管理 ....................................... 259 6.7 软件文档 ............................................... 261 6.8 Project的功能及使用方法介绍 ........... 263

6.8.1 Project概述 .................................... 263 6.8.2 利用 Project管理网上书店

系统的开发过程 ............................ 270 6.9 用户手册编写指南................................ 273 6.10 用户安装手册编写指南...................... 274 小结 ................................................................ 275 习题 ................................................................ 275

第 7章 课程设计 .................................... 277

7.1 课程设计 ............................................... 277 7.2 课程设计题目 ....................................... 278

7.2.1 网上书店 ........................................ 278 7.2.2 图书馆图书管理系统 .................... 279 7.2.3 教务系统 ........................................ 279 7.2.4 会议室管理系统 ............................ 280 7.2.5 财务管理系统 ................................ 280 7.2.6 本科生毕业设计管理 .................... 280 7.2.7 BBS系统........................................ 281 7.2.8 教师工资管理系统 ........................ 281 7.2.9 网上投稿系统 ................................ 281 7.2.10 学校教材订购系统 ...................... 282 7.2.11 网上机票订约系统 ...................... 282 7.2.12 网上选课管理系统 ...................... 283 7.2.13 远程教学平台 .............................. 283 7.2.14 小型商业网站 .............................. 283 7.2.15 小型超市收银系统 ...................... 284 7.2.16 ATM柜员机模拟程序 ................ 284 7.2.17 模拟计算器 .................................. 284

软件工程——理论与实践

4

7.2.18 俄罗斯方块游戏...........................285 7.2.19 通讯录 ..........................................285 7.2.20 即时通信系统...............................285 7.2.21 游戏编程.......................................285 7.2.22 高校医院管理信息系统...............286

7.2.23 酒店管理系统 .............................. 286 7.2.24 复杂网络环境下的 B/S、

C/S混合系统 ............................... 287

参考文献 ........................................................ 288

1

第1章 软件工程概述 本章目标 ● 了解软件的概念,理解软件的特点。 ● 了解软件危机产生的原因和表现,明确软件工程的重要性。 ● 掌握软件工程的基本内容。 ● 掌握软件生命周期的概念。 ● 掌握各种软件开发模型的特征及适用范围。 ● 熟悉与软件开发项目相关的常用自动化工具。 ● 掌握 Microsoft Office Visio 的功能及使用方法。 ● 掌握 Rational Rose 的功能及使用方法。

1.1 软 件

1.1.1 软件的概念

软件是计算机系统的“思维中枢”,在计算机系统中起着举足轻重的作用。它与计算机硬件相

互作用,相互配合,从而实现了特定的系统功能。计算机软件的概念是随着计算机技术的发展而

发展的。 在计算机发展初期,软件就是指程序,即计算机可以识别的源代码或机器可直接执行的代码。

当时,软件的作用并没有得到足够的重视。使用者一般需要直接操纵计算机硬件,程序是为某个

特定问题而专门设计的。 随着计算机技术的发展,人们越来越充分认识到高质量的

软件会使计算机系统的功能和效率大大地提高。高质量、多功

能的软件使得计算机的应用从单一的科学计算扩展到多个领

域,比如数据处理、实时控制等。随着计算机应用的日益普及,

软件日益复杂,规模日益增大,人们开始意识到软件并不仅仅

等于程序。 全面地讲,软件由图 1-1所示的 3部分组成。具体包括: (1)计算机程序,即人们为了完成特定的功能而编制的一

组指令集。

图 1-1 软件的组成

软件工程——理论与实践

2

(2)数据,即程序能处理的具有一定数据结构的信息。 (3)软件文档,它是与程序的开发、维护和使用有关的图文资料,如软件开发计划书、需求

规格说明书、设计说明书、测试分析报告和用户手册等。

1.1.2 软件的特点

任何事物都有自己的特点,这是区别于其他事物的根本。理解事物的特点有利于人们更加深

刻、更加准确地认识事物的本质。作为计算机系统的重要组成部分,计算机软件的功能依赖于计

算机硬件的支持。与硬件相比,计算机软件具有以下特点。 (1)计算机硬件是实物产品,是有形的设备,具有明显的可见性。但是,人们却无法直接观

察计算机软件的物理形态,只能通过观察它的实际运行情况来了解它的功能、特性和质量等。 (2)人们在分析、设计、开发、测试软件产品以及在软件开发项目的管理过程中,渗透了大

量的脑力劳动。可以说,人类的逻辑思维、智能活动和技术水平是生产软件产品的关键。而传统

意义上的硬件制造,除了人类的脑力劳动外,还需要大量的体力劳动。 程序员,就像诗人一样,几乎是仅仅工作在单纯的思考中。

—《人月神话》 (3)在计算机系统运行的过程中,计算机硬件存在着磨损和老化的现象,这也是一切物理器

件都存在的普遍现象。但是,硬件设备磨损后,人们可以简单地用另一个硬件设备替换。对于计

算机软件而言,不存在像硬件一样的磨损和老化现象,因为它不会受到引起硬件磨损的环境因素

(比如温度、振动、灰尘和阳光等)的影响。但是软件却存在着缺陷维护和技术更新的问题。人们

在对软件的缺陷进行维护或者对技术进行更新的时候,往往要对软件的设计和编码进行改动,这

个过程会比简单的硬件替换复杂得多。如图 1-2 和图 1-3 所示分别展示了硬件的失效率与使用时间的关系以及软件的失效率与使用时间的关系。

图 1-2 硬件失效曲线图 图 1-3 软件失效曲线图

计算机系统的硬件维护包括了 3 项活动:更换损坏的器件,清洁和润滑及修改设计上的缺

陷。软件维护不包括清洁、润滑和对损坏器件的修复,它主要包含对设计缺陷的修复。 —《人月神话》

第 1章 软件工程概述

3

(4)软件的开发和运行必须依赖于特定的计算机系统环境,比如硬件、网络配置和支撑软件等。软件对运行环境的这种依赖性是一般产品所没有的。为了减少这种依赖性,在软件开发的过

程中提出了软件的可移植性。 (5)软件具有可复用性。软件一旦被开发出来,便可以很容易地被大量复制,从而形成多个

副本,而硬件产品必须经过完整的生产周期才能得到。

1.1.3 软件的分类

随着计算机软件复杂性的增加,在某种程度上很难对软件给出一个通用的分类,但是可以从

不同的角度,按照特定的方法对软件进行归类。 按照功能的不同,可以把软件划分为系统软件、支撑软件和应用软件。 (1)系统软件是与计算机硬件结合最紧密的软件,它在计算机系统中必不可少,可以协调各

个物理部件的工作,同时服务于其他上层软件。操作系统就是最典型的系统软件,它负责管理系

统的资源,并为上层软件的运行提供了必备的接口和条件。 (2)支撑软件是工具性软件,它一方面可以协调用户进行软件开发,另一方面还能对应用软

件进行维护。我们常用的文本编辑器、绘图软件、数据库管理系统和 CASE工具系统等都属于支撑软件。 (3)应用软件是为特定的领域或服务开发的针对性较强的软件。它的种类极其繁多,应用范

围最为广泛,是直接服务于用户的软件。比如,地理信息系统软件、航空售票软件、教务管理系

统软件和信息管理系统等。 按照软件服务对象的不同,软件还可以分为通用软件和定制软件。 (1)通用软件是由特定的软件开发机构开发,面向市场公开销售的独立运行的软件系统,如

操作系统、文档处理系统和图片处理系统等。 (2)定制软件通常是面向特定的用户需求,由软件开发机构在合同的约束下开发的软件,如

为企业定制的办公系统、交通管理系统和飞机导航系统等。 按照软件产品规模的不同,计算机软件还可以划分为小型软件、中型软件和大型软件。按照

工作方式的不同,计算机软件还可以划分为实时软件、分时软件、交互式软件和批处理软件。 软件的分类示意图如图 1-4所示。

图 1-4 软件的分类

软件工程——理论与实践

4

1.2 软 件 危 机

1.2.1 软件危机的表现

软件危机是指落后的软件生产方式无法满足迅速增长的计算机软件需求,从而导致软件开

发与维护过程中出现一系列严重问题的现象。软件危机爆发于 20 世纪 60 年代中期,随着软件规模的扩大、复杂性的增加及功能的增强,高质量的软件开发变得越来越困难。在软件开发的

过程中经常会出现不能按时完成任务,产品质量得不到保证,工作效率低下和开发经费严重超

支等情况。这些情况逐渐使人们意识到软件危机的存在及其重要性。具体来讲,软件危机的主

要表现如下。 (1)开发人员开发的软件产品不能完全满足用户的需求,即产品的功能或特性与需求不符。

这主要是因为开发人员与用户之间的交流不够充分,使得开发人员理解的用户需求与实际的用户

需求之间存在差异。 (2)软件产品的质量难以得到保证。开发团队缺少完善的软件质量评审体系以及科学的软件

测试规程,使得最终的软件产品存在诸多缺陷。 (3)软件产品的开发周期、开发经费和维护费用很难被准确地估计,从而给项目的管理带来

很多麻烦。很多情况下,软件产品的开发周期或经费会大大超出预期。 (4)随着技术的更新和用户需求的扩大,已有的软件产品往往不能灵活地适应环境的改变。

再加上软件生产观念的落后和高素质软件开发人员的匮乏等因素,软件产品的可维护性、可扩展

性和可复用性往往不能满足市场的要求。 (5)软件文档不完备,并且存在文档内容与软件产品不符的情况。软件文档是计算机软件的

重要组成部分,它为在软件开发人员之间以及开发人员与用户之间信息的共享提供了重要的平台。

软件文档的不完整和不一致会给软件的开发和维护等工作带来很多麻烦。 在史前史中,没有别的场景比巨兽们在焦油坑中垂死挣扎的场面更令人震撼。上帝见证着

恐龙、猛犸象、剑齿虎在焦油中挣扎。它们挣扎得越猛烈,焦油纠缠得就越紧。没有任何猛兽

足够强壮或具有足够的技巧能够挣脱束缚,它们最后都沉到了坑底。 过去几十年的大型系统开发就犹如这样一个焦油坑,很多大型和强壮的“动物”在其中剧

烈地挣扎。他们中大多数开发出了可运行的系统—但只有极少数项目满足了目标、进度和预

算的要求。各种团队,大型的和小型的,庞杂的和精干的,一个接一个地淹没在了“焦油坑”

中。表面上看起来好像没有哪一个问题会导致开发困难,每个问题都能得到解决,但是当它们

互相纠缠和累积在一起的时候,团队的行动就变得越来越慢。对问题的麻烦程度,每个人似乎

都会感到惊讶,却很难看清问题的本质。 —《人月神话》

软件开发过程中出现的这些问题严重影响了软件产业健康快速地发展。为了形象地描述软件

危机,OS 360经常被作为一个典型的案例。这是一个超大型的软件项目,动用了近千名程序员。经历了数十年的开发之后,极度复杂的软件项目甚至产生了一套不包括在原始设计方案之中的工

作系统。Frederic kP. Brooks是这个项目的管理者,他在自己的著作《人月神话》中曾经承认,自

第 1章 软件工程概述

5

己犯了一个价值数百万美元的错误。

Frederick P. Brooks, Jr.

Frederick P. Brooks是 1999年的图灵奖得主。他在 29岁时就主持和领导了被称为人类从原子能时代进入信息时代标志的 IBM/360 系列计算机的开发工作,取得辉煌成功,从而名噪一时,与 Bob Evans并称为“IBM/360之父”。IBM/360 成功以后,他离开 IBM 回到其故乡,为北卡罗来纳大学

(UNC)创建了计算机科学系,担任该系系主任长达 20年(1964~1984年)。卸任以后仍在该系任教至今。 他作为硬件和软件的双重专家和出色的教育家,始终活跃在计算机舞台上,在计算机技术

的诸多领域中都做出了巨大的贡献。1987 年,Brooks 当选为美国工程院院士,他同时也是英国皇家学会和荷兰皇家科学与艺术院的外籍院士。

Brooks的著作不多,但影响都很大,最为著名的是 1975年出版的《人月神话》(The Mythical Man-Month: Essays on Software Engineering)。本书是他领导 IBM/360软件开发经验的结晶,内容丰富而生动,堪称软件工程方面的经典之作。

1.2.2 软件危机的原因

软件危机的出现及其日益严重的趋势充分暴露了软件产业在早期发展过程中存在的各种各样

的问题。可以说,人们对软件产品认识的不足以及对软件开发的内在规律的理解偏差是软件危机

出现的本质原因。具体来说,软件危机出现的原因可以概括为以下几点。 (1)软件开发是一项复杂的工程,需要用科学的工程化的思想来组织和指导软件开发的各个

阶段。而这种工程学的视角正是很多软件开发人员所没有的,他们往往简单地认为软件开发就是

程序设计。 (2)没有完善的质量保证体系。建立完善的质量保证体系需要有严格的评审制度,同时还需

要有科学的软件测试技术及质量维护技术。软件的质量得不到保证,开发出来的软件产品往往不

能满足需求,同时还可能需要花费大量的时间、资金和精力去修复软件的缺陷,从而导致软件质

量下降和开发预算超支等后果。 (3)软件文档的重要性没有得到软件开发人员和用户的足够重视。软件文档是软件开发团队

成员之间交流和沟通的重要平台,也是软件开发项目管理的重要工具。如果不能充分重视软件文

档的价值,势必会给软件开发带来很多不便。 (4)从事软件开发的专业人员对这个产业认识不充分,缺乏经验。软件产业相对于其他工业

产业而言是一个比较年轻、发展不太成熟的产业,人们对它的认识缺乏深刻性。 (5)软件独有的特点也给软件的开发和维护带来困难。软件的抽象性和复杂性使得软件在开

发之前很难对开发过程的进展进行估计。再加上软件错误的隐蔽性和改正错误的复杂性,都使得

软件开发和维护在客观上比较困难。 为了解决软件危机,人们逐渐认识了软件的特性以及软件产品开发的内在规律,并尝试用工

程化的思想去指导软件开发,于是软件工程诞生了。

软件工程——理论与实践

6

1.3 软 件 工 程

1.3.1 软件工程的概念

1968年,在北大西洋公约组织举行的一次学术会议上,该组织的科学委员们在开会讨论软件的可靠性与软件危机的问题时,首次提出了“软件工程”的概念,并将其定义为“为了经济地获

得可靠的和能在实际机器上高效运行的软件而建立和使用的健全的工程规则”。这个定义肯定了工

程化的思想在软件工程中的重要性,但是并没有提到软件产品的特殊性。 经过 40多年的发展,软件工程已经成为一门独立的学科,人们对软件工程也逐渐有了更全面、

更科学的认识。在现代,软件工程是指应用计算机科学技术、数学和管理学的原理,运用工程科

学的理论、方法和技术,研究和指导软件开发和演化的一门交叉学科。它强调按照软件产品的特

殊性质,采用工程化的思想来指导软件开发,在高效的软件生产和科学的项目管理的基础上得到

高质量的软件产品。 可以说,软件工程的提出是为了解决软件危机所带来的各种弊端。具体地讲,软件工程的目

标主要包括以下几点: (1)使软件开发的成本能够控制在预计的合理范围内; (2)使软件产品的各项功能和性能能够满足用户需求; (3)提高软件产品的质量; (4)提高软件产品的可靠性; (5)使生产出来的软件产品易于移植、维护、升级和使用; (6)使软件产品的开发周期能够控制在预计的合理时间范围内。 开发人员交付的是用户满意度,而不仅仅是有形的产品。

—Cosgrove 实际上,我们可以把上述各个目标概括为开发正确、可用和经济的软件产品。当然,在实际

的软件开发过程中,软件开发团队很难同时兼顾所有的目标。通常,人们会根据实际项目的情况,

对各个目标做优先级排序。

1.3.2 软件工程的基本内容

相对于其他学科而言,软件工程是一门比较年轻的学科,它的思想体系和理论基础还有待进

一步修正和完善。软件工程学科包含的内容有软件工程

原理、软件工程过程、软件工程方法、软件工程模型、

软件工程管理、软件工程度量、软件工程环境和软件工

程应用等,如图 1-5所示。 软件工程原理就是指软件工程学科在发展过程中所

遵循的基本原理和普遍规律。实际的软件开发项目只有

在一定的软件工程原理的约束下,才能够有效地贯彻软

件工程的思想。经过长期的开发实践和理论研究,著名软件工程专家 B. W. Boehm提出了以下几

图 1-5 软件工程学科

第 1章 软件工程概述

7

项软件工程的基本原则。 (1)将软件的生命周期划分为多个阶段,对各个阶段实行严格的项目管理。软件开发是一个

漫长的过程,人们可以根据工作的特点或目标,把整个软件的开发周期划分为多个阶段,并为每

个阶段制定分阶段的计划及验收标准,这样有利于对整个软件开发过程进行管理。在传统的软件

工程中,软件开发的生命周期可以划分为可行性研究、需求分析、软件设计、软件实现、软件测

试、产品验收和交付等阶段。 (2)坚持阶段评审制度,以确保软件产品的质量。严格地贯彻与实施阶段评审制度可以帮

助软件开发人员及时地发现并改正错误。在软件开发的过程中,错误发现得越晚,修复错误所

要付出的代价就会越大。实施阶段评审,只有在本阶段的工作通过评审后,才能进入下一阶段的

工作。 (3)实施严格的产品控制,以适应软件规格的变更。在软件开发的过程中,用户需求很可能

不断发生变化。有些时候,即使用户需求没有改变,软件开发人员受到经验的限制以及与用户交

流不充分的影响,也很难做到一次性获得全部的、正确的需求。可见,需求分析工作应该贯穿整

个软件开发的生命周期。在软件开发的整个过程中,需求的改变是不可避免的。当需求变更时,

为了保证软件各个配置项的一致性,实施严格的版本控制是非常有必要的。 不变只是愿望,变化才是永恒。

—《人月神话》 (4)采用现代程序设计技术。这是提高软件开发和维护效率的关键。现代的程序设计技术,

比如面向对象,可以使开发出来的软件产品更易于维护和修改,同时还能缩短开发的时间,并且

更符合人们的思维逻辑。 (5)开发出来的软件产品应该能够清楚地被审查。虽然软件产品的可见性比较差,但是它的

功能和质量应该能够被准确地审查和度量,从而有利于有效的项目管理。一般软件产品包括可以

执行的源代码、一系列相应的文档和资源数据等。 (6)合理地安排软件开发小组的人员,并且开发小组的人员要少而精。开发小组人员的数量

少,有利于组内成员充分的交流,这是高效团队管理的重要因素。而高素质的开发小组成员是影

响软件产品的质量和开发效率的重要因素。 (7)不断地改进软件工程实践。随着计算机科学技术的发展,软件从业人员只有不断地总结

经验并且主动学习新的软件技术,才能不落后于时代。 软件工程过程是指在软件的生命周期内,为了实现特定目标而进行的一系列相关活动。每个

活动都有其确定的实现步骤。过程也可以划分为多种类型,如开发过程、维护过程、支持过程和

管理过程等。 软件工程方法包含软件开发方法、软件度量方法、软件管理方法和软件环境方法,但是通常

把软件工程方法等同于软件开发方法。目前,常用的软件开发方法有面向过程的开发方法、面向

对象的开发方法、面向数据的开发方法和形式化方法。在本书的后续章节中,我们将详细介绍面

向过程的开发方法和面向对象的开发方法。 面向数据的开发方法是指面向元数据的方法,它与关系数据库管理系统紧密地联系在一起。

从 20世纪 80年代开始流行的关系数据库管理系统和关系数据库程序设计语言促进了面向数据的开发方法的发展。这种方法适合于信息系统中数据层的开发,在程序执行的过程中,可以根据数

据流动和处理的需要,选择由程序控制还是由用户控制。

软件工程——理论与实践

8

形式化方法建立在严格的数学逻辑的基础上,以逻辑推理为出发点,其内容包括有限状态机、

程序的正确性证明、净室软件工程、Petri网和通信系统演算等。形式化方法多用在对安全性和可靠性要求较高的系统中,如航空航天系统和铁路运输系统等。

软件工程模型有领域模型、需求模型、设计模型、实现模型和测试模型。每种模型都反映了

一定的工作特点,它们可以由建模语言(如 UML)来描述。 除了以上这些内容以外,软件工程还包括管理、度量、环境和应用等领域的内容。总的来说,

软件工程是一门交叉学科,涉及的范围很广泛。

1.3.3 软件工程的知识体系

虽然“软件工程”这个概念对我们来说并不陌生,它在 20世纪 60年代就被提出,但是,软件工程作为一个合理的工程学科和一个被认可的职业状态的时间却不长。IEEE计算机学会主持了一个名为“软件工程知识体系指南”(SWEBOK: Guide to the Software Engineering Body of Knowledge 2004 Version)的项目,它清晰地描述了“软件工程知识体系”的内容以及体系中哪些部分已经被普遍接受。概括来讲,IEEE计算机学会建立“软件工程知识体系指南”的目的主要有以下几点。 (1)促进世界范围内对软件工程的一致观点。 (2)阐明软件工程相对于其他学科的位置,并确立它们的分界。“软件工程知识体系指南”认

为与软件工程相关的学科有 8个,分别是 ① 计算机工程(computer engineering); ② 计算机科学(computer science); ③ 管理(management); ④ 数学(mathematics); ⑤ 项目管理(project management); ⑥ 质量管理(quality management); ⑦ 软件人类工程学(software ergonomics); ⑧ 系统工程(systems engineering)。 (3)刻画软件工程学科的内容。 (4)提供使用知识体系的主题。 (5)为开发课程表、个人认证和许可材料提供基础。 电气电子工程师学会(Institute of Electrical and Electronics Engineers, IEEE)是一个成立

于 1963年 1月 1日的国际性电子技术与电子工程师协会,亦是世界上最大的专业技术组织之一,

拥有来自 175 个国家的 36 万会员。除设立于美国纽约市的总部以外,其在全球 150 多个国家亦

拥有分会,并且还有 35 个专业学会及两个联合会。其每年均会出版多种杂志、学报、书籍,亦

举办至少 300 次的专业会议。目前 IEEE 在工业界所定义的标准有着极大的影响。 IEEE 定位在“科学和教育,并直接面向电子电气工程、通信、计算机工程、计算机科学理

论和原理研究的组织以及相关工程分支的艺术和科学”。为了实现这一目标,IEEE 承担着多个

科学期刊和会议组织者的角色。它也是一个广泛的工业标准开发者,主要领域包括电力、能源、

生物技术和保健、信息技术、信息安全、通信、消费电子、运输、航天技术和纳米技术。

知识小卡片

第 1章 软件工程概述

9

在 SWEBOK中,“软件工程”被定义为 (1)应用系统化、学科化和定量化的方法来开发、运行和维护软件,即将工程应用到软件中; (2)对(1)中各种方法的研究。 SWEBOK将“软件工程”组织为 11个知识域(knowledge areas,KA),如图 1-6所示。

图 1-6 软件工程的知识域

软件需求是为解决特定问题而必须由被开发的软件展示的特性。软件需求知识域涉及软件需

求的获取、分析、规格说明和确认,它还可以进一步分解为 7个子领域,如图 1-7所示。

图 1-7 软件需求知识域的结构分解

定义一个系统或组件的体系结构、组件、接口和其他特征的过程以及这个过程的结果被称为

软件设计。软件设计包含 6个子领域,如图 1-8所示。 软件构造是指通过编码、验证、单元测试、集成测试和调试的组合,详细地创建可工作的和

有意义的软件的过程。软件构造知识域包含 3个子领域,如图 1-9所示。 软件测试是为评价和改进产品的质量,标识产品的缺陷和问题而进行的活动,软件测试知识

域的结构分解如图 1-10所示。

软件工程——理论与实践

10

图 1-8 软件设计知识域的结构分解

图 1-9 软件构造知识域的结构分解

图 1-10 软件测试知识域的结构分解

第 1章 软件工程概述

11

软件维护是指由于一个问题或改进的需要而修改代码和相关文档,进而修正现有软件产品并

保证其完整性的过程。软件维护知识域包括 4个子领域,如图 1-11所示。

图 1-11 软件维护知识域的结构分解

软件配置管理是一个支持性的软件生命周期过程,它是为了系统地控制配置变更,在软件系

统的整个生命周期中维持配置的完整性和可追踪性而标识系统在不同时间点上的配置的学科。软

件配置管理知识域的结构分解如图 1-12所示。

图 1-12 软件配置管理知识域的结构分解

为了保证软件的开发和维护是系统的、规范的和量化的,对软件工程进行管理是非常有必要

的。软件工程管理的活动建立在组织和内部基础结构管理、项目管理、度量程序的计划制定和控

软件工程——理论与实践

12

制 3个层次上,其知识域的结构分解如图 1-13所示。

图 1-13 软件工程管理知识域的结构分解

软件工程过程涉及软件生命周期过程本身的定义、实现、评估、管理、变更和改进。软件工

程过程知识域的结构分解如图 1-14所示。

图 1-14 软件工程过程知识域的结构分解

软件工程工具与方法的知识域覆盖整个生命周期过程,其结构分解如图 1-15所示。 软件质量特征涉及多个方面,保证软件产品的质量是软件工程的重要目标。软件质量知识域

包含 3个子领域,如图 1-16所示。

第 1章 软件工程概述

13

软件工程工具 软件工程方法 

软件需求工具 

·需求模型 

·需求可追踪性 

软件设计工具 

软件构造工具 

·程序编辑器 

·编译器与代码生成器 

·解释器 

·调试器 

软件测试工具 

·测试生成器 

·测试执行框架 

·测试评价 

·测试管理 

·性能分析 

软件维护工具 

·程序理解 

·再工程 

软件配置管理工具 

·缺陷、增强、发生和问题追踪 

·版本管理 

·发布与建造 

软件工程管理工具 

·项目计划与追踪 

·风险管理 

·度量 

软件工程过程工具 

·过程建模 

·过程管理 

·集成 CASE 环境 

·以过程为中心的软件工程环境 

软件质量工具 

·评审与审计 

·静态分析 

其他工具问题 

·工具集成技术 

·元工具 

·工具评价 

启发式方法 

·结构化方法 

·面向数据方法 

·面向对象方法 

形式化方法 

·规格说明语言与符号 

·细化 

·验证/证明特性 

原型方法 

·风格 

·原型化对象 

·评价技术 

图 1-15 软件工程工具与方法知识域的结构分解

图 1-16 软件质量知识域的结构分解

1.4 软件生命周期

1.4.1 软件生命周期的概念

任何事物都有一个从产生到消亡的过程,事物从其孕育开始,经过诞生、成长、成熟、衰退

到最终灭亡,就经历了一个完整的生命周期。生命周期是世界上任何事物都具备的普遍特征,软

件产品也不例外。作为一种工业化的产品,软件产品的生命周期是指从设计该产品的构想开始,

软件工程——理论与实践

14

到软件需求的确定、软件设计、软件实现、产品测试与验收、投入使用以及产品版本的不断更新,

到最终该产品被市场淘汰的全过程。 软件产品概念的提出有利于人们更科学、更有效地组织和管理软件生产。软件生命周期这个

概念从时间的角度将软件的开发和维护的复杂过程分解为若干个阶段,每个阶段都完成特定的相

对独立的任务。由于每个阶段的任务相对于总任务难度会大幅度降低,在资源分配、时间把握和

项目管理上都会比较容易控制。合理地划分软件生命周期的各个阶段,使各个阶段之间既相互区

别又相互联系,为每个阶段赋予特定的任务,这些都是软件开发项目成功的重要因素。

1.4.2 传统软件生命周期的各个阶段

对软件生命周期的划分必须依据特定的软件开发项目所采用的软件开发模型。软件开发模型

相当于软件生命周期中所有工作和任务的总体框

架,它不仅反映了软件开发的组织方式,还映射

了不同阶段之间的过渡和衔接关系。采用不同模

型开发的软件产品,其生命周期也有所不同。但

是,在传统的软件工程中,软件产品的生命周期

一般可以划分为 6个阶段,如图 1-17所示。 1.可行性研究

可行性研究阶段为后续的软件开发做必要的准备工作。它首先要确定待开发的软件产品所要

解决的问题。软件分析人员与用户之间需要充分地交流与合作,才能对待开发软件产品的目标达

成一致。同时,在可行性研究阶段,开发人员还应该确定总体的开发策略与开发方式,并对开发

所需要的资金、时间和各种资源做出合理的估计。精确的预估需要建立在开发人员对用户需求的

充分了解以及自身丰富经验的基础上。此外,在可行性研究阶段还需要对开发软件产品进行可行

性分析,并制定初步的开发计划。可行性分析是为了在技术、经济、操作或社会等多个方面寻求

可行的解决方案,并对各个方案进行比较,完成可行性分析报告。 2.需求分析

需求是指为了解决用户提出的问题,目标系统需要做什么。需求分析是一个很复杂的过程,

需求分析是否准确和成功,直接关系到后续的软件开发的成败。在需求分析阶段,开发人员首先

要通过各种途径对需求进行获取,要得到正确和详尽的需求,开发人员与用户之间的交流与沟通

是非常重要的。得到需求后,开发人员需要对原始的需求进行抽象与概括,从功能、性能、界面

和接口等诸多方面对需求进行详细的描述,并最终反映到软件需求规格说明书中。 3.软件设计

软件设计就是指在需求分析的基础上,软件开发人员通过制定设计方案,把需求文档中描述

的功能可操作化。设计可以分为概要设计和详细设计两个阶段。概要设计旨在建立系统的总体结

构,从总体上对软件的结构、接口和全局数据结构等给出数据说明。详细设计关注每个模块的内

部实现细节,为后续的编码工作提供最直接的依据。 4.编码

在编码阶段,开发人员根据设计阶段制定出的设计方案,编写程序代码。简单地说,编码的

过程就是把详细设计文档中对每个模块实现过程的算法描述转换为能用某种程序设计语言来实现

的程序。在规范的软件开发过程中,编码必须遵守一定的标准,这样有助于团队开发,同时能够

提高代码的质量。

图 1-17 传统的软件生命周期

第 1章 软件工程概述

15

计算机编程基于十分容易掌握的介质,编程人员通过非常纯粹的思维活动—概念以及灵

活的表现形式来开发程序。 —《人月神话》

5.软件测试

软件测试是保证软件质量的关键步骤。软件测试的目的是发现软件产品中存在的缺陷,进而

保证软件产品的质量。在软件开发的实践中,软件缺陷的产生是必然的。软件缺陷发现得越晚,

修复缺陷所需的成本就越高,损失也就越大。为了尽早发现软件缺陷,有效地进行软件测试是必

需的。按照测试点的不同,测试可以分为单元测试、集成测试、系统测试和验收测试。 6.软件维护

在软件产品被交付后,其生命周期还在继续。在使用的过程中,用户还会不断地发现产品中

所隐藏的各种各样的错误。同时,随着用户需求的增长或改变以及市场环境的变化,软件产品的

功能需要不断更新,版本需要不断升级。所以,在使用软件产品的过程中,软件开发人员需要对

产品进行维护,以保证软件产品的正常运行。一般来讲,软件产品的质量越高,进行维护的工作

量就会越小。

1.5 软件开发模型及其发展

在现实生活中,人们处理问题时经常采用建模的方法。在软件工程中,人们通过建立抽象的

软件开发模型,把软件生命周期中的各个活动或步骤安排到一个框架中,将软件开发的全过程清

晰且直观地表达出来。可以说,软件开发模型是软件工程思想的具体化,它反映了软件在其生命

周期中各阶段之间的衔接和过渡关系以及软件开发的组织方式,是人们在软件开发实践中总结出

来的软件开发方法和步骤。 软件开发模型的内在特征有以下 4点: (1)描述了主要的开发阶段; (2)定义了每个阶段要完成的主要任务和活动; (3)规范了每个阶段的输入和输出; (4)提供了一个框架,把必要的活动映射到这个框架中。 40多年来,软件工程领域中出现了多种不同的软件开发模型,它们具有不同的特征,适用于

不同特点的软件开发项目。 常见的软件开发模型有很多种,这里主要介绍瀑布模型,演化模型(包含原型模型、增量模

型和螺旋模型),喷泉模型,形式化方法模型,基于组件的开发模型,统一软件开发过程模型以及敏捷模型。

1.5.1 瀑布模型

瀑布模型是出现得比较早的软件开发模型。在这种模型中,各阶段之间的组织方式就如同瀑

布流水一样,逐级下落。开发人员必须在完成前一阶段的任务后,才能开始下一阶段的工作,各

个阶段之间通常是按固定顺序连接的,前一阶段的输出往往就是后一阶段的输入。瀑布模型的过

程如图 1-18所示。

软件工程——理论与实践

16

图 1-18 瀑布模型

根据瀑布模型的理论,这种模型具有以下几个特点。 (1)瀑布模型是一种线性的软件开发模型,回溯性很差。也就是说,只有某一个阶段的活动

完成后,开发过程才会进入下一个阶段,各阶段之间按单向顺序逐级过渡。如果在后续阶段中发

现前一阶段的错误,那么修复错误将会造成巨大的损失。 (2)瀑布模型是一种基于里程碑的阶段过程模型。开发人员为每个阶段设立里程碑或基线,

并组织好对基线的评审与审计。阶段评审通过后才能开始下一阶段的工作。这种里程碑式的工作

流程有助于开发人员及时地发现各个阶段中产生的软件缺陷,对软件产品的质量进行管理。 (3)瀑布模型强调软件开发过程的阶段性,每个阶段完成特定的任务。软件开发人员可以按

阶段制定项目计划,核算成本,分配资源和评审标准等,这为软件项目的管理提供了便利,提供

了项目管理的可操作性。瀑布模型为软件开发提供了一种有效的项目管理模式,这是瀑布模型在

20世纪 80年代之前广受推崇的重要原因。 瀑布模型适用于具有以下特征的软件开发项目。 (1)在软件开发的过程中,需求不发生或很少发生变化,并且开发人员可以一次性获取到全

部需求。否则,由于瀑布模型较差的可回溯性,在后续阶段中需求的经常性变更需要付出高昂的

代价。 (2)软件开发人员具有丰富的经验,对软件应用领域很熟悉。 (3)软件项目的风险较低。瀑布模型不具有完善的风险控制机制。 根据以上对瀑布模型的描述,可以总结出瀑布模型的优点是阶段性强,易于对项目进行管理,

缺点是开发过程不灵活,不能适应环境的变化。如果后续阶段中发现前期工作的错误或需求发生

了变更,就会造成巨大的损失。

1.5.2 演化模型

大量开发实践表明,在需求阶段很难全面、精确地提出软件的需求,这也导致瀑布模型等线

性开发模型会因为过多回溯大大增加开发成本。为了减少这种因为前期需求的不确定性导致过多

回溯给软件开发带来的风险,可以在获取部分基本需求后,通过快速分析,构造出该软件的一个

初始版本,这个版本称为原型(prototype)。然后通过让用户使用原型,提出意见和建议,并结合需求的变更来开发新的原型,重复这一过程,直到原型演化为最终客户满意的软件产品。 演化模型其实就是将构造的含有部分需求(如前期需求)的版本,通过逐步完善演化为最终

第 1章 软件工程概述

17

版本软件产品的过程。演化模型特别适用于在前期难以准确提出软件需求的软件开发中,典型的

演化模型有原型模型、增量模型和螺旋模型。

1.5.3 原型模型

原型模型是开发人员为了快速准确地获取需求而经常采用的方法。在初步获取需求后,开

发人员会快速地开发一个原型系统。通过对原型系统进行模拟操作,开发人员可以更直观、更

全面和更准确地了解用户对待开发系统的各项要求,同时还能挖掘到隐藏的需求。如果开发人

员对将采用的开发技术把握不大,也可以采用原型模型进行技术上的尝试,以降低后续开发的

风险。 按照应用目的,原型主要分为 3类。 (1)探索型原型。主要用于弄清目标系统的要求,确定系统特性以及探索解决方案的可

行性。 (2)实验型原型。主要是验证方案或算法的合理性,以便在正式开发和实现之前,考核方案

是否合适,规格说明是否可靠。 (3)演化型原型。是目标系统的子部分,通过不断改进该原型,将其演化为最终目标系统。 前两种原型使用后通常被丢弃,然后根据探索或实验的结果用更好的结构和设计方案重新设

计目标系统。第 3种由于实现了目标系统特性的一个子集,可以通过不断修改和扩充该子集的方式将其演化为目标系统。在应用中,有很多原型辅助开发工具辅助进行原型开发,如界面原型、

窗口管理原型、报告生成原型等。 原型模型的开发过程如图 1-19所示。

图 1-19 原型模型

原型模型具有以下特点。 (1)原型模型主要用于挖掘需求,或是进行某种技术或开发方法的可行性研究。在构造原型

时,开发人员要本着省时、省力和省资源的原则。如果需求或设计方案已确定下来,则原型将不

再使用。 (2)原型系统通常针对软件开发系统的子功能模块,其功能相对不完善。 (3)由于原型系统功能的局部性以及存在阶段的局部性,因此在软件开发的实践中,原型模

软件工程——理论与实践

18

型通常结合其他的软件开发模型共同使用。 原型模型适用于具有以下特征的软件开发项目。 (1)对现有的软件系统进行产品升级或功能完善。 (2)开发人员与用户之间交流受限,需求获取困难。 (3)开发人员对将要采用的技术手段不熟悉或把握性不大。 (4)具备快速开发的工具。 根据以上对原型模型的描述,原型模型的优点是简单和快速,缺点是需要花费一些额外的成

本来构造原型,并且不利于创新。

1.5.4 增量模型

增量模型是把待开发的软件系统模块化,将每个模块作为一个增量组件,从而分批次地分析、

设计、编码和测试这些增量组件。运用增量模型的软件开发过程是递增式的过程。相对于瀑布模

型而言,采用增量模型进行开发,开发人员不需要一次性地把整个软件产品提交给用户,而是可

以分批次进行提交。 一般情况下,开发人员会首先实现提供基本核心功能的增量组件,创建一个具备基本功能的

子系统,然后再对其进行完善。增量模型的示意图如图 1-20所示。

图 1-20 增量模型

增量模型的最大特点就是将待开发的软件系统模块化和组件化。基于这个特点,增量模型具

有以下优点。 (1)将待开发的软件系统模块化,可以分批次地提交软件产品,使用户可以及时了解软件项

目的进展。 (2)以组件为单位进行开发,降低了软件开发的风险。一个开发周期内的错误不会影响到整

个软件系统。 (3)开发顺序灵活。开发人员可以对组件的实现顺序进行优先级排序,先完成需求稳定的核

心组件。当组件的优先级发生变化时,还能及时地对实现顺序进行调整。 增量模型的缺点是要求待开发的软件系统可以被模块化。如果待开发的软件系统很难被模块

化,那么将会给增量开发带来很多麻烦。 增量模型适用于具有以下特征的软件开发项目。 (1)软件产品可以分批次地进行交付。 (2)待开发的软件系统能够被模块化。 (3)软件开发人员对应用领域不熟悉,难以一次性地进行系统开发。 (4)项目管理人员把握全局的水平较高。

第 1章 软件工程概述

19

1.5.5 螺旋模型

螺旋模型是一种用于风险较大的大型软件项目开发的过程模型。它把开发过程分为制定计划、

风险分析、实施工程和客户评估 4种活动。制定计划就是要确定软件系统的目标,了解各种资源

限制并选定合适的开发方案。风险分析旨在对所选方案进行评价,识别潜在的风险,并制定消除

风险的机制。实施工程的活动中渗透了瀑布模型的各个阶段,开发人员对下一版本的软件产品进

行开发和验证。客户评估是获取客户意见的重要活动。螺旋模型的示意图如图 1-21所示。

图 1-21 螺旋模型

螺旋模型适应于风险较大的大型软件项目的开发。它的优点是将风险分析扩展到各个阶段中,

大幅度降低了软件开发的风险。但是这种模型的控制和管理较为复杂,可操作性不强,对项目管

理人员的要求较高。

1.5.6 喷泉模型

喷泉模型是一种过程模型,同时也支持面向对象开发。喷泉模型

的示意图如图 1-22所示。在分析阶段,定义类和对象之间的关系,建立对象-关系和对象-行为模型。在设计阶段,从实现的角度对分析阶段

模型进行修改或扩展。在编码阶段,使用面向对象的编程语言和方法

实现设计模型。在面向对象的方法中,分析模型和设计模型采用相同

的符号标示体系,各阶段之间没有明显的界限,而且常常重复、迭代

地进行。 “喷泉”一词体现了面向对象方法的迭代和无间隙性。迭代是指各阶

段需要多次重复,例如,分析和设计阶段常常需要多次、重复进行,以更

好地实现需求。无间隙性是指各个阶段之间没有明显的界限,并常常在时

间上互相交叉,并行进行。

演化

集成

测试

编码

设计

分析

图 1-22 喷泉模型

软件工程——理论与实践

20

1.5.7 形式化方法模型

形式化方法使用形式化的数学方法将系统描述转换为最终目标系统执行程序,适用于对安全

性、可靠性和保密性要求极高的软件系统开发。 形式化方法模型的示意图如图 1-23所示,通过将系统需求转换为使用数学符号表达的形式化

描述,然后再经一系列的转换将形式化描述转化为可执行程序,最后再将这些程序集成起来。 由于数学方法具有严密性和精确性,所以使用形式化方法模型的软件系统具有相对较少的缺

陷和安全漏洞。但是,实际中采用这一方法模型的工程并不多,主要有以下原因。 (1)形式化开发方法需要开发人员有一定的技能基础并经受严格的方法训练。 (2)实际中使用的大多数系统是交互性的系统,这些系统不太适宜使用形式化方法进行描述。 (3)对需求进行形式化描述和转换非常耗时费力,导致其开发成本相对较高。

需求定义 形式化描述 形式化转换1

形式化转换2

……

形式化转换n 集成和系统测试

形式化转换 n

图 1-23 形式化方法模型

1.5.8 基于组件的开发模型

基于组件的开发模型使用现有的组件以及系统框架进行产品开发,由于现有组件大多已经历

实际应用的反复检验,因此其可靠性相对新研发组件高出很多。 实际上,从最简单的应用程序到极度复杂的操作系统,现在的新产品开发很少有完全从零开

发的,而是或多或少地使用了现有的组件或系统开发框架,比如大型游戏的开发常常使用现有的

图形引擎、声音引擎以及场景管理模块等。使用现有的组件开发新产品不仅极大地提高了产品开

发效率,同时由于组件常常是经历了时间考验的,因此产品的质量也得到了提高。 基于组件开发模型的示意图如图 1-24所示,在确定需求之后,开发人员开始从现有的组件库

中筛选合适的组件,并对组件功能进行分析。组件库可能是组织内部开发的,也可能是商业授权

组件,后者常常需要支付费用并且不能任意修改和传播,但也有一些开源组织(如著名的 GNU)或自由开发人员提供免费并可自由修改和传播的组件。在对组件分析之后,开发人员可能适当修

改需求来适应现有组件,也可能修改组件或寻找新的组件。组件筛选完成之后,开发人员需要根

据需求设计或使用现有的成熟开发框架复用这些组件,一些无法利用现有组件的地方,则需要进

行单独的开发,新开发的组件在经历时间考验之后也会加入到组件库中。最后将所有组件集成在

一起进行系统测试。 基于组件的开发模型充分体现了软件复用的思想,降低了开发成本和风险,并加快了产

品开发。根据 AT&T 等公司的经验,一些软件使用复用组件比例高达 90%以上,可以提高产品研发效率 2~5倍,错误率降低到 1/10~1/5,成本减少 15%~75%。随着技术的发展,现在的软件系统越来越庞大,完全从零开发已近乎不可能,基于现有组件或系统开发已成为一

种趋势。

第 1章 软件工程概述

21

需求定义 组件分析 需求修改

面向复用的系统设计

开发和集成 系统验证

组件库 图 1-24 基于组件的开发模型

1.5.9 统一软件开发过程模型

统一软件开发过程(Rational Unified Process,RUP)模型是基于 UML(统一建模语言)的一种面向对象软件开发模型。它解决了螺旋模型的可操作性问题,采用迭代和增量递进的开发策略,

并以用例驱动为特点,集中了多个软件开发模型的优点。RUP模型的示意图如图 1-25所示。

图 1-25 统一软件开发过程模型

图 1-25 中的纵轴以工作的内容为组织方式,表现了软件开发的工作流程。工作流程就是指一系列的活动,这些活动产生的结果是可见的价值。工作流程可以分为核心工作流程和核心

支持工作流程。其中核心工作流程是在整个项目中与主要关注领域相关的活动的集合。在每

个迭代的软件生命周期中,核心工作流程有业务建模、需求、分析与设计、实现、测试和部

署。配置与变更管理、项目管理和环境属于核心支持工作流程,它们为核心工作流程的实施

提供支持。 图 1-25中的横轴以时间为组织方式,表现了软件开发的 4个阶段:先启、细化、构建和产品

化,每个阶段中都可能包含若干次迭代。这 4个阶段按照顺序依次进行,每个阶段结束时都有一个主要里程碑。实际上,可以把每个阶段看成是两个主要里程碑之间的时间跨度。在每个阶段结

束时都要进行阶段评估,确保该阶段目标已被实现,从而进入下一个阶段。阶段与里程碑的关系

如图 1-26所示。

软件工程——理论与实践

22

图 1-26 统一软件开发过程的项目阶段和里程碑

统一软件开发过程模型是基于迭代思想的软件开发模型。在传统的瀑布模型中,项目的组织

方法是使其按顺序一次性地完成每个工作流程。通常,在项目前期出现的问题可能推迟到后期才

会发现,这不仅增大了软件开发的成本,还严重影响了软件开发的进度。采用迭代的软件工程思

想可以多次执行各个工作流程,有利于更好地理解需求,设计出合理的系统构架,并最终交付一

系列渐趋完善的成果。可以说,迭代是一次完整地经过所有工作流程的过程,从图 1-25中我们可以看到,每个阶段都包含了一次或多次的迭代。 统一软件开发过程模型适用的范围极为广泛,但是对开发人员的素质要求较高。

1.5.10 敏捷模型

随着计算机技术的迅猛发展和全球化进程的加快,软件需求常常发生变化,强烈的市场竞争

要求更快速地开发软件,同时软件也能够以更快的速度更新。传统的方法在开发时效上时常面临

挑战,因此,强调快捷、小文档、轻量级的敏捷开发方法开始流行。如今,“敏捷”已经成为一个

非常时尚的名词。敏捷方法是一种轻量级的软件工程方法,相对于传统的软件工程方法,它更强

调软件开发过程中各种变化的必然性,通过团队成员之间充分的交流与沟通以及合理的机制来有

效地响应变化。 敏捷开发开始于“敏捷软件开发宣言”。2001年 2月,17位软件开发方法学家在美国犹他州

召开了长达两天的会议,制订并签署了“敏捷软件开发宣言”,该宣言给出了 4个价值观。 (1)个体与交互高于过程和工具。这并不是否定过程与工具的重要性,而是更加强调人与人

的沟通在软件开发中的作用。因为软件开发过程最终还是要由人来实施的,只有涉及软件开发过

程的各方面人员(需求人员、设计师、程序员、测试人员、客户和项目经理等)充分地沟通和交

流,才能保证最终的软件产品符合客户的需求。如果只是具有良好的开发过程和先进的过程工具,

而开发人员本身技能很差,又不能很好地沟通,那么软件产品最终一样会遭到失败。 (2)可运行软件高于详尽的文档。对用户来说,更多地会通过直接运行程序而不是阅读大量

的使用文档来了解软件的功能。因此,敏捷软件开发强调不断地、快速地向用户提交可运行程序,

虽然不一定是用完整程序来让用户了解软件以及得到用户的认可,但重要文档仍然是不可缺少的,

能帮助用户更精准、全面地了解软件的功能,软件开发的主要目标是开发出可执行的软件。 (3)与客户协作高于合同(契约)谈判。大量实践表明,在软件开发的前期,很少有客户能

够精确完整地表达他们的需求,即便是那些已经确定下来的需求,也常常会在开发过程中改变。

因此,靠合同谈判的方式将需求确定下来非常困难。对于开发人员来说,客户的部分需求变更甚

至会导致软件的大范围重构,而通过深入分析客户需求之后,有时还会发现通过适当调整需求就

可以避免做出重大调整。而对于前者的情况,开发团队往往通过和客户谈判,撰写精确的需求合

同来限制需求变更。但这导致最终的软件产品功能与客户需求之间存在难以避免的差异,导致客

户的满意度降低。因此,敏捷软件开发强调与客户的协作,通过密切的沟通合作而不是合同契约

来确定用户的需求。

第 1章 软件工程概述

23

(4)对变更及时响应高于遵循计划。任何的软件开发都需要制定一个详细的开发计划,确定各任务活动的先后顺序以及大致日期。然而,随着项目的进展,需求、业务环境、技术、团队等

都有可能发生变化,任务的优先顺序和时间有时必须面临调整,所以,必须保证项目计划能够很

好地适应这种难以预料的变化,并能够根据变化修订计划。比如,软件开发的后期,如果团队人

员流失,那么如果时间允许,适当后延计划比补充新的开发人员进入项目风险更小。 发表“敏捷软件开发宣言”的 17 位软件开发人员组成了敏捷软件开发联盟(agile software

development alliance),简称“敏捷联盟”。他们当中有极限编程的发明者 Kent Beck,Scrum的发明者 Jeff Sutherland和 Crystal的发明者 Alistair Cockburn。“敏捷联盟”为了帮助希望使用敏捷方法来进行软件开发的人们定义了 12条原则。 (1)我们首先要做的是通过尽早和持续交付有价值的软件来让客户满意。 (2)需求变更可以发生在整个软件的开发过程中,即使在开发后期,我们也欢迎客户对于需

求的变更。敏捷过程利用变更为客户创造竞争优势。 (3)经常交付可工作的软件。交付的时间间隔越短越好,最好 2~3周一次。 (4)在整个的软件开发周期中,业务人员和开发人员应该天天在一起工作。 (5)围绕受激励的个人构建项目,给他们提供所需的环境和支持,并且信任他们能够完成

工作。 (6)在团队的内部,最有效果和效率的信息传递方法是面对面交谈。 (7)可工作的软件是进度的首要度量标准。 (8)敏捷过程提倡可持续的开发速度。责任人、开发人员和用户应该能够保持一种长期稳定

的开发速度。 (9)不断地关注优秀的技能和好的设计会增强敏捷能力。 (10)尽量使工作简单化。 (11)好的架构、需求和设计来源于自组织团队。 (12)每隔一定时间,团队应该反省如何才能有效地工作,并相应调整自己的行为。 敏捷联盟官方网站为 http://www.agilealliance.org/home。

1.敏捷模型的特点

敏捷模型避免了传统的重量级软件开发过程复杂、文档烦琐和对变化的适应性弱等弊端,强

调软件开发过程中团队成员之间的交流、过程的简洁性、用户反馈、对所做决定的信心以及人性

化的特征。 敏捷模型强调软件开发过程中需求变化的必然性以及随时发生的可能性,因此对于软件系统

的建模要尽量简洁,这样才能更快地适应变化。开发人员还应该重视获取用户对于系统模型的反

馈意见,及时对模型进行修改,使之更好地反映用户的需求。此外,开发人员在完成工作时必须

有清晰的目标,这样才能避免盲目地工作。为了适应不同的项目情况,必要时还可以使用多种模

型。在对模型的表述问题上,敏捷模型更加注重模型的内容。可以说,在使用敏捷模型进行建模

的开发人员的眼中,内容比表现方式更加重要。只要能够有效地表达模型的内涵,使用何种建模

工具并不重要。在工作的过程中,团队成员之间的有效交流是非常重要的。开放和真诚的交流是

保证团队工作效率的重要途径。最后,使用敏捷模型建模时,还应关注工作的质量。 通俗来讲,敏捷模型就是“快”,快才能适应需求的频繁变化以及软件开发的快节奏。为了加

知识小卡片

软件工程——理论与实践

24

快速度,敏捷开发团队一般采用小版本的开发方式,使新功能可以快速展示给用户。为了缩短软

件版本的周期,“迭代”思想在软件开发的过程中至关重要。但是,对于复杂的用户需求,要同时

做到总体上的统一与合理的分割并不是很容易。 可以说,敏捷模型更加强调发挥团队成员的个性思维。虽然结对编程、代码共有和团队替补

等方式能够有效地减小个人对软件的影响力,但是还是会造成软件开发的继承性的下降。对于大

型软件系统的开发,规范的文档管理还是极其重要的。如果能有效合理地将敏捷的开发方法与传

统的软件开发方法进行结合,那么对软件产品的开发是非常有益的。 2.XP简介

敏捷模型包括多种实践方法,比如极限编程(eXtreme Programming,XP)、自适应软件开发(Adaptive Software Development,ASD)、动态系统开发方法(Dynamic System Development Method,DSDM)、Scrum、Crystal和特征驱动开发(Feature Driven Development,FDD)等。本节重点介绍极限编程的相关内容。

极限编程是一种实践性较强的规范化的软件开发方法,它强调用户需求和团队工作。利用极

限编程方法进行软件开发实践的工程师,即使在开发周期的末期也可以很快地响应用户需求。在

团队工作中,项目经理、用户以及开发人员都有责任为提高软件产品的质量而努力。XP 特别适用于软件需求模糊且容易改变、开发团队人数少于 10人、开发地点集中(比如一个办公室)的场合。

Kent Beck

“极限编程”是由 Kent Beck在 1996年提出的。Kent Beck从 20世纪 90年代初就开始探索新的软件开发方法,希望能使软件开发更加简单而有效。

通过仔细观察并分析各种简化软件开发的前提条件、可能性及面临的困难,

Kent Beck终于在 1996年的某个软件开发项目中引入了“极限编程”这个新的软件开发观念,因此也被誉为“极限编程之父”。

在俄勒冈州大学读本科期间,Kent Beck开始研究模式。他一直倡导软件开发的模式定义。早在 1993年,他就和“UML之父”Grady Booch发起并组织了一个团队进行这方面的研究。虽然撰写了 Smalltalk Best Practice Patterns一书,但这并不是他最大的贡献。他于 1996年提出的极限编程(XP)的方法学才是他的杰作,真正影响了后来的软件开发。和软件开发大师Martin Fowler合著的 Planning Extreme Programming可谓是关于 XP的奠基之作。后来,Test Driven Development: By Example、Extreme Programming Explained: Embrace Change等一系列作品让更多的人领略到了极限编程的精髓,也推进了极限编程的流行。

Kent Beck的贡献远非如此。对于众多的 Java程序员来说,他和 Erich Gamma共同打造的JUnit意义更加重大。也许正是这个简单而又强大的工具,让众多的程序员更加认可和信赖极限编程。

极限编程包含了一组相互作用和相互影响的规则和实践。在项目计划阶段,需要建立合理和

简洁的用户故事。在设计系统的体系架构时,可以采用 CRC(Class,Responsibility,Collaboration)卡促使团队成员共同努力。代码的质量在极限编程项目中非常重要。为了保证代码的质量,可以

采用结对编程以及在编码之前构造测试用例等措施。在测试方面,开发人员有责任向用户证明代

码的正确性,而不是由用户来查找代码的缺陷。合理的测试用例及较高的测试覆盖率是极限编程

项目测试所追求的目标。图 1-27更加详细地描述了极限编程所推崇的规则和实践方法。

第 1章 软件工程概述

25

图 1-27 极限编程所推崇的规则和实践方法

3.XP的 4个价值观

(1)交流。由于 XP方法使用较少的文档,因此 XP方法非常强调项目人员之间的沟通交流,尤其是直接的面对面的交流。交流不仅能使相关人员更为精确地理解需求,而且能够尽可能避免

因为需求变更导致的不一致。事实上,一些项目的失败就是由于项目相关人员沟通不到位导致的,

比如客户的需求变更没有准确及时地传递给涉及的开发人员,导致系统的不一致和集成的困难,

而如果这一问题在软件交付时才发现,那么修正的代价可能惊人得高。因此,项目相关人员之间

的充分沟通交流是极度重要的,尤其是对于 XP这种只有核心文档的项目来说。 (2)简单。简单是 XP 推崇的理念,一切都使用最简单、最小代价的方式达到目的以及用最

简洁的方法达到客户的要求。比如简单的过程(根据项目特点,对过程模型剪裁),简单的模型(可

使用任意模型,只要能达到目的即可),简单的文档(只编写核心的、必需的文档),简洁的设计

实现等。该价值观体现了软件开发的“刚好够用”的思想,避免冗余繁杂。 (3)反馈。及时高效的反馈能够确保开发工作的正确性,并能够在发生错误时更及时地纠正

偏差。比如,团队工作时,相关开发人员在一起工作,这样每个人的意见都能够在几分钟甚至几

软件工程——理论与实践

26

秒钟内得到反馈。而通过非正式的评审(如走查)也可在几分钟的沟通中得到反馈,相比于正式

的评审会议,这种方式显然省时得多,而且也更及时。 (4)勇气。Scott W.Ambler 在《敏捷建模:极限编程和统一过程的有效实践》一书中指出:

“敏捷方法要求与其他人密切地合作,充分信任他人,也信任自己,这需要勇气。XP和敏捷建模(AM)等方法要求做能做到的最简单的事,相信明天能解决明天的问题,这需要勇气。AM要求只有在绝对需要的情况下才创建文档,而不是只要觉得舒适就去创建,这需要勇气。XP 和 AM要求让业务人员制定业务决策,如排定需求的优先级,而让技术人员制定技术决策,如软件如何

去满足需求,这需要勇气。AM 要求用尽可能简单的工具,比如白板和纸,除非复杂的建模工具能够提供更高价值时才去使用它们,这需要勇气。AM 要求不要为了推迟困难任务(如需要使用代码来验证模型)而把大量时间浪费在图的加工上,这需要勇气。AM 要求信任你的同事,相信程序员能制定设计决策,因此不需要给他们提供过多的细节,这需要勇气。AM要求必胜的信心,去结束 IT产业中接近灾难和彻底失败的循环,这需要勇气”。同时,“需要勇气来承认自己是会犯错误的,需要勇气来相信自己明天能克服明天出现的问题”。

4.XP的 12 个核心实践

(1) 完整的团队。使用 XP 方法时,项目组的所有成员最好在同一个场所工作,以便及时沟通和解决问题。同时,项目组中要求有一个现场用户,由其提出需求并制定需求优先级,编写验收测试用例。 (2)计划对策。有两个计划是必需的:发布计划和迭代计划。计划是根据业务需求的优先级

和技术评估来制定的,优先实现高优先级和技术难度低的需求,而低优先级和高技术难度的需求

则可以根据情况调整到后续计划中实现,这样可以尽可能地保证项目顺利进行以及给有难度的技

术争取更多的时间。制定的计划常常是可调整的,因为随着项目的进行,难免会出现一些前期无

法预料的事情,这时就要根据具体情况适当修正计划。 (3)系统比喻。系统比喻是对待开发软件系统的一种形象化比喻,这种比喻描述了开发人员

将来如何构建系统,起到一种概念性框架的作用。这种比喻必须是团队成员共同熟悉的。 (4)小发布。需要经常、不间断地发布可运行的、具有商业价值的小软件版本,以供用户使

用、评估和及时反馈。 (5)测试。XP 方法推荐在编写代码之前优先编写测试,这样开发人员可以在开发中快速地

检验自己的代码是否正确实现了功能。 (6)简单设计。系统的设计应该尽可能简洁,刚好满足当前定义的功能最好,简单、易懂、

无冗余,能通过所有的测试,没有重复混乱的逻辑,正确完整地实现了开发人员的意图,同时尽

可能少地使用类和方法。设计还应符合系统的比喻,以便于以后对系统重构。 (7)结对编程。XP 方法强烈推荐的一个核心实践是结对编程,即两个程序员肩并肩地坐在

同一个计算机前合作编程,在一个编程的同时,另一个负责检查代码的正确性和可读性。结对的

程序员之间可以是动态调整的,但是结对必须经过缜密的思考和计划,因为多数程序员习惯了独

自编码。通过结对,程序员通常可以更快地解决问题;由于两个程序员具有相同缺点和盲点的可

能性要小得多,所以出现更少的错误,降低了测试的时间和成本;程序员间的互相激励、帮助和

监督,降低了编程的枯燥性和懒惰的可能性。同时,由于软件中的任何一段代码至少有两位程序

员非常熟悉,因此,个别的人员流动对项目进展造成的影响就会相对很小。 (8)设计改进。在整个开发过程中,需要对程序的结构和设计不断地评估和改善。在不改变外部

可见功能的情况下,按照高内聚、低耦合的原则对程序内部实现进行改进,力求代码的简洁、无冗余。 (9)持续集成。持续集成是指完成一个模块的开发和单元测试之后,立即将其组装到系统中

第 1章 软件工程概述

27

进行集成测试,而且必须完成本次集成才能继续下一次集成。这样虽然集成的次数会增加很多,

但保证了每一个完成的模块始终是组装完毕、经过测试和可执行的。 (10)代码全体共有。代码全体共有是指团队中的任何人都可以在任何时候修改系统任何位置上

的代码。这是建立在小系统开发的前提下,由于团队的成员都可以参与模型的开发,又有系统的比喻,

因此,基本上每一个成员都会对系统有一定程度的了解。而且,结对编程、编码标准、持续集成等实

践都为代码全体共享提供了支持,能及时尽早地发现代码中的缺陷和错误,避免在后期集中爆发。 (11)编码标准。很多软件开发模型都强调编码标准,当然 XP也不例外。为编码制订统一的

标准,包括代码、注释、命名等,使得代码在整体上呈现一致性,为日后维护提供极大的便利。 (12)可持续步调。XP方法要求团队中的每一个成员时刻保持充沛的精力投入到项目中,长

时间、超负荷的工作会使工作效率极大地下降,因此,XP方法建议采用每周 40小时工作制,如果加班,也尽量限制在 2周之内。

5.XP开发过程

如图 1-28所示是 XP方法的开发过程模型,分为 5个阶段:探索阶段、计划阶段、迭代到发布阶段、产品化阶段和维护阶段。XP 中的各阶段之间并没有明显的界限,各个阶段之间常常存在往复,每个阶段的持续时间也随项目的不同而有所变化,比如计划阶段可能只需几小时即可完

成。下面对各个阶段的具体任务做简单介绍。

用户故事

体系结构骨架

探索阶段

制订发布计划

计划阶段

难点骨架

迭代开发

验收测试

小交付

测试用例

需求

系统比喻 发布计划 最新版本 用户认可

新用户故事 错误

下一迭代确定的估计不确定的估计

维护阶段

迭代到发布阶段 产品化阶段

图 1-28 XP方法的开发过程模型

(1)探索阶段。探索阶段的主要任务是设定用户故事和体系结构骨架。用户故事由用户参与讲述,用户故事描述了系统的高层需求,是制订发布计划的输入。一个项目中,用户故事可能有

几个到几十个。体系结构骨架是系统中固定不变的部分,为该部分找出一种比喻,描述开发人员

准备如何构建系统,起到概念框架的作用。例如,可以把网上购物比喻为到传统的商店购物,订

单比喻为购物车,客户填写订单比喻为把货物放进购物车等。等到团队对系统比喻达成共识之后,

就可以绘制体系结构骨架模型图(敏捷方法更注重内容,对图形的绘制要求并不严格)。根据测试

优先的思想,探索阶段还应该依据用户故事制订测试用例,用于后期的验收测试。 (2)计划阶段。计划阶段的主要任务是根据用户故事、体系结构骨架以及系统比喻指定迭代

和发布计划。可以使用任意的方法为用户故事建立直观的模型,用模型来描述用户故事的任务以

及这些任务间的关系,然后,尽可能地精准估计任务的工作量作为制订详细计划的依据。但这并

不是绝对的,计划可能会随着计划的执行修改甚至增删。对于一些难点骨架,常常需要反复分析

才能排除其中的不确定估计。

软件工程——理论与实践

28

(3)迭代到发布阶段。迭代到发布阶段根据前一阶段制订的迭代和发布计划开发用户需求的软件,软件的开发工作,包括建模、编码、测试和集成都在这一阶段完成。对集成后的新版本进

行验收测试(测试用例在第一阶段已经完成),如果发现错误或需要进行下一次迭代,则重复迭代

开发工作。如果这一阶段有新的用户故事加入,则回到计划阶段适当修改或调整迭代和发布计划。 (4)产品化阶段。在产品化阶段需要对最终的软件版本进行更多的测试,包括系统测试、负

载测试、安装测试等。该阶段另一个重要的工作就是整理文档,虽然敏捷方法并不注重文档,但

有些文档是非常必要的,比如系统文档、操作文档、支持文档和用户文档。这些文档能够极大地

方便日后的维护工作以及使非开发人员快速地了解和使用系统。在以后的系统升级或二次开发中,

这些文档也能够帮助新的开发团队快速理解原系统的设计和实现方案。 (5)维护阶段。维护阶段涵盖了计划阶段、迭代到发布阶段和产品化阶段,主要包括系统的

运行和支持等面向产品的活动。

1.6 软件工程的相关工具

软件工具是进行软件开发时必不可少的部分,是指在软件开发、测试、维护和分析过程中,

程序员所使用的辅助工具。合适的软件工具可以帮助软件开发人员方便、便捷、高效地进行软件

开发、维护和管理等工作。通常,人们把在软件项目的开发过程中,相关的开发人员按照软件工

程的原则和方法,借助于计算机及其软件工具的帮助,开发、维护和管理软件产品的过程称为计

算机辅助软件工程(Computer-Aided Software Engineering,CASE)。 软件工具的使用为软件项目的开发过程提供了自动化的支持,可以在很大程度上简化软件开

发过程,提高软件开发质量,减少成本,缩短项目工期,并方便项目的管理工作。 与软件工程相关的常用工具软件主要有Microsoft Office Visio、Rational Rose、Microsoft Office

Project、Microsoft Visual Studio、Together、CASE Studio、Microsoft Visual Sourcesafe、Microsoft TeamSuite、Clear Case和Microsoft Fxcop等。其中,Microsoft Office Visio、Rational Rose、Together和 CASE Studio属于建模工具,Microsoft Office Project常用于软件项目的管理,Microsoft Visual Studio是强大的编码工具,同时也提供单元测试的功能,Microsoft Fxcop是静态代码分析工具,而Microsoft Visual Sourcesafe、Microsoft TeamSuite和 Clear Case是配置管理工具。 在本书的实践部分将重点介绍Microsoft Office Visio、Rational Rose、Microsoft Office Project

和Microsoft Visual Studio的使用。

1.7 软件工程的常用信息源

因特网上与软件工程相关的资源非常丰富,下面列出了一些网站地址,方便读者学习。 http://se.csai.cn/ http://www.51testing.com/ http://www.csdn.net/ http://www.csai.cn/ http://www.uml.org.cn/

第 1章 软件工程概述

29

http://www.csia.org.cn

1.8 Visio 的功能及使用方法介绍

Microsoft Office Visio(以下简称 Visio)是Microsoft Office家族中的一员,是一种强大的绘图工具软件。它提供了丰富的绘图模板集,可以帮助用户快速、简捷地绘制各种图形,帮助用户

将信息形象化和直观化,以方便信息的交流和共享。 在软件工程项目的需求分析阶段,可以利用 Visio绘制数据流图和 E-R图(实体-联系图)等

图形。 Visio的文件共有 3种类型,分别是绘图文件、模具文件和模板文件。绘图文件扩展名为.vsd,

用于存储绘制的各种图形。模具文件扩展名为.vss,是与特定的 Visio 模板(.vst 文件)相关联的形状的集合,用来存放绘图过程中产生的各种图形的“母体”。模板文件的扩展名为.vst,它同时存放了绘图文件和模具文件,并定义了相应的工作环境。3种类型文件之间的关系如图 1-29所示。

图 1-29 Visio中 3种文件之间的关系

一般情况下,模具文件位于绘图窗口的左侧,它包

含大量的绘图文件。用户可以通过拖动的方式将绘图文

件添加到绘图窗口上来反复创建图形元素,如图 1-30所示。 目前,Visio的最新版本是Microsoft Office Visio

2010(以下简称 Visio 2010),它有 3个独立的版本,即 Office Visio Standard(标准版)、Office Visio Professional(专业版)和 Office Visio Premium(高级版)。专业版除了拥有标准版的全部功能外,还允许用

户将图表连接和发布到 Visio Services上,通过 Visio Services可以在 SharePoint中浏览最新更新数据图表;专业版还包括高级图表模板。高级版拥有专业版的全

部功能,并新增高级进程管理等额外功能,同时高级

版整合了 SharePoint Server 2010。 Visio 2010 提供了非常丰富的图表模板和形状,

有些很简单,有些则相当复杂。每个模板都有不同的

用途,从管线规划到计算机网络,多种多样。如图 1-31所示为 Visio 2010的模板类别选择界面。

图 1-30 模具文件与绘图文件

软件工程——理论与实践

30

图 1-31 Visio 2010模板类别选择界面

下面详细介绍 Visio 2010中的模板文件。 (1)“常规”模板包括基本框图和具有透视效果的框图。 (2)“地图和平面布置图”模板包括 HVAC 规划、HVAC 控制逻辑图、安全和门禁平面图、

办公室布局、三维方向图和现场平面图等。 (3)“工程”模板包括部件和组件绘图、工艺流程图、电路和逻辑电路、系统、管道和仪表设

备图等。 (4)“流程图”模板包括 BPMN图、Microsoft SharePoint工作流、工作流程图、基本流程图、

跨职能流程图、IDEF0图表和 SDL图(见图 1-32)。

图 1-32 “流程图”模板

(5)“日程安排”模板包括 PERT图表、甘特图、日程表和日历(见图 1-33)。

第 1章 软件工程概述

31

图 1-33 “日程安排”模板

(6)“软件和数据库”模板包括 COM和 OLE、UML模型图、程序结构、企业应用、数据库模型图、数据流模型图、数据流图标、网站图、网站总体设计和线框图表等(见图 1-34)。

图 1-34 “软件和数据库”模板

(7)“商务”模板包括数据透视图表、组织结构图、故障树分析图、审计图和营销图表等。 (8)“网络”模板包括基本网络图、网站图、详细网络图和机架图等。 创建了特定的模板文件后,就进入了应用程序的绘图环境。绘图环境包括多项组成元素,比

如标题栏、菜单栏、工具栏、绘图页面、页面标签、状态栏、模具、绘图文件(图件)、控制按钮、

软件工程——理论与实践

32

标尺、网格和滚动条等。Visio 2010应用程序的绘图环境如图 1-35所示。

控制按钮

标尺

网格

绘图页面

菜单栏 工具栏

模具

图件

标题栏

页面标签 状态栏

滚动条

图 1-35 Visio 2010的绘图环境

下面以创建一个简单的绘图文件为例,介绍 Visio 2010的基本用法。 (1)打开 Visio 2010,会出现如图 1-31所示的界面,可以在此界面选择模板类型。 (2)选择“常规”,出现如图 1-36所示的界面。

图 1-36 选择模板

这一界面右侧会出现对框图模板的介绍。选择“框图”,单击“创建”,就会进入 Visio 2010的工作窗口,如图 1-37所示。 工作窗口的最上面一行是菜单,菜单的下面是工具栏。窗口左侧是各种模具及每种模具包含

的形状。模具是存放各种形状的仓库,比如模具“方块”下存放了“框”、“菱形”和“圆形”等

第 1章 软件工程概述

33

形状;窗口的右侧是布满网格的绘图窗口,其左侧和上方有标尺。

图 1-37 工作窗口环境

(3)对形状进行操作。Visio 支持“拖曳式绘图”,可在左侧的窗口中选择某种形状,直接用鼠标把它拖放到绘图窗口上。双击绘图窗口上的形状可以添加文本,拖曳鼠标还可以调整形状的

大小,如图 1-38所示。

图 1-38 调整形状大小

若要对形状进行编辑,可以用鼠标右键单击所绘的形状,如图 1-39所示。

软件工程——理论与实践

34

图 1-39 编辑形状

若想改变形状的角度,可以选中图形,点中圆形操作柄拖动即可。也可以选择菜单“开始”→

“排列”→“位置”→“方向形状”→“旋转形状”,使用操作即可,如图 1-40所示。

图 1-40 改变形状的角度 图 1-41 对齐形状

当绘图窗口中有多个形状时,若想对齐形状,可以先选择要对齐的形状,然后选择菜单栏中

的“开始”→“排列”→“位置”→“对齐形状”,会出现如图 1-41 所示的窗口,选择相应的对齐方式即可。 (4)连接形状。先选中(激活)菜单“开始”→“工具”→“连接线”,然后选中要进行连接

的形状,点中出现的操作连接点,拖动到目标图形的操作连接点即可,如图 1-42所示。

第 1章 软件工程概述

35

(5)绘制完图形后将其保存即可。有疑问的地方可以查看菜单栏中的“帮助”。

图 1-42 连接形状

1.9 Rose 的功能及使用方法介绍

Rational Rose(以下简称 Rose)是一种基于 UML的可视化的建模工具,它是由 IBM公司开发的产品。Rose最后的版本是 Rational Rose 2003,之后由一系列 Java平台支持的建模工具取代,如 Rational Software Architect、Rational Software Modeler和 Rational Rhapsody等。使用 Rose可以完成 UML 建模过程中所使用的多种模型和框图,如用例图、包图、类图、顺序图、活动图和状态机图等。同时通过对多种程序设计语言(如 C++、Java、VB 等)的集成,Rose 还可以根据现有的模型帮助开发人员产生框架代码。 启动 Rose后,选择所要建立的模型的模板,进入如图 1-43所示的系统主界面。 在主界面的工作环境中,各种元素的功能介绍如下。 (1)浏览器是一个控件窗口,显示系统的 4种视图及模型属性。这 4种视图分别是用例视图

(Use Case View)、逻辑视图(Logical View)、组件视图(Component View)和部署视图(Deployment View),如图 1-44所示。其中,用例视图主要从用例一级建立系统的高层模型,它并不关注系统的具体实现细节,而是从业务领域来描述系统;逻辑视图从类或对象一级建立系统的实现模型,

它详细地描述了系统的实现过程;组件视图主要是用来表示系统的各个模块、连接库和文件之间

的关系;部署视图更加关注系统在物理部署上的相关内容。 (2)文档窗口用于记录模型中各种元素的说明性文字。用户可在文档窗口中对各个模型元素

进行详细的文档注释。当在编辑区选择某个建模元素时,文档窗口会自动显示所选元素的文档

注释。 (3)编辑区用于显示和编辑多个 UML视图。

拖动到目标形状上

软件工程——理论与实践

36

工具栏

文档窗口

编辑区

日志窗口

浏览器

图 1-43 Rose的主界面

(4)工具栏中显示了相关工具的图标。 (5)日志窗口记录了用户的某些操作信息,如图 1-43所示。用户可以通过日志窗口查看错误

信息。 Rose中的基本操作包括对模型的操作、对框图的操作及对元素的操作。要创建一个新的模型,

可以在菜单栏中选择“File”→“New”,然后在弹出的对话框中选择相应的模型,如图 1-45所示。

用例视图

逻辑视图

组件视图

部署视图

图 1-44 浏览器 图 1-45 创建模型

创建好的模型包含 4种视图:用例视图、逻辑视图、组件视图和部署视图。每种视图中又包含有多种框图。每种视图下所包含的元素和框图见表 1-1。

第 1章 软件工程概述

37

表 1-1 视图包含的元素及框图

视 图 元 素 框 图

用例视图

用例

操作者

用例图

类图

协作图

顺序图

活动图

状态机图

逻辑视图

用例

接口

用例图

类图

协作图

顺序图

活动图

状态机图

组件视图 包

组件 组件图

部署视图 处理器

设备

创建好模型后,就可以在该模型下创建框图了。用鼠标右键单击某视图,选择“New”及相

应的框图即可,如图 1-46所示。

图 1-46 创建框图

创建好框图后,就可以在该框图下添加模型元素了。不同的框图包含的模型元素的种类也不

同。比较方便的是,编辑区左侧的工具栏里显示了当前框图所支持的模型元素。如果创建了一个

用例图,那么工具栏的状态如图 1-47所示。如果创建了一个顺序图,那么工具栏的状态如图 1-48所示。 在编辑区中添加元素时,可以先在编辑区左侧的工具栏中选择相应的元素,然后在框图中选

软件工程——理论与实践

38

定恰当的位置,单击鼠标即可。 要删除模型元素或框图,在浏览器中选中相应的元素或框图,右键单击鼠标,选择“Delete”

即可,如图 1-49所示。

图 1-47 用例图对应的工具栏

图 1-48 顺序图对应的工具栏

当整个模型创建完成后,可以把它发布到 Web 页面上。例如,已经完成了如图 1-50 所示的一张简单用例图(它保存在用例视图下),在主界面的菜单栏上选择“Tools”→“Web Publisher”,弹出如图 1-51所示的对话框。

图 1-49 删除元素或框图 图 1-50 示例用例图

第 1章 软件工程概述

39

图 1-51 发布文件对话框

选择要发布的内容及文件路径后,单击“Publish”按钮,发布成功后,在设定的路径下打开*/root.html文件,就会得到如图 1-52所示的视图。

图 1-52 */root.html文件

在视图左侧的“Display documentation”下选择先前所绘制的用例图,就会得到如图 1-53 所示的结果。

软件工程——理论与实践

40

双击用例图的构成元素,还可以得到对相应元素的详细描述,如图 1-54所示。

图 1-53 用例图

图 1-54 对元素的详细描述

第 1章 软件工程概述

41

小 结

本章主要介绍了与软件工程相关的基本概念,同时还重点介绍了软件工程的基本内容和典型

的软件开发模型。 软件由计算机程序、数据和软件文档 3部分组成,是人类智力劳动的产物,具有抽象性和可

复用性,且没有老化和磨损的现象。此外,软件的运行需要依赖于一定的硬件环境。 软件危机爆发于 20世纪 60年代中期,它的出现严重影响了软件产业的发展。软件工程是解

决软件危机的方法。软件工程是一门应用计算机科学技术、数学和管理学的原理,运用工程科学

的理论、方法和技术,研究和指导软件开发和演化的交叉学科。著名的软件工程专家 B. W. Boehm提出了 7条软件工程的基本原则。 软件的生命周期是指软件产品从构想到被市场淘汰所经历的全过程。对软件生命周期的划分

必须依据特定的软件开发项目所采用的软件开发模型。传统的软件产品的生命周期一般可以划分

为 6个阶段:可行性研究、需求分析、软件设计、编码、软件测试和软件维护。 软件开发模型是软件工程思想的具体化,它反映了软件在其生命周期中各阶段之间的衔接和

过渡关系以及软件开发的组织方式,是人们在软件开发实践中总结出来的软件开发方法和步骤。

典型的软件开发模型有瀑布模型,演化模型(包括原型模型、增量模型、螺旋模型),喷泉模型,

形式化方法模型,基于组件的开发模型,统一软件开发过程模型和敏捷模型。瀑布模型是线性的

回溯性较差的开发模型,它的阶段性强,易于对项目进行管理,但是它的开发过程不灵活,不能

适应环境的变化。原型模型可以帮助开发人员充分挖掘需求,并对技术的可行性进行研究。增量

模型把待开发的软件系统看成是一个个的增量组件,从而分批次地实现和交付各个增量。螺旋模

型将风险分析的机制扩展到了各个阶段的活动中,可以有效地降低软件开发的风险,但是这种模

型可操作性不强。喷泉模型具有无间隙性,并具有面向对象的迭代性。形式化方法模型常用于对

安全、可靠和保密性高的系统开发中,但实施难度也比较大。基于组件的开发模型实现了软件的

复用,是比较流行的一种开发模型。统一软件开发过程模型是面向对象软件开发模型,它基于迭

代的思想,适用范围极其广泛。敏捷模型是一种轻量级的软件开发过程,它支持软件产品的快速

开发,能够很快地适应软件开发周期中的各种变化。极限编程是敏捷模型的一种典型应用,特别

适用于小组织和需求不定并有用户紧密参与的情况(如小型系统和实验性课题),但高可靠性要求

和大型项目不宜采用。 本章还介绍了软件工程的相关工具、软件工程的常用信息源、Visio 的功能及使用方法以及

Rose的功能及使用方法。

习 题

1.与计算机硬件相比,计算机软件有哪些特点? 2.为什么说软件工程的发展可以在一定程度上解决软件危机的各种弊端? 3.请简述软件工程的基本原则。 4.如何理解软件生命周期的内在特征?

软件工程——理论与实践

42

5.请对比瀑布模型、原型模型、增量模型和螺旋模型。 6.在统一软件开发过程模型中,核心工作流程包含哪些? 7.与本课程学习相关的常用网络资源提供了哪些与软件工程相关的信息?除了书中提到的资

源以外,你还知道哪些? 8.请列举与软件工程相关的自动化工具。

第2章 可行性研究及需求分析 本章目标 ● 了解可行性研究的目的与意义。 ● 熟悉可行性研究的内容和步骤。 ● 掌握需求分析的步骤。 ● 熟悉获取需求的常用方法。 ● 理解结构化需求分析方法的基本思想。 ● 掌握数据流图、E-R 图的绘制方法和数据字典的用法。 ● 理解面向对象的基本思想及面向对象的软件工程方法的特征。 ● 掌握面向对象需求分析的内涵。 ● 熟悉 UML 的意义。 ● 掌握利用 Visio 绘制数据流图的方法。 ● 掌握利用 Rose 创建用例模型的方法。

2.1 可行性研究

可行性研究是项目开发之前的重要阶段。为了避免盲目的软件开发,相关人员需要对开发特

定软件项目的可行性进行研究,结合资金、时间和环境等各方面的制约条件,对该软件产品是否

能够解决存在的问题,是否能够带来预期的效果和价值等做出评估。

2.1.1 可行性研究的目的与意义

可行性研究的目的不在于提出解决问题的方案,而在于研究解决问题的必要性和可能性。 在软件开发实践中,由于软件开发人员或用户对市场的了解不充分,对技术的把握不成熟,

对进行开发的各项风险估计不足等因素,许多问题都不能在预期的时间范围内或资源限制下得到

解决。如果开发人员能够尽早预知存在的问题没有合理的解决方案,那么尽早停止项目的开发就

能够避免时间、资金、人力和物力的浪费。

2.1.2 可行性研究的内容

可行性研究主要是从技术、经济和社会 3个方面对软件项目的可行性进行分析,如图 2-1所示。

43

软件工程——理论与实践

技术可行性研究是对技术解决方案的实用性、技术资源的可用性和设备条件做出评估。概括

地说就是要回答使用现有的技术资源是否能实现待开发的软件系统

的问题。其研究内容一般包括风险分析、资源分析和技术分析。

图 2-1 可行性研究

经济可行性研究要对项目的开发总成本与开发系统将带来的经济

效益之间的差值进行度量,从经济的角度去判断是否值得为软件开

发项目进行投资。经济可行性研究也叫做成本效益分析,简单地说,

只有开发系统的总成本小于将来系统投入使用后带来的总收益的软

件开发项目才值得进行下去。经济可行性研究的研究内容包括以下

几项。 (1)成本。支出的资金成本涉及硬件资源的支出(计算机购置和网络环境的搭建等),软件资

源的支出(操作系统、支持软件和应用软件的购置与安装),办公必需品的支出等。 (2)收益。包括开支的减少、效率的改进、客户的增多等。 (3)收益/投资比。 (4)投资回收周期。 (5)敏感度分析。

社会可行性研究从政策、法律和制度等社会因素方面考虑项目开发的合理性和意义。比如,项目是

否与现行的某些国家政策相背离,是否会违反某些法律法规,是否不符合社会的伦理道德等。

2.1.3 可行性研究的步骤

典型的可行性研究的步骤如图 2-2所示。

图 2-2 可行性研究的步骤

1.确定系统的目标

系统分析人员要详细地阅读各种相关资料,并对用户和市场进行

调查,从而确认目标系统要完成的任务。同时,还要明确进行项目开

发时的一切限制和约束以及可以使用的各种资源。 2.分析研究正在运行的系统

对现有系统功能特点的充分了解是成功开发新系统的前提。对现

有系统的研究包括阅读和分析各种文档资料,观察系统的运行状况和

实地操作系统,收集和分析用户对现有系统的意见等。可以说,现有

系统是开发目标系统时重要的信息来源。 3.设计新系统的高层逻辑模型

一般来说,新系统应该完成现有系统的功能,并对现有系统中

存在的问题进行改善或修复。在分析研究了现有系统的基础上就可

以大体把握新系统的功能和结构,然后从较高层次上建立新系统的

逻辑模型。 4.提出可行的解决方案并对其进行评估和比较

基于新系统的高层逻辑模型,系统分析人员可以从技术的角度提出多种解决方案,并从经济、

社会和技术等多个方面对各种解决方案进行比较和评估。 5.选择合适的解决方案

在上述研究的基础上,回答该软件产品是否能够解决存在的问题,是否能够带来预期的效果

和价值的问题。如果该软件开发项目没有必要性和可能性,则应立即停止,并给出详细的理由。

44

第 2 章 可行性研究及需求分析

如果有开发该软件产品的必要性和可能性,那么应该从上述的多个解决方案中选取出最合适、最

可行的解决方案,列举出选择该方案的原因,从经济可行性、社会可行性和技术可行性 3个方面对该方案进行可行性研究。

6.撰写可行性研究报告

可行性研究报告是可行性研究阶段的输出文档,应该包括的内容有项目背景、管理概要、候

选方案、系统描述、经济可行性分析、社会可行性分析、技术可行性分析及可行性研究的结论等。 可行性研究的结论一般有 3种。 (1)可以按计划进行软件项目的开发。 (2)需要解决某些存在的问题(如资金短缺、设备陈旧和开发人员短缺等)或者需要对现有

的解决方案进行一些调整或改善后才能进行软件项目的开发。 (3)待开发的软件项目不具有可行性,应立即停止该软件项目。 上述可行性研究的步骤只是一个经过长期实践总结出来的框架,在实际的使用过程中,它不

是固定的,根据项目的性质、特点以及开发团队对业务领域的熟悉程度会有些变化。

2.2 需 求 分 析

需求分析是在可行性研究的基础上,将用户对系统的描述通过开发人员的分析概括抽象为完

整的需求定义,再形成一系列文档的过程。可行性研究旨在评估目标系统是否值得去开发,问题

是否能够解决,而需求分析旨在回答“系统做什么”的问题,确保将来开发出来的软件产品能够

真正满足用户的需要。 构建一个软件系统最困难的工作是确定构建什么。其他任何工作都不会像这部分工作那样,

在出错之后会如此严重地影响随后实现的系统,并且在以后修补竟会如此的困难。 —Frederick P. Brooks, Jr.

2.2.1 需求分析的目的与意义

需求分析是一个非常重要的过程,它完成的好坏直接影响后续软件开发的质量。一般情况下,

用户并不熟悉计算机的相关知识,而软件开发人员对相关的业务领域也不甚了解,用户与开发人

员之间对同一问题理解的差异和习惯用语的不同往往会为需求分析带来很大的困难。所以,开发

人员和用户之间充分和有效的沟通在需求分析的过程中至关重要。 有效的需求分析通常都具有一定的难度,一方面是因为交流存在障碍,另一方面是因为用户

通常对需求的陈述不完备、不准确和不全面,并且还可能不断地变化。开发人员不仅需要在用户

的帮助下抽象现有的需求,还需要挖掘隐藏的需求。此外,把各项需求抽象为目标系统的高层逻

辑模型对日后的开发工作也至关重要。合理的高层逻辑模型是系统设计的前提。 在进行需求分析的过程中,首先要明确需求分析应该是一个迭代的过程。由于市场环境的易

变性以及用户本身对于需求描述的模糊性,需求往往很难一步到位。需求分析不仅仅是属于软件

开发生命周期早期的一项工作,而且还应该贯穿于整个生命周期中,它应该随着项目的深入而不

断地变化。 此外,为了方便后续的评审和测试等工作,需求的描述应该尽量做到具体、详细、可以测量

45

软件工程——理论与实践

和可以实现,并且基于时间。

2.2.2 需求分析的步骤

遵循科学的需求分析步骤可以使需求分析工作更高效。需求分析的一般步骤如图 2-3所示。 需求涉及的方面有很多。

图 2-3 需求分析的步骤

(1)在功能方面,需求包括系统要做什么,相对于原系统,目标系统需要进行哪些修改,目标用户有哪些,不同用户需要通过系统完成何

种操作等。 (2)在性能方面,需求包括用户对于系统执行速度、响应时间、吞

吐量和并发度等指标的要求。 (3)在运行环境方面,需求包括目标系统对于网络设置、硬件设备、

温度和湿度等周围环境的要求以及对操作系统、数据库和浏览器等软件

配置的要求。 (4)在界面方面,需求涉及数据的输入/输出格式的限制及方式、数

据的存储介质和显示器的分辨率要求等问题。 1.获取需求,识别问题

开发人员从功能、性能、界面和运行环境等多个方面识别目标系统要解决哪些问题,要满足

哪些限制条件,这个过程就是对需求的获取。开发人员要通过调查研究,理解当前系统的工作模

型和用户对新系统的设想与要求。 此外,在获取需求时,还要明确用户对系统的安全性、可移植性和容错能力等其他要求。比

如,多长时间需要对系统做一次备份,系统对运行的操作系统平台有何要求,发生错误后重启系

统允许的最长时间是多少等。 遗漏需求是最难修订的需求错误。

—Robert L. Glass 获取需求是需求分析的基础。为了能有效地获取需求,开发人员应该采取科学的需求获取方

法。在实践中,获取需求的方法有很多种,比如,问卷调查、访谈、实地操作、建立原型和研究

资料等。 问卷调查法是采用调查问卷的形式来进行需求分析的一种方法。通过对用户填写的调查问卷

进行汇总、统计和分析,开发人员便可以得到一些有用的信息。采用这种方法时,调查问卷的设

计很重要。一般在设计调查问卷时,要合理地控制开放式问题和封闭式问题的比例。 (1)开放式问题的回答不受限制,自由灵活,能够激发用户的思维,使他们能尽可能地阐述自

己的真实想法。但是,对开放式问题进行汇总和分析的工作会比较复杂。 (2)封闭式问题的答案是预先设定的,用户从若干答案中进行选择。封闭式问题便于对问卷信

息进行归纳与整理,但是会限制用户的思维。 访谈通过开发人员与特定的用户代表进行座谈,进而了解到用户的意见,是最直接的需求获

取方法。为了使访谈有效,在进行访谈之前,开发人员要首先确定访谈的目的,进而准备一个问

题列表,预先准备好希望通过访谈解决的问题。在访谈的过程中,开发人员要注意态度诚恳,并

保持虚心求教的姿态,同时还要对重点问题进行深入的讨论。由于被访谈的用户身份可能多种多

样,开发人员要根据用户的身份特点进行提问,给予启发。当然,进行详细的记录也是访谈过程

46

第 2 章 可行性研究及需求分析

中必不可少的工作。访谈完成后,开发人员要对访谈的收获进行总结,澄清已解决的和有待进一

步解决的问题。 关注用户的行为而不是他们的言语。

—Jakob Nielsen 为了深入地了解用户需求,有时候开发人员还会以用户的身份直接参与到现有系统的使用过

程中,在亲身实践的基础上,更直接地体会现有系统的弊端以及新系统应该解决的问题,这种需

求获取方法就是实地操作。通过实地操作得到的信息会更加准确和真实,但是这种方法会比较费

时间。 当用户本身对需求的了解不太清晰的时候,开发人员通常采用建立原型系统的方法对用户需

求进行挖掘。原型系统就是目标系统的一个可操作的模型。在初步获取需求后,开发人员会快速

地开发一个原型系统。通过对原型系统进行模拟操作,开发人员能及时获得用户的意见,从而对

需求进行明确。利用原型系统获取需求的方法示意图如图 2-4所示。

图 2-4 利用原型系统获取需求

2.分析需求,建立目标系统的逻辑模型

在获得需求后,开发人员应该对问题进行分析抽象,并在此基础上从高层建立目标系统的逻

辑模型。模型是对事物高层次的抽象,通常由一组符号和组织这些符号的规则组成。常用的模型

图有数据流图、E-R 图、用例图和状态转换图等,不同的模型从不同的角度或不同的侧重点描述目标系统。绘制模型图的过程,既是开发人员进行逻辑思考的过程,也是开发人员更进一步认识

目标系统的过程。 3.将需求文档化

获得需求后要将其描述出来,即将需求文档化。对于大型的软件系统,需求阶段一般会输出

3个文档: (1)系统定义文档(用户需求报告); (2)系统需求文档(系统需求规格说明书); (3)软件需求文档(软件需求规格说明书)。 对于简单的软件系统而言,需求阶段只需要输出软件需求文档(即软件需求规格说明书)就

可以了。软件需求规格说明书主要描述软件的需求,从开发人员的角度对目标系统的业务模型、

功能模型和数据模型等内容进行描述。作为后续的软件设计和测试的重要依据,需求阶段的输出

47

软件工程——理论与实践

文档应该具有清晰性、无二义性和准确性,并且能够全面和确切地描述用户需求。 4.需求验证

需求验证是对需求分析的成果进行评估和验证的过程。为了确保需求分析的正确性、一致性、

完整性和有效性,提高软件开发的效率,为后续的软件开发做好准备,需求验证的工作非常必要。 在需求验证的过程中,可以对需求阶段的输出文档进行多种检查,比如,一致性检查、完整

性检查和有效性检查等。同时,需求评审也是在这个阶段进行的。

2.3 结构化需求分析的方法

结构化需求分析是 20世纪 70年代由 Yourdon、Constaintine及 DeMarco提出的一种面向数据流的需求分析方法。它基于“分解”和“抽象”的基本思想,逐步建立目标系统的逻辑模型,进

而描绘出满足用户要求的软件系统。 “分解”是指对于一个复杂的系统,为

了将复杂性降低到可以掌握的程度,可以

把大问题分解为若干个小问题,然后再分

别解决。如图 2-5所示演示了对目标系统 X进行自顶向下逐层分解的示意图。 最顶层描述了整个目标系统,中间层将

目标系统划分为若干个模块,每个模块完成

一定的功能,而最底层是对每个模块实现方

法的细节性描述。可见,在逐层分解的过程中,起初并不考虑细节性的问题,而是先关注问题最

本质的属性,随着分解自顶向下进行,才逐渐考虑越来越具体的细节。这种用最本质的属性表示

一个软件系统的方法就是“抽象”。

图 2-5 自顶向下逐层分解

X

抽象是一种人类处理复杂问题的基本方法。

—Grady Booch 分解和抽象是结构化需求分析的基本指导思想。在结构化需求分析的过程中,通常还需要借

助数据流图、数据字典、E-R 图、结构化语言、判定表、判定树等工具。接下来我们介绍数据流图、数据字典和 E-R图的相关知识。

2.4 结构化需求分析的工具

2.4.1 数据流图

数据流图(Data Flow Diagram,DFD)是描述系统中数据流的图形工具,是一种用来表示信息流和信息变换过程的图解方法,可以标识一个系统的逻辑输入和逻辑输出以及把逻辑输入转换为逻

辑输出所需的加工处理。数据流图把软件系统看成是由数据流联系的各种功能的组合,在需求分

析的过程中,可以用来建立目标系统的逻辑模型。

48

第 2 章 可行性研究及需求分析

结构化需求分析采用的是“自顶向下,由外到内,逐层分解”的思想,开发人员要先画出系

统顶层的数据流图,然后再逐层画出底层的数据流图。顶层的数据流图要定义系统范围,并描述

系统与外界的数据联系,它是对系统架构的高度概括和抽象。底层的数据流图是对系统某个部分

的精细描述。 数据流图的目的是在用户和系统开发人员之间提供语义的桥梁。

—Kenneth Kozar 按照 Gane-Sarson法,在绘制数据流图的过程中主要用到了 4个基本符号,见表 2-1。

表 2-1 数据流图的基本符号

名 称 符 号 含 义

信息源

表示数据的源点或终点,它是系统之外的实体,可以是人、物或者其他系统

加工

表示对数据进行加工或处理,比如对数据的算法分析和科学计算

数据存储 表示输入或输出文件。这些文件可以是计算机系统中的外部或内部文件,也

可以是表和账单等

数据流 表示数据流的流动方向。数据流可以从加工流向加工,从加工流向文件,或

者从文件流向加工 为了对数据流图有更直观的认识,我们以一个考试成绩管理系统为例,介绍它的数据流图。

某单位进行招聘考试,应聘者报名后,单位的招聘委员会将每位应聘者的基本情况输入系统。招

聘考试结束后,招聘委员会需要将应聘者的成绩输入系统,并按照成绩对应聘者进行排序,将成

绩单发放给每位应聘者,并发放录用通知书。该考试成绩管理系统顶层和底层的数据流图分别如

图 2-6和图 2-7所示。

图 2-6 考试成绩管理系统顶层数据流图

图 2-7 考试成绩管理系统底层数据流图

在绘制数据流图的过程中,要注意以下几点。 (1)数据的处理不一定是一个程序或一个模块,也可以是一个连贯的处理过程。 (2)数据存储是指输入或输出文件,但它不仅仅可以是文件,还可以是数据项或用来组织数

据的中间数据。 (3)数据流和数据存储是不同状态的数据。数据流是处于流动状态的数据,而数据存储是处

49

软件工程——理论与实践

于静止状态的数据。 (4)当目标系统的规模较大时,为了描述的清晰和易于理解,通常采用逐层分解的方法,画

出分层的数据流图。在分解时,要考虑到自然性、均匀性和分解度几个概念。 自然性是指概念上要合理和清晰。 均匀性是指尽量将一个大问题分解为规模均匀的若干部分。 分解度是指分解的维度,一般每一个加工每次分解最多不宜超过 7个子加工,应分解到基

本的加工为止。 (5)数据流图分层细化时必须保持信息的连续性,即细化前后对应功能的输入和输出数据必

须相同。 关于数据流图的详细绘制方法,本章的实践部分会详细介绍。

2.4.2 数据字典

用数据流图来表示系统的逻辑模型直观且形象,但是缺乏细节描述,也就是说它没有准确和

完整地定义各个图元。可以用数据字典(Data Dictionary,DD)来对数据流图做出补充和完善。 数据字典用于定义数据流图中各个图元的具体内容,为数据流图中出现的图形元素做出确切

的解释。数据字典包含 4类条目:数据流、数据存储、数据项和数据加工。这些条目按照一定的规则组织起来便构成了数据字典。定义规则时,常用的符号见表 2-2。

表 2-2 数据字典符号

符 号 含 义 示 例

= 被定义为

+ 与 X=a+b表示 X由 a和 b组成

[⋯|⋯] 或 X=[a | b]表示 X由 a或 b组成

m{⋯}n或 { }n

m⋅ ⋅ ⋅ 重复 X= 2{a}6或 { } 表示重复 2~6次 a 6

2a

{⋯} 重复 X={a}表示 X由 0个或多个 a组成

(⋯) 可选 X=(a)表示 a在 X中可能出现,也可能不出现

“⋯” 基本数据元素 X=“a”表示 X是取值为字符 a的数据元素

.. 连接符 X=1..9表示 X可取 1到 9中的任意一个值 例如,数据流“应聘者名单”由若干应聘者的姓名、性别、年龄、专业和联系电话等信息组

成,那么“应聘者名单”可以表示为:应聘者名单={应聘者姓名+性别+年龄+专业+联系电话}。数据项考试成绩可以表示为:考试成绩 =0..100。再如,某教务系统的学生成绩库文件的数据字典描述可以表示为以下形式。 文件名:学生成绩库 记录定义:学生成绩 = 学号+姓名+{课程代码+成绩+[必修|选修]} 学号:由 6 位数字组成

姓名:2~4 个汉字 课程代码:8 位字符串

成绩:1~3 位十进制整数 文件组织:以学号为关键字递增排列

50

第 2 章 可行性研究及需求分析

2.4.3 E-R 图

E-R图用于描述应用系统的概念结构数据模型,它是进行需求分析并归纳、整理、表达和优化现实世界中数据及其联系的重要工具。

在建模的过程中,E-R图以实体、联系和属性 3个基本概念概括数据的基本结构。 实体就是现实世界中的事物,多用矩形框来表示,框内含有相应的实体名

称。比如,在一个教务系统中,“学生”就是一个实体,如图 2-8所示。 属性多用椭圆形表示,并用无向边与相应的实体联系起来,表示该属性归

某实体所有。可以说,实体是由若干个属性组成的,每个属

性都代表了实体的某些特征。学生实体的属性如图 2-9所示。

图 2-8 学生实体

图 2-9 学生实体的属性

联系用菱形表示,并用无向边分别与有关实体连接起来,以

此描述实体之间的关系。实体之间存在着 3种联系类型,分别是一对一、一对多和多对多,它们反映到E-R图中就为相应的联系类型,即 1:1、1:n和m:n。 (1)一对一联系是指甲实体的任何一个实例只能对应到乙

实体的一个实例,并且乙实体的任何一个实例只能对应到甲实

体的一个实例。例如,在一个座位分配系统中,“学生”实体和

“座位”实体之间的关系就是一对一的,如图 2-10所示。 (2)一对多联系是指甲实体的任何一个实例能够对应到乙实体的多个实例,而乙实体的任何一个

实例只能对应到甲实体的一个实例。例如,在一个住宿管理系统中,一个“学生”只能分配到一间“宿

舍”,而一间“宿舍”可以容纳多个“学生”,如图 2-11所示。

图 2-10 一对一联系 图 2-11 一对多联系

(3)多对多联系是指甲实体的任何一个实例能够对应到乙实体的若干个实例,而乙实体的任何一个实例也可以对应到甲实体的若干个实例。例如,在一个选课系统中,一个“学生”可以选

修若干门“课程”,同时一门“课程”也可以被若干个“学生”选修,如图 2-12所示。

图 2-12 多对多联系

需要指出的是,同一个系统的 E-R图不具有唯一性,即不同的软件开发人员所设计出来的 E-R图可能不同。

2.5 面向对象的软件工程方法

2.5.1 面向对象的基本概念

近年来,为了克服传统软件工程方法存在的复用性和可维护性差以及难以满足用户需要等缺

51

软件工程——理论与实践

点,面向对象的思想越来越受到人们的欢迎和重视。面向对象的思想提倡运用人类的思维方式,

从现实世界中存在的事物出发来构造软件。它建立在“对象”概念的基础上,以对象为中心,以

类和继承为构造机制来设计和构造相应的软件系统。 面向对象的基本思想最先体现在面向对象程序设计语言中,然后才逐渐形成了面向对象的分析

和设计方法。20世纪 60年代开发的 Simula 67语言首次提出了对象的概念,它是第一个面向对象程序设计语言。Ada语言是在 20世纪 70年代出现的又一种支持数据抽象的基于对象概念的程序设计语言。最具有代表性和影响力的面向对象程序设计语言是由美国 Xerox(施乐)公司 Palo Alto研究中心的 Alan Kay开发的 Smalltalk语言。Smalltalk全面实现了面向对象技术的机制,丰富了面向对象的概念,它的发布引起了人们对面向对象概念的广泛关注。随后产生了多种面向对象程序设计

语言,如 C++和 Java等,同时,面向对象的分析和设计方法也被广泛应用于软件开发中。比较具有代表性的基于面向对象思想的软件开发方法有 Grady Booch提出的面向对象的分析与设计方法论、Jim Rumbaugh提出的面向对象的建模技术和 Zvar Jacobson提出的面向对象的软件工程方法学等。

Alan Kay

2003年,Alan Kay因在面向对象程序设计上的杰出贡献,成为图灵奖的得主。Alan Kay于 1970年加入 Xerox(施乐)公司的 Palo Alto研究中心。20世纪 70年代初期,Alan Kay等人开发了最具代表性和影响力的面向对象语言 Smalltalk,因此被誉为“Smalltalk之父”。

Alan Kay 不但是面向对象编程语言 Smalltalk 的发明人之一,也是面向对象编程思想的创始人之一。他是笔记本电脑最早的构想者,同时也是

现代Windows GUI的架构师。Alan Key可谓是计算机领域的大师。 相对于传统的软件工程思想而言,面向对象的思想更符合人类的思维逻辑,它淡化了计算机

的观点,以现实世界中的模型作为构造软件系统的依据。面向对象的基本概念包括对象、类、封

装、继承和多态,下面一一介绍。 1.对象

对象可以是客观世界中存在的事物,也可以是概念化的实体,它由一组属性和操作组成。属性是

用来描述对象静态特征的数据项,是对客观世界实体所具有性质的抽象。操作是用来描述对象的

动态特征。例如,把人当成一个对象,那么他的属性就有身高、体重、姓名和年龄等静态特征,

他的操作就包括工作、学习、吃饭和运动等;把汽车当成一个对象,那么它的属性就有品牌、颜

色、价格和寿命等,它的操作就包括加速、减速和刹车等。 理解对象的概念时,需要注意以下几点。

(1)对象的数据是封装起来的,对数据的处理需要通过特定的操作。 (2)对象之间通过传递消息进行通信,不同的对象独立地处理自身的数据。 (3)对象具有主动性。要处理对象的内部数据时,外界需要通过接口向对象发送消息,请求它执行特定的操作。

2.类

类是对对象的抽象,是对具有相同属性和相同操作的一组相似对象的定义。通常情况下,很多对象

都有相似的特征。例如,对于两个教师,他们虽然可能身高、体重、性别、年龄和籍贯等特征不同,

但是职业却是相同的;对于两把椅子,它们可能颜色、形状、价格和位置等特征不同,但是作用却

52

第 2 章 可行性研究及需求分析

是相同的。在这种情况下,我们就可以忽略事物的非本质特征,只注意那些与当前目标相关的本质

特征,从中找出事物的共性,把本质特征相同的事物划分为一类,即将多个对象抽象为类。 对于同类对象,它们具有相同的属性和操作,但是每个对象的属性值可能不同,执行操作的

结果也可能不同。例如,在教务管理系统中,可以定义“学生”类,并定义编号、姓名和院系等

属性及登录该系统进行操作。每位学生都有自己特定的编号、姓名和院系等属性值,并且执行登

录操作后,都会进入个性化的主页。 谈到类的概念,就必须知道什么是类的实例。实例是由某个特定的类描述的一个具体的对象。

例如,对于“教师”类,某位教师“王一”就是类的一个实例;对于“学生”类,某位学生“李

二”就是该类的一个实例。 3.封装

封装是指把对象的属性和操作结合在一起,组成一个独立的单元。封装强调两个概念,即独立和

封闭。 (1)独立是指对象是一个不可分割的整体,它集成了事物全部的属性和操作,并且它的存在不

依赖于外部事物。 (2)封闭是指与外部的事物通信时,对象要尽量地隐藏其内部的实现细节,它的内部信息对外

界来说是隐蔽的,外界不能直接访问对象的内部信息,而只能通过有限的接口与对象发生联系。 可以说,类是数据封装的工具,而对象是封装的实现。类的成员又分为公有成员、私有成员

和保护成员,它们分别有不同的访问控制机制。封装是软件模块化思想的重要体现。 4.继承

继承表示类之间的层次关系,它使得某类对象可以自动拥有另外一个或多个对象的全部属性和操

作。比如,某系统已经定义了一个学生类,现在还需要定义一个研究生类。由于研究生也属于学

生的一种,它具有学生所有的一切属性和操作,这时就可以采用继承的方法,使研究生类直接获

得学生类的一切属性和操作。在这个系统中,研究生类就叫做子类或派生类,学生类就叫做父类或

基类。子类可以把父类定义的内容自动作为自己的部分内容,同时再加入新的内容。 继承可以分为单重继承和多重继承。

(1)单重继承是指一个子类只有一个父类。 (2)多重继承是指一个子类可以同时继承多个父类。 单重继承构成的类之间的关系是树状结构,多重继承构成的类之间的关系是网状结构。继承

简化了定义一个新类的过程,有利于人们对事物的认识和描述,达到了软件复用的目的。 5.多态

多态是一种使父类中定义的属性或操作被子类继承后,可以有不同的实现的机制。换句话说,多

态允许属于不同类的对象对同一消息做出不同的响应。当一个对象接收到进行某项操作的消息时,多

态机制将根据对象所属的类,动态地选用该类中定义的操作。比如,先定义一个父类“几何图形”,它

具有“计算面积”的操作,然后再定义一些子类,如“三角形”、“长方形”和“圆形”,它们可继承父

类“几何图形”的各种属性和操作,并且在各自的定义中要重新描述“计算面积”的操作。这样,当

有计算几何图形面积的消息发出时,对象会根据类的类型做出不同的响应,采用不同的面积计算公式。 多态这种机制极大地减少了软件设计中的冗余信息,提高了软件的可复用性和可扩展性。

2.5.2 面向对象的软件工程方法的特征与优势

自软件工程问世以来,出现了很多种软件工程的方法学。方法、工具和过程是软件工程方法

53

软件工程——理论与实践

学的 3个重要因素。 (1)方法是指为了完成软件开发的各项任务所采用的技术方法。 (2)工具是为方法的实行提供的自动或半自动的支持。 (3)过程是指为了获得高质量的软件产品所需要完成的一系列任务的框架。

知识小卡片 在软件工程领域,“方法学”是被广泛使用的一个词汇。在 20 世纪 70 年代,“方法学”一

词用于表示“开发软件产品的方式”,而该词实际上是指“方法的科学”。“方法学”应用于整个

软件工程的过程。 1.流行的软件工程方法

目前比较流行的软件工程方法包括面向过程的软件工程方法、面向数据的软件工程方法、面

向对象的软件工程方法和形式化的软件工程方法。 (1)面向过程的软件工程方法基于“自顶向下,逐步求精”的原则来完成软件开发各阶段的

任务。程序的执行过程主要由顺序、选择和循环等控制结构来控制。 (2)面向数据的软件工程方法中的数据是指元数据。元数据并不表示某一记录的具体信息,

而是用来将一些基础数据组织起来,即元数据是组织数据的数据。比如,信息系统中实体名及姓

名的集合或者数据库中物理表的表名及字段名的集合。这种方法与关系数据库联系紧密,特别适

合信息系统中数据层的设计与实现。 (3)面向对象的软件工程方法是当前最流行的软件工程方法,它主要有以下几个方面的特征。

把数据和操作封装在一起,形成对象。对象是构成软件系统的基本构件。 把特征相似的对象抽象为类。 类之间可以存在继承或被继承的关系,形成软件系统的层次结构。 对象之间通过发送消息进行通信。 将对象的私有信息封装起来。外界不能直接访问对象的内部信息,而必须是发送相应的消

息后,通过有限的接口来访问。 (4)形式化的软件工程方法基于严格的数学逻辑,多应用于对安全性和可靠性要求较高的特

殊领域。 2.面向对象的软件工程方法的优点

(1)符合人类的思维习惯。通常人类在认识客观世界的事物时,不仅会考虑到事物会有哪些属性,还会考虑到事物能完成哪些操作,也就是说静态的属性及动态的动作特征都是组成事物的一部

分,它们组合起来才能完整地表达一个事物。而面向对象的软件工程方法最重要的特点就是把事物的

属性和操作组成一个整体,以对象为核心,更符合人类的思维习惯。此外,面向对象的软件工程方法

更加注重人类在认识客观世界时循序渐进、逐步深化的特点。用面向对象的软件工程方法进行软件开

发的过程,是一个主动的多次反复迭代的过程,而不是把整个过程划分为几个严格的顺序阶段。 (2)稳定性好。传统的软件工程方法基于功能分析和功能分解。当软件功能发生变化时,很容易

引起软件结构的改变。而面向对象的软件工程方法则是基于对象的概念,用对象来表示与待解决的问题

相关的实体,以对象之间的联系来表示实体之间的关系。当目标系统的需求发生变化时,只要实体及实

体之间的联系不发生变化,就不会引起软件系统结构的变化,而只需要对部分对象进行局部修改(如从

现有的类中派生出新的子类)就可以实现系统功能的扩充。因此,基于对象的软件系统稳定性比较好。 (3)可复用性好。面向对象技术采用了继承和多态的机制,极大地提高了代码的可复用性。从

54

第 2 章 可行性研究及需求分析

父类派生出子类,一方面复用了父类中定义的数据结构和代码,另一方面提高了代码的可扩展性。 复用是指使用一个产品的组件来简化另一个功能不同的产品的开发。

—Stephen R. Schach (4)可维护性好。由于利用面向对象软件工程方法开发的软件系统稳定性好和可复用性好,

而且采用了封装和信息隐藏机制,易于对局部软件进行调整,所以系统的可维护性比较好。 基于以上这些优点,面向对象的软件工程方法越来越受到人们的青睐。

2.6 面向对象需求分析方法

面向对象的需求分析基于面向对象的思想,以用例模型为基础。开发人员在获取需求的基础

上建立目标系统的用例模型。所谓用例是指系统中的一个功能单元,可以描述为操作者与系统之

间的一次交互。用例常被用来收集用户的需求。 首先要找到系统的使用者,即用例的操作者。操作者是在系统之外,透过系统边界与系统进

行有意义交互的任何事物。“在系统之外”是指操作者本身并不是系统的组成部分,而是与系统进

行交互的外界事物。这种交互应该是“有意义”的交互,即操作者向系统发出请求后,系统要给

出相应的回应。而且,操作者并不限于人,也可以是时间、温度和其他系统等。比如,目标系统

需要每隔一段时间就进行一次系统更新,那么时间就是操作者。 可以把操作者执行的每一个系统功能都看作一个用例。可以说,用例描述了系统的功能,涉

及系统为了实现一个功能目标而关联的操作者、对象和行为。识别用例时,要注意用例是由系统

执行的,并且用例的结果是操作者可以观测到的。用例是站在用户的角度对系统进行的描述,所

以描述用例要尽量使用业务语言而不是技术语言。关于用例模型的详细创建方法,本书的实践部

分会进行介绍。如图 2-13所示为某图书馆信息管理系统的用例图。

图 2-13 图书馆信息管理系统的用例图

55

软件工程——理论与实践

确定了系统的所有用例之后,就可以开始识别目标系统中的对象和类了。把具有相似属性和

操作的对象定义为一个类。属性定义对象的静态特征,一个对象往往包含很多属性。例如,读者的

属性可能有姓名、年龄、年级、性别、学号、身份证号、籍贯、民族和血型等。目标系统不可能关

注对象的所有属性,而只是考虑与业务相关的属性。例如,在“图书馆信息管理”系统中,可能就

不会考虑读者的民族和血型等属性。操作定义了对象的行为,并以某种方式修改对象的属性值。 目标系统的类可以划分为边界类、控制类和实体类,如图 2-14所示。 (1)边界类代表了系统及其操作者的边界,描述

操作者与系统之间的交互。它更加关注系统的职责,

而不是实现职责的具体细节。通常,界面控制类、系

统和设备接口类都属于边界类。

图 2-14 边界类、控制类和实体类的图符

(2)控制类代表了系统的逻辑控制,描述一个用例所具有的事件流的控制行为,实现对用例行

为的封装。通常,可以为每个用例定义一个控制类。 (3)实体类描述了系统中必须存储的信息及相关的行为,通常对应于现实世界中的事物。 确定了系统的类和对象之后,就可以分析类之间的关系了。对象或类之间的关系有依赖、关

联、聚合、组合、泛化和实现。 (1)依赖关系是“非结构化”的和短暂的关系,表明某个对象会影响另外一个对象的行为或服务。 (2)关联关系是“结构化”的关系,描述对象之间的连接。 (3)聚合关系和组合关系是特殊的关联关系,它们强调整体和部分之间的从属性,组合是聚合

的一种形式,组合关系对应的整体和部分具有很强的归属关系和一致的生存期。例如,计算机和

显示器就属于聚合关系。 (4)泛化关系与类间的继承类似。 (5)实现关系是针对类与接口的关系。 明确了对象、类和类之间的层次关系之后,需要进一步识别出对象之间的动态交互行为,即

系统响应外部事件或操作的工作过程。一般采用顺序图将用例和分析的对象联系在一起,描述用

例的行为是如何在对象之间分布的。 最后,需要将需求分析的结果用多种模型图表示出来,并对其进行评审。由于分析的过程

是一个循序渐进的过程,合理的分析模型需要多次迭代才能得到。面向对象需求分析的示意图

如图 2-15所示。

图 2-15 面向对象的需求分析

2.7 UML 简介

UML(Unified Modeling Language),即统一建模语言,是一种标准的图形化建模语言。它主

56

第 2 章 可行性研究及需求分析

要用于软件的分析与设计,用定义完善的符号来图形化地展现一个软件系统。UML的使用可以贯穿于软件开发周期的每一个阶段,适用于数据建模、业务建模、对象建模和组件建模。作为一种

建模语言,UML并不涉及编程的问题,即与语言平台无关,这就使开发人员可以专注于建立软件系统的模型和结构。

UML 作为一种语言,可以像其他语言一样用来编写小说、百科全书、诗歌、祷告、新闻报

道甚至是软件工程的教科书。语言是表达思想的一种工具,而不应该约束语言所能表达的思想

类型或者表达的方式。 —Stephen R. Schach

UML是由 Grady Booch、Jim Rumbaugh和 Ivar Jacobson 3位专家共同开发的。1996年 6月和

10月分别发布的 UML 0.9版本和 UML 0.91版本当时就获得了工业界、科技界和用户的广泛支持。1996 年底,UML 已经占领了面向对象技术市场 85%的份额,成为事实上的可视化建模语言的工业标准。1997年 11月,OMG(国际对象管理组织)把 UML 1.1作为基于面向对象技术的标准建模语言。目前,UML已经推出了 2.0版本,其巨大的市场潜力和经济价值正逐渐得到人们广泛的认可。

UML 2.0版本由 4个部分组成: (1)基础结构; (2)上层结构; (3)对象约束语言; (4)图交换标准。 基础结构和上层结构构成了 UML 2.0提案需求的主体部分。基础结构的设计目标是定义一个

元语言的核心库,通过对此核心的复用,可以定义各种元模型。上层结构的设计目标是复用基础

结构中的制品,提高对基于构件开发和模型驱动体系结构的支持,同时优化架构的规约能力。 UML 2.0支持 13种图,其中有 6种结构图和 7种行为图。结构图也称为静态模型图,主要用

来表示系统的结构,它包括类图、组织结构图、组件图、部署图、对象图和包图。行为图也称为动

态模型图,主要用来表示系统的行为,它包括活动图、交互图、用例图和状态机图。其中交互图

是顺序图、通信图、交互概况图和时序图的统称。UML 2.0的 13种图如图 2-16所示。

图 2-16 UML 2.0中的 13种图

结构图中比较常用的有类图和对象图。类图主要用来表示类、接口、协作以及它们之间的关

系。对象图主要表示对象的特征以及对象之间的关系。

57

软件工程——理论与实践

行为图中比较常用的有用例图、顺序图、状态机图和活动图。用例图用来描述一组用例、用例的

操作者以及它们之间的关系。顺序图用来显示若干对象间的动态协作关系,强调对象之间发送消息的

先后顺序,描述对象之间的交互过程。状态机图用来描述类的对象的所有可能的状态以及引起状态转

换的事件。活动图用来重点描述事物执行的控制流或数据流,是一种描述交互的方法。 UML使问题表述标准化,有效促进了软件开发团队内部各种角色人员的交流,提高了软件开

发的效率。以下部分重点对 UML中常用的几种图进行介绍。 知识小卡片

UML 软件工程组织官方网站为 http://www.uml.org/。

2.7.1 类图和对象图

类图使用类和对象描述系统的结构,展示了系统中类的静态结构,即类与类之间的相互关系。

类之间有多种联系方式,如关联(相互连接)、依赖(一个类依赖于或使用另一个类)、泛化(一

个类是另一个类的特殊情况)。一个系统有多幅类图,一个类也可以出现在几幅类图中。 对象图是类图的实例,它展示了系统在某一时刻的快照。对象图使用与类图相同的符号,只

是在对象名下面加上下画线。 在 UML中,类图用具有 3个分隔线的矩形表示。顶层分隔表示类和对象的名字,中间表示

属性,底层表示操作。对象图通常只有名称和属性。通常情况下,类名称的开头字母用大写,

对象名称的开头字母用小写,对象名引用时常常后面跟着类名。如图 2-17所示,Student、Librarian和 Book 是图书管理系统中的 3 个示例类。其中 Book 类中包含 3 个属性(id、name、author)以及两个操作(getInfo和 edit)。其中,属性和操作前面的加号表示属性或操作是公有(Public)的,如果是减号,则表示属性或操作是私有的(Private),关于属性和操作的可见性见表 2-3。图 2-18表示图 2-17的一个对象图,图中包含 john、jim和 se 3个对象,其中 se对象是 Book类的对象。因为 Book类中包含 3个属性,所以 se对象中也对应地包含 3个属性值。对象的属性类型表示属性的取值范围。如果类定义时没有指明属性的类型,比如因为类型不是系统中已定

义的基本类型,则对该属性的决策可以推迟到对象创建之时。这样可以允许开发者在设计类时

将注意力更多地放在系统功能的设计上,并在系统功能修订的时候,将细节变化的程度减少到

最小。

+borrow() : bool

+id : int+name : string

Student

+lend() : bool

+id : int+name : string

Librarian

+getInfo() : object+edit() : bool

+id : int+name : string+author : string

Book

1 * * *

图 2-17 图书管理系统中的示例类图

id : int = 1name : string = Mike B

john : Student

id : int = 13name : string = Jim L

jim : Librarian id : int = 17name : string = software engineeringauthor : string = Dbernd

se : Book

图 2-18 图书管理系统中的示例对象图

58

第 2 章 可行性研究及需求分析

表 2-3 属性和操作的可见性

符 号 种 类 语 义

+ Public(公共的) 能访问该类的类都能访问该属性

# Protected(受保护的) 该类和其继承类都能访问该属性

− Private(私有的) 只有该类能访问该属性

~ Package(包的) 在同一个包中的类都能够访问该属性 类与类之间的关系有关联、依赖、泛化和实现等。 1.关联

关联(Association)表达模型元素间的一种语义关系,是对具有共同的结构特性、行为特性、关系和语义的链的描述。UML 中使用一条直线表示关联关系,直线两端上的数字表示重数。图2-17中,一个学生可以同时借阅多本书,但一本书只能同时被一个学生借阅,关系是一对多;而一个图书管理员可以管理多本图书,一本图书也可以被多个管理员管理,关系是多对多。 关联关系还分为二元关联、多元关联、受限关联、聚集和组合等。

二元关联指两个类之间的关联,图 2-17中展示的就是二元关联。 多元关联指一对多或多对多的关联。三元关联使用菱形符号连接关联类,图 2-19 表示的就是三元关联关系。

* *

*

Student Teacher

Course

图 2-19 三元关联

受限关联用于一对多或多对多的关联。如果关联时需要从多重数的端中指定一个对象来限定,可以

通过使用限定符来指定特定对象。比如,一个学生可以借多本书,但这多本书可以根据书的书号不

同而区分,这样就可以通过限定符“书号”来限定这些图书中的某一本图书,如图 2-20所示。

Student Book

书号

1 1

图 2-20 受限关联

聚集和组合表示整体-部分的关联,有时也称之为“复合”关系。聚集的部分对象可以是任意整

体对象的一部分,比如,“目录”与该目录下的“文件”,班级与该班级的学生等。组合则是一种

更强的关联关系,代表整体的组合对象拥有其子对象,具有很强的“物主”身份,具有管理其部

分对象的特有责任,比如“窗口”与窗口中的“菜单”。聚集关联使用空心菱形表示,菱形位于代

表整体的对象一端;组合关联与聚集关联表示方式相似,但使用实心菱形。聚集和组合的关联关

系如图 2-21和图 2-22所示。

59

软件工程——理论与实践

目录 文件

1 *

窗口 菜单

1 *

图 2-21 聚集关联 图 2-22 组合关联

关联类是一种充当关联关系的类,和类一样具有自己的属性和操作。关联类使用虚线连接自己和

关联符号。关联类依赖于连接类,没有连接类时,关联类不能单独存在。例如如图 2-23 所示的关联类关系,一次借阅中,学生可以借阅一本书,借阅类就是该例子中的关联类。实际上,任何关联类都

可以表示成一个类和简单关联关系,但常常采用关联类的表示方式,以便更加清楚地表示关联关系。

Student Book

+time : string

Borrow

1..* 1

图 2-23 关联类实例

重数是关联关系中的一个重要概念,表示关联链的条数。例如图 2-22中,链的两端的数字“1”和符号“*”表示的就是重数。重数可以是一个任意的自然数集合,但实际使用中,大于 1 的重数常常用“*”号代替,所以实际使用的重数多为 0、1和符号“*”。一对一关联的两端重数都是 1;一对多关联的一端重数是 1,另一端是“*”;多对多关联的两端重数都是 0~n,常表示为“*”。

2.依赖

依赖指出两个或多个模型元素之间的语义上的关系,被依赖元素的改变会导致依赖元素的改

变。依赖关系常用带箭头的虚线表示,箭头指向依赖对象。在 UML 2.0中的依赖关系见表 2-4。

表 2-4 依赖的种类

依 赖 功 能 关 键 词

访问 私有导入另一个包的内容 access

绑定 把值赋给一个模板的参数,以生成新的模型元素 bind

调用 陈述一个类调用另一个类的操作的方法 call

创建 陈述一个类创建另一个类的实例 create

派生 陈述一个实例能从另一个实例计算得到 derive

实例化 陈述一个类创建另一个类的实例的方法 instantiate

允许 允许一个元素使用另一个元素的内容 permit

实现 一个规约与它的实现之间的映射 realize

精化 陈述在两个不同语义层上的元素之间存在一个映射 refine

发送 一个信号的发送者和接受者之间的关系 send

替换 陈述源类支持目标类的接口和契约,并且可以替换它 substitute

追踪依赖 陈述不同模型中元素间存在某种连接,但不如映射精确 trace

使用 陈述一个元素行使职责(如调用、创建、实例化、发送等)时,需要另一个元素 use

60

第 2 章 可行性研究及需求分析

3.泛化

泛化关系描述类的一般-特殊关系,是更一般描述与更特殊描述之间的一种分类学关系,特殊

描述常常是建立在一般描述基础上的,比如会员是 VIP会员的一般描述,VIP会员就是会员的泛化,会员是一般类,VIP会员是特殊类;学生是本科生的一般描述,本科生就是学生的泛化,学生是一般类,本科生是特殊类。特殊类是一般类的子类,而特殊类还可以是另一个特殊类的子类。比如,

本科一年学生就是本科生的更特殊化描述,是后者的泛化。泛化的这种特点构成泛化的分层结构。 在面向对象的分析与设计时,可以把一些类的公共部分(包括属性与操作)提取出来作为它

们的父类。这样,子类继承了父类的属性和操作,子类中还可以定义自己特有的属性和操作。子

类不能定义父类中已经定义的属性,但可以通过重载的方式重定义父类的操作,这种方式称为方

法重载。当操作被重载时,在子类对象的父类引用中调用操作方法,对象会根据重载定义调用该

操作在子类中的实现,这种行为称为多态。重载的操作必须和父类操作具有相同的接口(操作名、

参数、返回类型)。比如,三角形、四边形、六边形都属于多边形,而四边形中又包含矩形,它们

的关系如图 2-24所示。多边形中的“显示”操作是一个抽象操作,而三角形和六边形中具体化和重载了这个操作,因为父类多边形自身的“显示”操作并不能确定图形如何显示,也不适用于子

类的显示,所以子类必须根据自己的特定形状重新定义“显示”操作。在四边形中定义了父类多

边形中没有的“计算面积”操作,在子类矩形中重载了该操作,因为子类包含特有的属性“长”

和“宽”,可以用于矩形的面积计算。

+显示()

多边形

+显示()

三角形

+显示()+计算面积()

四边形

+显示()

六边形

+计算面积()

+长+宽

矩形

图 2-24 类的泛化和继承关系

泛化是一种分类学的关系,一个一般类可以从不同的方面将其特化为不同的特殊类集合,用

类元表示类的某一个方面,由一个类元特化而成的特殊类组成了一个泛化集。在泛化集中可以对

其元素应用约束,UML中提供 4类约束,见表 2-5。

表 2-5 泛化集约束

符 号 含 义

disjoint(不相交) 该类元在泛化集中是互斥的

overlapping(交跌) 该类元在泛化集中不是互斥的

complete(完全的) 该类元在泛化集中完全覆盖特化的方面

incomplete(不完全的) 该类元在泛化集中不完全覆盖特化的方面

61

软件工程——理论与实践

例如,类别“人”根据性别类元可以划分为“男人”和“女人”,还可以根据身份类元划分为

“学生”、“教师”和“领导”等。“男人”和“女人”包含了所有的性别,所以是互斥的,且是完

全的。而由于“老师”也可以是“领导”,而且还可以有其他的职业划分,所以“学生”、“教师”

和“领导”是交跌的,且是不完全的。如图 2-25所示。 4.实现

实现关系将一个模型连接到另一个模型,通常情况下,后者是行为的规约(如接口),前者要

求必须至少支持后者的所有操作。如果前者是类,后者是接口,则该类是后者的实现。 实现与泛化很相似,区别是泛化是针对同层级元素之间的连接,而实现是针对不同语义层上

的元素的连接。如子类与父类关系是泛化,类与接口关系是实现。例如,定义“图形”接口,类

“圆”则是该接口的实现,如图 2-26所示。

男人

女人

学生 教师 领导

+显示()

<<interface >>图形

+显示()

+显示()

图 2-25 泛化集的约束 图 2-26 实现关系

2.7.2 用例图

用例图是从用户的角度描述系统的功能,由用例(User Case)、操作者(Actor)以及它们的关系连线组成。 用例是从用户角度描述系统的行为,它将系统的一个功能描述成一系列的事件,这些事件最

终对操作者产生有价值的观测结果。操作者是与系统交互的外部实体,可能是使用者,也可能是

与系统交互的外部系统、基础设备等。 在 UML 中,操作者使用人形符号表示,并且具有唯一的名称;用例使用椭圆表示,也具有

唯一的名称。操作者和用例之间使用带箭头的实线连接,由操作者指向用例。 正确识别系统的操作者尤为重要,以图书管理系统中学生借书事务为例,学生将书带到总借

还台,由图书管理员录入图书信息,完成学生的借书事务。这个使用场景中,图书管理员是操作

者,而学生不是,因为借书事务本身是由图书管理员来完成,而不是学生本身。但如果学生可以

自助借书,或者可以在网上借书,那么学生也将是操作者,因为这两种场景中学生直接与图书管

理系统进行了交互。 在分析系统的操作者时,除了考虑操作者是否与系统交互之外,还要考虑操作者是否在系统

的边界之外,只有在系统边界之外的操作者才能称为操作者,否则只能是系统的一部分。初学者

常常把系统中的数据库识别为系统的操作者,对于多数系统来说,数据库是用来存储系统数据的,

是系统的一部分,不应该被识别为操作者。可能的例外是,一些遗留系统的数据库存储着新系统

需要导入或者处理的历史数据,或者系统产生的数据导出到外部数据库中以供其他系统使用,这

62

第 2 章 可行性研究及需求分析

时的数据库应该视为系统的参与者。 在分析用例名称是否合适时,一个简单有效的方法是将操作者和其用例连在一起读,看是否

构成一个完整场景或句子。例如“游客浏览图书”,“游客登录注册”都是一个完整的场景,而“游

客图书”就不是一个完整场景或句子。 操作者之间可以存在泛化关系,类似的参与者可以组成一个层级结构。在网上书店的例子中,

会员是游客的泛化,游客有浏览图书的用例,而会员不仅包含游客的全部用例,还具有自己特有

的购买图书用例,如图 2-27所示。

浏览图书

会员 购书

游客

登录注册

按类别浏览图书

按年份浏览图书

查询图书

<<extend>>

<<include>>

图 2-27 网上书店部分用例

用例之间的关系有 3种,包括“包含”(include)、“扩展”(extend)和“泛化”(generalization)。

根据 3种不同的用例关系,用例间连线也有 3种,“包含”关系使用带箭头的虚线表示,虚线上标有

“<<include>>”,方向由包含用例指向被包含用例;扩展关系也使用带箭头的虚线表示,虚线上标有

“<<extend>>”,方向由扩展用例指向被扩展用例;“泛化”关系使用带三角形箭头的实线表示,方向由子用

例指向父用例。 1.包含关系

如果系统用例较多,不同的用例之间存在共同行为,可以将这些共同行为提取出来,单独组

成一个用例。当其他用例使用这个用例之时,它们就构成了包含关系。 2.扩展关系

在用例的执行过程中,可能出现一些异常行为,也可能会在不同的分支行为中选择执行,这

时可将异常行为与可选分支抽象成一个单独的扩展用例,这样扩展用例与主用例之间就构成了扩

展关系。一个用例常常有多个扩展用例。 3.泛化关系

用例之间的泛化关系描述用例的一般与特殊关系,不同的子用例代表了父用例的不同实现。

本章实践部分详细介绍使用 Rose绘制网上书店系统的用例模型。

2.7.3 顺序图

顺序图描述了一组对象的交互方式,它表示完成某项行为的对象和这些对象之间传递消息的

时间顺序。顺序图由对象(参与者的实例也是对象)、生命线、控制焦点和消息等组成。生命线是

一条垂直的虚线,表示对象的存在时间;控制焦点是一个细长的矩形,表示对象执行一个操作所

经历的时间段;消息是作用于控制焦点上的一条水平带箭头的实线,表示消息的传递。 一般使用顺序图描述用例的事件流,标识参与这个用例的对象,并以服务的形式将用例的

行为分配到对象上。通过对用例进行顺序图建模,可以细化用例的流程,以便发现更多的对象

和服务。 顺序图可以结合以下步骤进行绘制: (1)列出启动该用例的操作者; (2)列出启动用例时操作者使用的边界对象; (3)列出管理该用例的控制对象; (4)根据用例描述的所有流程,按时间顺序列出分析对象之间进行消息传递的序列。

63

软件工程——理论与实践

绘制顺序图需要注意以下问题: (1)如果用例的事件流包含基本流和若干备选流,则应当对基本流和备选流分别绘制顺序图。 (2)如果备选流比较简单,可以合并到基本流中。 (3)如果事件流比较复杂,可以在时间方向上将其分成多个顺序图。 (4)实体对象一般不会访问边界对象和控制对象。 以图书管理系统的“登记借书”用例为例,基本流的顺序图如图 2-28所示。

Librarian

LendItemForm LendItemControl Title BorrowerInfo Loan Item

specifyCriteria

search

search(criteria )

match(criteria )

selectTitle

getItem(title)

getItems

selectItem

lend

lend(item)

isAllowed (item)

setStatus

create(borrower,item)

create(borrower,item)

图 2-28 图书管理系统中“登记借书”用例的顺序图

2.7.4 状态图

状态图由状态机扩展而来,用来描述对象对外部对象响应的历史状态序列,即描述对象所有可能

的状态以及哪些事件将导致状态的改变。包括对象在各个不同状态间的跳转以及这些跳转的外部触发

事件,即从状态到状态的控制流。状态图侧重于描述某个对象的动态行为,是对象的生命周期模型。 状态图的组成元素包括状态、事件、转换、活动和动作。在 UML中,状态用圆角矩形表示,

一个转换由连接两个状态的箭头表示。状态图还可以进行嵌套。 (1)状态是指在对象生命周期中的一个条件或状况,对象在此期间将满足某些条件,执行某

些活动或者进行某些等待。状态由状态名、进入/退出动作、内部转移、约束和延迟事件等组成。 (2)事件是对触发状态转换的事情的描述。 (3)转换是指两个状态之间的转换,描述对象在第一个状态中执行一定动作,并在满足特定

64

第 2 章 可行性研究及需求分析

条件或发生特定事件后进入第二个状态。 (4)活动是状态机中进行的非原子执行单元。 (5)动作由引起(状态或事件)模型状态或值改变的一系列可执行原子计算组成。 在状态图中,只能有一个初态,可以有多个终态。初态使用实心黑圆表示,终态使用包含实

心黑圆的圈表示。而且,状态图还可以有分支、分叉、汇合、历史状态等。 图 2-29 显示了网上书店订单类的示意状态图。由初态开始,首先进入“付款审核”,如果没

有支付,则转到“拒绝”状态并进入终态;如果已经支付,则转到“审核完成”状态。接着进入

“订单审核”状态,如果有货则“发货”,没货则进入“等待发货”。发货完成,进入买家“已收货”

状态,最终进入终态。

图 2-29 网上书店订单类的状态图

2.7.5 活动图

活动图中的活动是展示整个计算步骤的控制流(及其操作数)的结点和流的图。执行的步骤

可以是并发的或顺序的。 活动图可以看作特殊的状态图,用于对计算流程和工作建模(后者是对对象的状态建模)。活

动图的状态表示计算过程中对象所处的活动状态。活动图的开始结点和结束结点与状态图相同,

活动图中的状态称为动作状态,也使用圆角矩形表示。动作状态之间使用箭头连接,表示动作迁

移,箭头上可以附加警戒条件、发送子句和动作表达式。活动图是状态图的变形,根据对象状态

的变化捕获动作(所完成的工作和活动)和它们的结果,表示了各动作及其之间的关系。 与状态图不同的是,活动图之间的动作迁移并不是靠触发状态图之间状态迁移的事件完成的,

而是当动作状态包含的活动完成时就进入下一个状态。在活动图中,事件只能附加在开始结点到

第一个动作状态之间的迁移上。在活动图中,判定符号用菱形表示,可以包含两个或更多附加有

警戒条件的输出迁移,迁移根据警戒条件是否为真选择迁移结点。 活动图可以根据活动发生位置的不同划分为若干个矩形区,每个矩形区称为一个泳道,泳道

有泳道名。把活动划分到不同的泳道中,能更清楚地表明动作在哪里执行(在哪个对象中等)。 一个动作迁移可以分解成两个或更多导致并行动作的迁移,多个来自并行动作的迁移也可以

合并为一个迁移。需要注意的是,并行迁移上的动作必须全部完成才能进行合并。 活动图中也可以包含对象,对象使用矩形表示,可作为活动的输入或输出(用虚线箭头连接),

表示对象受特定动作的影响,如图 2-30所示。

65

软件工程——理论与实践

订单显示

初始化

[价格、数量]

计算计算结果 : Order更新显示

图 2-30 计算订单总价的活动图

此外,活动图还可以描述系统的活动场景。以用户在网上书店提交订单为例,系统接收用户

的订单,确认是否付款,若未付款,则取消订单;若已付款,则检查订单内容;如果有货,就发

货并更新库存;若无货则等待采购。这一活动场景的活动图如图 2-31所示。

提交订单 确认付款

取消订单

检查订单

[无货]

[有货]

等待采购

发货

更新库存

图 2-31 网上书店系统用户提交订单的活动图

2.7.6 通信图

通信图又称协作图(或合作图),用于显示系统的动作协作,类似顺序图中的交互片段,但通

信图也显示对象之间的关系(上下文)。实际建模中,顺序图和通信图的选择需要根据工作的目标

而定。如果重在时间或顺序,那么选择顺序图;如果重在上下文,那么选择通信图。顺序图和通

信图都显示对象之间的交互。 通信图显示多个对象及它们之间的关系,对象间的箭头显示消息的流向。消息上也可以附带

标签,表示消息的其他信息,如发送顺序、显示条件、迭代和返回值等。开发人员熟识消息标签

的语法之后,就可以读懂对象之间的通信,并跟踪标准执行流程和消息交换顺序。但是,如果不

66

第 2 章 可行性研究及需求分析

知道消息的发送顺序,那么就不能使用通信图来表示对象关系。网上书店游客成功登录过程的通

信图如图 2-32所示。

游客 主页

登录页登录模块

1: 点击登录

7: 显

示用户

名2: 跳转

页面

3: 填写用户名、密码

4: 点击登录

6: 登录成功5: 验证登录

图 2-32 网上书店游客成功登录过程的通信图

2.7.7 交互概况图

交互概况图为建模人员提供从高级抽象层次来检查系统主要交互流的方式。当建模人员设法

保证所做的设计已经捕获了用例中定义的所有主流程元素时,就可以证明 UML 的这个特征非常有用。交互概况图基本上就是一个活动图,只是主节点由交互片段(即顺序图的某些部分)代替,

并以特定的顺序放置。交互概况图也为建模人员提供了另一种显示交互期间的流控制的方法,其

要点就是显示在系统某个位置处的交互具有的各种选择。

2.7.8 时序图

时序图主要用于实时系统,显示对象的交互以及这些对象沿着时间轴所发生的状态变化。时

序图提供了一种用来显示主动对象以及在它们与其他主动对象、系统资源的交互过程中的状态变

化的方法。时序图的 X轴为时间轴,Y轴为主动对象及其状态。 每个主动对象在 X轴方向上具有方波(矩形波)一样的时间序列,根据时间轴向的时序宽度,

即可知道主动对象在某一状态的持续时间。由于多个对象在 Y轴方向对齐排列,所以很容易判断同一时刻哪些主动对象处于什么状态,这为挑选竞争条件、优先级倒置、死锁以及其他通信问题

提供了一个非常有用的工具。

2.7.9 组件图

组件图根据系统的代码组件显示系统代码的物理结构,其中的组件可以是源代码组件、

二进制组件或者可执行组件。组件包含了其实现的一个或多个逻辑类信息,因此也就创建了

从逻辑视图到组件视图的映射。根据组件视图中组件之间的关系,可以轻易地看出当某一个

组件发生变化时,哪些组件会受到影响。如图 2-33 所示的组件图,“Student”组件依赖于“Common”组件,“Librarian”组件也依赖于“Common”组件,这样,如果“Common”组件发生变化,就会同时影响到“Student”组件和“Librarian”组件。依赖关系本身还具有传递性,如“Common”组件依赖于“DataBase”组件,所以“Student”和“Librarian”组件也依赖于“DataBase”组件。

67

软件工程——理论与实践

Student

Common

Librarian

DataBase

图 2-33 图书管理系统组件示例图

2.7.10 部署图

部署图用于显示系统中硬件和软件的物理结构,可以显示实际中的计算机和设备(节点)以

及它们之间的互连关系。在部署图中的节点内已经分配了可以执行的组件和对象,以显示这些软

件单元具体在哪个节点上运行。部署图也显示了各组件之间的依赖关系。 部署图是对系统实际物理结构的描述,不同于用例图等从功能角度的描述。对一个明确定义

的模型,可以实现完整的导航:从物理部署节点到组件,再到实现类,然后是该类对象参与的交

互,最后到达具体的用例。系统的各种视图合在一起,从不同的角度和细分层面完整地描述整个

系统。图书管理系统的物理机构部署图如图 2-34所示,整体上划分为数据库、应用系统和客户端3个节点。数据库节点中包含“DataBase”的相关组件,应用系统中包含“Common”、“Student”和“Librarian”等组件,客户端中包含各种客户端组件。

DatabaseServer LibraryAPPServer ClientNode

* ** *

图 2-34 图书管理系统物理结构部署图

2.7.11 包图

包是一种对元素进行分组的机制。如果系统非常复杂,常常包含大量的模型,为了利于理解

以及将模型独立出来用于复用,对这些元素进行分组组织,从而作为一个个集合进行整体命名和

处理。包的符号如图 2-35所示。

图 2-35 包的图形表示

包中的元素需要与其他包或类中的元素进行交互,交互过程的可

访问性包括 3种。 (1)Public(公有访问)(+):包中元素可以被其他包的元素访问。 (2)Private(私有访问)(−):包中元素只能被同属于一个包的内

含元素访问。 (3)Protected(保护访问)(#):包中的元素只能被此包或其继承包内的元素访问。 包的一些特征如下: (1)包是包含和管理模型内容的一般组织单元,任何模型元素都可以包含其中。 (2)一个模型元素只能存在于一个包中,包被撤销时,其中的元素也被撤销。 (3)包可以包含其他包,构成嵌套层次结构。 (4)包只是一个概念化的元素,不会被实例化,在软件运行中不会有包存在于其中。

68

第 2 章 可行性研究及需求分析

2.8 利用 Visio 绘制网上书店系统的数据流图

网上书店是一种新型的书店模式,它不仅是传统销售渠道的发展和补充,也是未来图书销售的发展

方向。目前,我国运作和销售较好的大型网上书店有很多,如当当、卓越亚马逊等,其中当当网上书店

在价格和品种方面的优势众所周知;卓越亚马逊网上书店创造流行的能力比较强。国外影响较大的网上

书店有美国的亚马逊、德国的贝塔斯曼等,其中亚马逊网上书店在 1998年拥有 450万名顾客,而到 2002年就有将近 32亿人网上购书,销售额达到了 78亿美元。网上售书将成为图书销售的主要渠道。 下面我们将以一个小型的“网上书店系统”为例,对软件工程开发实践方法和相关工具的使用进

行介绍。该网上书店系统旨在实现图书销售的电子商务模式并满足经销商和用户进行电子交易的需

求,从而充分发挥网上交易的优势。它的目标是保证经销商和用户之间进行快速的信息交流。 本节主要是实践利用 Visio 2010来绘制网上书店系统的数据流图。利用 Visio 2010创建 Gane-

Sarson数据流图,可以选择“软件和数据库”模板,然后再选择“数据流模型图”,创建之后可以看到 Gane-Sarson有 4种基本符号,见表 2-1。 在绘制系统数据流图的过程中,结构化需求分析方法通常强调“自顶向下,逐层分析”的思

想。对于大规模的软件系统而言,需要采用多层的数据流图才能将问题描述清楚,而对于中等规

模或小型的软件系统而言,采用 3层的数据流图就可以了。在 3层的数据流图中,顶层数据流图主要描述目标系统作为一个整体与外部用户或数据之间的交互;中层数据流图是对顶层数据流图

的细化,描述系统的主要功能模块以及数据在功能模块之间的流动关系;底层数据流图是对中层

数据流图的进一步细化,它更关注于功能模块内部的数据处理细节。 绘制目标系统的顶层数据流图时,关键在于分析系统有哪些外部用户及与该系统进行交互的

数据源点或终点。例如,对于这里的网上书店系统,其外部用户主要有游客、会员和管理员。其

中,游客进行注册后,可以成为系统的会员,会员享有订购图书及订单和书籍等信息查询的功能,

管理员可对系统的各种信息进行管理和维护。 根据上述分析,可以得到网上书店系统的顶层数据流图,如图 2-36所示。

书籍、会员、书籍信息及相关的统计报表

图 2-36 网上书店系统的顶层数据流图

中层数据流图是对顶层数据流图的细化,它把目标系统主要的功能模块细分为不同的加工,并对数

据在不同加工之间的流动关系进行描述。按照结构化需求分析方法,网上书店系统的主要功能模块可以

分为用户注册、订单信息查询、书籍信息查询、订购图书及订单信息管理和图书信息管理等。在数据处

理的过程中,系统内部的信息存储至少应该包括会员信息记录、图书信息记录和订单信息记录。 根据上述分析,可以得到“网上书店系统”的中层数据流图,如图 2-37所示。

69

软件工程——理论与实践

图 2-37 网上书店系统的中层数据流图

为了对数据流图进行细化,可以进一步对中层数据流图中的每一个加工进行分解和求精。在

网上书店系统的中层数据流图中包含 6个加工,分别是用户注册、订单信息查询、书籍信息查询、订购图书、订单信息管理和图书信息管理。那么,该系统应该包含 6张底层数据流图。底层数据流图展现了系统最精确和最细节性的数据处理过程,为系统设计和编码提供最直接的参考。图 2-38和图 2-39分别是“订购图书”和“订单信息查询”功能模块的底层数据流图。读者可以参考本节中提供的底层数据流图绘制出其他功能模块的底层数据流图。

图 2-38 订购图书模块的底层数据流图

在介绍了网上书店系统的 3层数据流图之后,下面详细阐述一下如何用 Visio 2010来绘制数据流图。数据流图的绘制过程可以分为 4 步:绘制图元,编辑图元文字,连接图元和调整布局。 下面以网上书店系统的“订购图书”模块的数据流图为例,详细介绍它的绘制过程。 (1)打开 Visio 2010,选择“软件和数据库”→“数据流模型图”,如图 2-40所示。“数据

70

第 2 章 可行性研究及需求分析

流模型图”的模具文件下包含了与数据流图相关的各种绘图文件,比如加工、数据流和数据存

储等。

图 2-39 订单信息查询模块的底层数据流图

图 2-40 选择数据流模型图

(2)绘制图元。Visio 2010支持拖曳式绘图,即将所需要的图元拖到绘图窗口上,如图 2-41所示。 (3)编辑图元。双击每个图元,进入文本编辑状态后,输入相应的文字信息。这里要注意:

在 Visio 2010中,不能对“数据存储”图元进行文字编辑,如图 2-42所示。 (4)连接图元。依据数据在各图元之间的流动关系,将相关图元用数据流连线连接起来。在

连接图元时,可以用 Visio 2010的自动连线功能,也可以将“数据流”连线拖曳到待连线的图元之间。双击“数据流”图元,可以输入数据流所表示的详细信息。如图 2-43所示为 Visio 2010的自动连线功能。

71

软件工程——理论与实践

图 2-41 绘制图元

图 2-42 编辑图元

会员编号、密码

连接到相邻形状

图 2-43 连接图元

(5)布局。先选中多个图元,然后利用菜单栏里的“开始”→“排列”→“位置”对图形进

行布局,如图 2-44所示。最后便可得到完整的数据流图。

72

第 2 章 可行性研究及需求分析

图 2-44 对齐形状

2.9 利用 Rose 创建网上书店系统的用例模型

数据流图是一种结构化需求分析工具,而用例模型多用在面向对象需求分析方法中。用例图

是 UML 中的一种动态图,用于定义系统的行为,并展示操作者与用例之间的相互作用。本节将具体介绍如何用 Rose来创建网上书店系统的用例模型。 创建用例模型时,首先要确定用例的操作者,即系统的使用者。例如,在某高校的“教务管

理系统”中,学生、教师和教务工作人员都可能成为用例的操作者。在识别和判断操作者时要注

意以下两点。 (1)操作者处于系统之外,即操作者本身并不是系统的组成部分,而是与系统进行交互的外

界事物。 (2)操作者与系统之间要进行有意义的交互。也就是说,操作者向系统发出请求后,系统要

给出相应的回应。 识别出操作者后,可以把操作者所执行的一系列系统功能归结为一个个用例。识别用例时还

要注意,用例是站在用户的角度对系统进行的描述,要尽量使用业务语言。此外,每个用例应该

针对一个可测量的任务或目标,即用例之间应该是独立的。通常软件开发人员可以从需求的描述

中提取用例,对于一个独立的事件,只要找到它的操作者、操作者的行为以及行为的对象就可以

定义一个用例了。 用例模型不仅包括用例图,还包括与用例图相关的文字性描述。因此,在绘制完用例图后,

还要对每个用例的细节作详细的文字性说明。 可以使用 Rose来创建用例模型。Rational Rose 2003中提供的用例图的建模符号以及对符号

的相关描述如图 2-45所示。 用例模型可以建立在不同的层次上,具有不同的粒度。顶层用例图比较概要地描述系统的结

构和功能,底层用例图对顶层用例图中的用例进行细化。下面我们以创建网上书店系统的顶层用

例模型为例,介绍如何运用 Rational Rose 2003创建用例模型。 (1)创建一个名为“网上书店系统.mdl”的 Rose模型文件。

73

软件工程——理论与实践

(2)在用例视图下,创建一个用例图。右击“Use Case View”,选择“Use Case Diagram”,如图 2-46所示。将用例图命名为“顶层用例图”,然后在浏览区中双击“顶层用例图”,打开编辑区中对应的框图。

图 2-45 用例图的建模符号 图 2-46 创建用例图

(3)在编辑区添加用例模型的操作者。在网上书店系统中,操作者有游客、会员和管理员。单击工具栏上的操作者图标,然后将鼠标移动到用例图窗口上的合

适位置,单击即可。同时,为操作者命名,如图 2-47所示。 (4)如果想对操作者作详细的说明或定义,可以在编辑区中右

击相应的操作者图符,然后选择“Open Specification”,然后在如图2-48所示的窗口中为该操作者添加详细的说明信息。 (5)添加操作者之间的关系。部分操作者之间可能会存在着

“泛化”的关系。所谓泛化,可以理解为类之间的继承。在网上书

店系统中,“会员”是对“游客”的泛化。添加泛化关系时,可以单

击工具栏中的泛化关系图标,然后在编辑区中的操作者之间画一条

线。双击这条线,可以在打开的窗口中对“泛化”关系进行详细定义。至此,我们得到了用例模

型的操作者视图,如图 2-49所示。

图 2-47 添加操作者

图 2-48 对操作者的详细说明 图 2-49 用例模型中的操作者

74

第 2 章 可行性研究及需求分析

(6)添加用例。单击工具栏中的用例图符,然后在用例图的合适位置单击鼠标,得到一个用例图符,然后对该用例进行编辑,添加它的名称,如图 2-50 所示。如果想对用例作详细描述,可以在编辑区中右击相应的用例,然后选择“Open Specification”,在打开的窗口中,添加相应的信息即可。

图 2-50 添加用例

(7)添加操作员与各用例之间的关系。单击工具栏中的单向连接线图标,然后在编辑区中从操作者到相关用例画一条线即可。绘好单向连线后的用例图如图 2-51所示。 (8)添加用例之间的关系。添加用例之间的关系时,可以单击工具栏中的依赖或实例化图标,

然后在有关联的用例间画一条线。选中该线,右击选择“Open Specification”,得到如图 2-52 所示的对话框。在 Stereotype栏里选择相应的关系即可。

图 2-51 添加单向连接线后的用例图 图 2-52 设置用例间的关系

用例之间的关系包括包含、扩展和泛化等关系。 包含是指一个用例的执行需要另一个用例的实现,也就是说只有在另一个用例执行之后,

该用例才能执行。它的箭头方向由包含用例指向被包含用例。当某些步骤在多个用例重复出现,

且单独形成价值时,可以将这些步骤提取出来,单独形成一个可供其他用例使用的用例,从而使

用例模型得到简化。例如,在“网上书店系统”中,会员或管理员进行某些操作之前,必须首先

登录系统,所以“登录注册”用例就可以被其他若干个用例包含。 扩展是指当前用例在执行的过程中可能产生的行为,它的箭头方向由扩展用例指向被扩展

75

软件工程——理论与实践

用例。扩展关系将在某些情况下才发生的路径提取出来单独形成用例,简化了基本路径。比如,

在某“图书管理系统”的用例图中,“超期罚款”就可能成为“还书”用例的扩展。 泛化关系多用于同一业务目的的不同技术实现,比如对于“系统”这个业务,系统可以采

用指纹验证,也可以采用口令验证,那么“指纹验证”和“口令验证”就是对“系统”的泛化。 设置好用例间关系的“网上书店系统”的用例图如图 2-53所示。

图 2-53 网上书店系统的顶层用例图

(9)添加对用例的文字性描述。用例图可以展示系统的功能需求,但是仅仅有用例图是不够的。例如,对“浏览图书”用例而言,多个活动步骤并不能反映到用例图里。所以还需要对用例

图进行文字性的描述,使得对系统的功能需求的描述更加清晰。文字性的描述可以包括以下几个

方面:用例编号、用例名称、用例描述、前置条件、后置条件、活动步骤、扩展点和异常处理。

前置条件是指用例执行前必须满足的条件。后置条件是用例执行结束后系统的状态。活动步骤是

描述在一般情况下系统的执行步骤,即各个活动的组织顺序。如果某用例有多个执行步骤,可在

扩展点中阐述。异常处理主要描述系统如何处理异常的发生。 对“浏览图书”用例的描述如下。

用例编号:20 用例名称:书籍信息查询 前置条件:用户在本系统中选择了“浏览图书目录”项 后置条件:用户成功浏览图书目录

活动步骤:

图 2-54 添加对用例的文字性描述

1.用户选择浏览图书目录,或者输入查看的图书信息。 2.系统处理用户请求成功并返回用户查看的相应的图书目

录页面。 扩展点:无 异常处理: 系统在数据库中没有找到与客户输入的相关的信息,系统返

回提示信息。 这些文字性的描述信息也可以表现在用例模型中。在编

辑区中选中用例“浏览图书”,右击选择“Open Specification”,在得到的对话框的Documentation栏里输入对该用例的描述,如图 2-54所示。

76

第 2 章 可行性研究及需求分析

按照这一方法对每一个用例添加文字性描述。添加完成后,回到主界面,选中每个用例时,

对该用例的文字性描述会自动出现在文档窗口中,如图 2-55所示。

图 2-55 文档窗口显示文字性描述信息

至此,网上书店系统的顶层用例图已经绘完,要及时保存。根据用例模型的分层思想,还可

以对顶层用例图中的用例进行细化,即继续绘制低一层的用例图。网上书店系统中“订单管理”

模块的底层用例图如图 2-56所示。其他模块的底层用例图的绘制可参照本节中介绍的方法完成。

图 2-56 订单管理模块的用例图

2.10 需求规格说明书编写指南

一般来说,软件需求规格说明书的格式可以根据项目的具体情况有所变化,没有统一的标准。

77

软件工程——理论与实践

下面是一个可以参照的软件需求规格说明书的模板。

1 概述 本文档是进行项目策划、概要设计和详细设计的基础,也是软件企业测试部门进行内部验

收测试的依据。 1.1 用户简介

列出本软件的最终用户的特点,充分说明操作人员、维护人员的教育水平和技术专长以及

本软件的预期使用频度。这些是软件设计工作的重要约束。 1.2 项目的目的与目标

项目的目的是对开发本系统的意图的总概括。 项目的目标是将目的细化后的具体描述。项目目标应是明确的、可度量的、可以达到的,

项目的范围应能确保项目的目标可以达到。 对于项目的目标可以逐步细化,以便与系统的需求建立对应关系,检查系统的功能是否覆

盖了系统的目标。 1.3 术语定义

列出本文件中用到的专门术语的定义和外文首字母缩写词的原词组。 1.4 参考资料

列出相关的参考资料,如: 本项目的经核准的计划任务书或合同及上级机关的批文;

属于本项目的其他已公布的文件;

本文件中各处引用的文件和资料,包括所要用到的软件开发标准。

列出这些文件资料的标题、文件编号、发表日期和出版单位,说明得到这些文件资料的来源。

1.5 相关文档 项目开发计划。

概要设计说明书。

详细设计说明书。

1.6 版本更新信息 版本更新记录格式,见表 1。

表 1 版本更新记录

版 本 号 创 建 者 创 建 日 期 维 护 者 维 护 日 期 维 护 纪 要

V1.0 王林 2009/03/03 — — —

V1.0.1 — — 李丽 2009/03/16 业务模型维护

2 目标系统描述 2.1 组织结构与职责

将目标系统的组织结构逐层详细描述,建议采用树状的组织结构图进行表达,每个部

门的职责也应进行简单的描述。组织结构是用户企业业务流程与信息的载体,对分析人员

理解企业的业务,确定系统范围很有帮助。取得用户的组织结构是需求获取步骤中的工作

任务之一。

78

第 2 章 可行性研究及需求分析

2.2 角色定义

用户环境中的企业角色和组织机构一样,也是分析人员理解企业业务的基础,是需求获取

的工作任务,同时也是分析人员提取对象的基础。对每个角色的授权可以进行详细的描述,建

议采用表格的形式,见表 2。对用户角色的识别也包括使用了计算机系统后的系统管理人员。

表 2 角色定义

编 号 角 色 所在部门 职 责 相关的业务

1005 采购员 业务部 商品采购、合同签订、供应商选择 进货、合同管理

2.3 作业流程或业务模型

目标系统的作业流程是对现有系统作业流程的重组、优化与改进。企业的作业流程首先要

有一个总的业务流程图,将企业中各种业务之间的关系描述出来,然后对每种业务进行详细的

描述,使业务流程与部门职责结合起来。 详细业务流程图可以采用直式业务流程图、用例图或其他示意图的形式。 图形可以将流程描述得很清楚,但是还要附加一些文字说明,如关于业务发生的频率、意

外事故的处理、高峰期的业务频率等,不能在流程图中描述的内容,需要用文字进行详细描述。 2.4 单据、账本和报表

目标系统中用户将使用的正式单据、账本、报表等进行穷举、分类、归纳。单据、账本和

报表是用户系统中信息的载体,是进行系统需求分析的基础,无论采用哪种分析方法,这都是

必不可少的信息源。 2.4.1 单据

因为单据上的数据是原始数据,所以一种单据一般对应一个实体,一个实体一般对应一张

基本表。单据的格式可用表格描述,见表 3。

表 3 单据的描述格式

单 据 名 称

用途

使用单位

制作单位

频率

高峰时数据流量 各数据项的详细说明如下。

数据项中文名 数据项英文名 数据项类型、长度、精度 数据项的取值范围 主键/外键

2.4.2 账本 因为账本上的数据是统计数据,所以一个账本一般对应一张中间表,账本的格式可用表格

描述,见表 4。

79

软件工程——理论与实践

表 4 账本的描述格式

账 本 名 称

用途

使用单位

制作单位

频率

高峰时数据流量

各数据项的详细说明如下。

序 号 数据项中文名 数据项英文名 数据项类型、长度、精度 数据项算法

1

2

3

2.4.3 报表 因为报表上的数据是统计数据,所以一个报表一般对应一张中间表,报表的格式可用表格

描述,见表 5。

表 5 报表的描述格式

报 表 名 称

用途

使用单位

制作单位

频率

高峰时数据流量 各数据项的详细说明如下。

序 号 数据项中文名 数据项英文名 数据项类型、长度、精度 数据项算法

1 2 3

2.5 可能的变化

对于目标系统,将来可能会有哪些变化,需要在此描述。企业中的变化是永恒的,系统分

析员需要描述哪些变化可能引起系统范围变更。 3 目标系统功能需求 3.1 功能需求描述

采用功能需求点列表或者用例模型的方式对目标系统的功能需求进行详细描述。功能需求

描述可以提供给后续设计、编程、测试使用,也可以在用户测试验收时使用。功能需求点列表

的格式见表 6。

80

第 2 章 可行性研究及需求分析

表 6 功能需求点列表

编 号 功能名称 使用部门 使用岗位 功能描述 输 入 系统响应 输 出

1 2 3

4 目标系统性能需求 4.1 性能需求描述

详细列出用户性能需求点列表,提供给后续分析、设计、编程、测试使用,更是为了用户

测试验收时使用。性能需求点列表的格式见表 7。

表 7 性能需求点列表

编 号 性能名称 使用部门 使用岗位 性能描述 输 入 系统响应 输 出

1 2 3

5 目标系统界面与接口需求 5.1 界面需求

界面的原则要求,如方便、简洁、美观、一致等。整个系统的界面风格定义,某些功能模

块的特殊的界面要求。 输入设备:键盘、鼠标、条码扫描器、扫描仪等。 输出设备:显示器、打印机、光盘刻录机、磁带机、音箱等。 显示风格:图形界面、字符界面、IE 界面等。 显示方式:1024×768、640×480 等。 输出格式:显示布局、打印格式等。

5.2 接口需求点列表 与其他系统的接口,如监控系统、控制系统、银行结算系统、税控系统、财务系统、政

府网络系统及其他系统等。 与系统特殊外设的接口,如 CT 机、磁共振、柜员机(ATM)、IC 卡、盘点机等。 与中间件的接口,要列出接口规范、入口参数、出口参数、传输频率等。

应在此列举出所有的外部接口名称、接口标准、规范。接口需求点列表见表 8。

表 8 接口需求点列表

编 号 接口名称 接口规范 接口标准 入口参数 出口参数 传输频率

1 2 3

6 目标系统其他需求 6.1 安全性

列出安全性需求。 6.2 可靠性

列出可靠性需求。

81

软件工程——理论与实践

6.3 灵活性

列出灵活性需求。 6.4 特殊需求

列出其他特殊需求,例如以下需求。 进度需求:系统的阶段进度要求。

资金需求:投资额度。

运行环境需求:平台、体系结构、设备要求。

培训需求:用户对培训的需求,是否提供多媒体教学光盘。

推广需求:推广的要求,如在上百个远程的部门推广该系统,是否要有推广的支持软件。

7 目标系统假设与约束条件 假设与约定条件是对预计的系统风险的描述,例如以下内容。

法律、法规和政策方面的限制。

硬件、软件、运行环境和开发环境方面的条件和限制。

可利用的信息和资源。

系统投入使用的最晚时间。

2.11 网上书店系统的需求规格说明书

1 概述 1.1 用户简介

网上书店的使用者主要有经销商和用户群两种。 (1)经销商,相对于实体书店,网络经销商有如下特点。

营业时间不受限制,与传统的 8 小时营业时间不同,借助互联网,网上书店可以 24小时全天候营业。这种不间断的服务方式对于巩固和扩大读者群,培育潜在的顾客具有重

大意义。 不受营业场地限制。因为网上书店是虚拟书店,所以它无需门市,只要维持面积有限的

库房即可正常运转,并以最低的成本经营最多的品种。 供需双方之间信息交流的广度、深度和速度有了质的飞跃。可提供的图书信息与用户需

求信息的相互沟通及匹配一直是制约图书销量增长的瓶颈,网上书店以其直观的界面、丰富的

信息、灵活的检索方式和个性化的定制服务,成功地解决了这一难题。 经营管理更加科学。现代信息技术的大量运用使得网上书店能够快捷地对业务数据进行

采集、统计、分析和应用,这有助于克服传统营销模式中的主观性和盲目性,对于提高经营管

理水平大有裨益。 (2)网上书店的用户群,该群体有如下特征。

主流人群为经常上网的读书爱好者,拥有能够上网的条件,以青年和中年人为主。 部分用户持有信用卡,可在网上直接付款;无信用卡的用户可以汇款进行交易。 从职业划分来看,一部分用户是高校学生,追求时尚快捷的购物方式,购买力有限;另

一部分则为工作人群,追求高效经济的购物方式,购买力较强。

82

第 2 章 可行性研究及需求分析

1.2 项目的目的与目标 1.2.1 目的

通过网上书店系统实现图书销售的电子商务模式并满足经销商和用户进行电子交易的需

求,保证充分发挥网上交易的优势。 1.2.2 目标

(1)网上书店各个功能完整。 (2)整个系统可以稳定运行。 (3)用户之间信息渠道畅通。 (4)用户可以迅速找到自己所需要的图书。 (5)付款渠道畅通。

1.3 术语定义 暂无。

1.4 参考资料 [1]赵池龙,杨林,孙伟.实用软件工程,第 2 版.北京:电子工业出版社,2006. [2]肖汉.软件工程理论与实践。北京:科学出版社,2006.

1.5 相关文档 软件开发计划书。

1.6 版本更新信息 版本更新记录见表 1。

表 1 版本更新记录

版 本 号 创 建 者 创 建 日 期 维 护 者 维 护 日 期 维 护 纪 要

V1.0 王明华 2009-5-15

2 现有系统描述 2.1 角色定义

网上书店系统的角色定义见表 2。

表 2 角色定义

编 号 角 色

01 采购与发货

02 总务会计

03 网站管理

04 仓库管理

05 售后服务

2.2 作业流程 网上书店系统的作业流程如图 1 所示。

83

软件工程——理论与实践

图 1 作业流程

2.3 单据、账本和报表 2.3.1 单据

暂无。 2.3.2 账本

暂无。 2.3.3 报表

暂无。 2.4 可能的变化

暂无。 3 目标系统功能需求

网上书店系统的功能概述如图 2 所示。

图 2 网上书店系统的功能概述

(1)登录注册 会员登录和游客注册的用例图如图 3 所示。

84

第 2 章 可行性研究及需求分析

图 3 登录注册模块的用例图

对用例的说明见表 3。

表 3 对用例的说明

编号 功能

名称 使用

部门输入

系统 响应

输出 功能描述

101 用户

注册 游客 用户注册

时的基本

信息

系统将用

户注册时

的信息全

部存入数

据库中

用户可

用注册

时输入

的用户

名和密

码进行

登录

用例编号:101

用例名称:用户注册

前置条件:游客申请注册

后置条件:游客注册成功成为会员

活动步骤:

(1)游客选择注册。

(2)系统返回一个注册页面。

(3)游客根据提示输入相应的注册信息。

(4)系统验证游客输入成功。

(5)游客提交注册信息。

(6)系统提示注册成功并返回首页。(默认已登录)

扩展点:无

异常处理:

(1)游客输入信息和系统验证不一致(如字段长度超过系统设置等),系统给出相应的提示

信息并返回注册页面。

(2)游客输入用户名是已注册用户名,系统给出提示并返回注册页面。

(3)系统异常,无法注册,并给出相应的信息(如网站维护等)。

85

软件工程——理论与实践

续表

编号 功能

名称 使用

部门输入

系统 响应

输出 功能描述

102 会员

登录 会员 用户注

册时的

用户名

和密码

用户的

登录时

间等相

关信息

存入数

据库中

相关

会员

的页

用例编号:102 用例名称:会员登录 前置条件:该会员必须是本网站已注册的成员 后置条件:该会员登录成功 活动步骤: (1)该会员选择登录。 (2)系统返回一个登录页面。 (3)会员输入用户名、密码和验证码并提交。 (4)系统进行系统验证,验证成功,记录该用户为登录用户并返回主页面。(表明该会员已登录) 扩展点:无 异常处理: (1)用户忘记密码,选择“找回密码”功能,进入找回密码用例。 (2)系统验证用户登录信息有错,提示用户重新登录。 (3)系统处理异常,系统给出相应的提示信息。

103 找回

密码 会员 用户注册

时的邮箱

号或密码

提示问题

系统根据

注册邮箱

号或密码

提示问题

找到相应

的用户并

返回其对

应的密码

设置页面

用户

重新

设置

自己

的密

用例编号:103 用例名称:找回密码 前置条件:用户必须是本系统的成功注册用户 后置条件:系统返回设置密码的页面让用户重新设

置密码 活动步骤: (1)会员选择“找回密码”。 (2)系统返回一个密码找回页面。(要求用户输入注册时的邮箱号,系统自动发送邮件到用户的邮箱中,

用户再根据邮箱中设置的链接重新设置密码。) (3)用户输入新的密码并提交。 (4)系统进行验证,验证成功,提示修改成功并自动跳转至登录页面。 扩展点: (1)与活动步骤中的步骤(1)相同。 (2)系统返回一个密码找回页面。(要求用户输入用户名,并根据密码提示问题让用户输入密码提示答案。) (3)用户输入用户名和密码提示问题并提交。 (4)系统进行验证,验证成功,并返回密码重新设置页面。 (5)用户输入新的密码并提交。 (6)与活动步骤中的步骤(4)相同。 异常处理: (1)在扩展点中,若用户输入错误的用户名或密码提示答案,则系统提示验证错误并返回登录页面。 (2)系统处理异常,系统给出相应的提示信息。

86

第 2 章 可行性研究及需求分析

续表

编号 功能

名称 使用

部门输入

系统 响应

输出 功能描述

104 修改

个人

信息

会员 用户输

入个人

的相关

信息

系统在

数据库

中用用

户现在

的个人

信息替

换以前

的个人

信息

用户的

个人信

息显示

被修改

用例编号:104

用例名称:修改个人信息

前置条件:该用户必须是此系统成功注册并且已成

功登录的用户

后置条件:该用户修改个人信息成功

活动步骤:

(1)会员选择“修改信息”。

(2)系统返回一个信息修改页面。

(3)会员修改相关信息并提交。

(4)系统进行系统验证,验证成功,提示修改成功。

扩展点:无

异常处理:

(1)系统验证会员输入有误,提示重新输入并返回“修改信息”页面。

(2)系统处理异常,系统给出相应的提示信息。

105 用户

注销 会员 系统自

动转换,

不需要

输入

系统自

动修改

用户在

数据库

中的相

应状态

显示用

户未登

用例编号:105

用例名称:用户注销

前置条件:该用户必须是该系统成功注册并且已成

功登录的用户

后置条件:用户成功注销

活动步骤:

(1)会员选择“注销”。

(2)系统提示用户成功注销并返回网站首页。

扩展点:无

异常处理:系统异常,并给出相应的提示信息

(2)浏览图书 浏览图书的用例图如图 4 所示。

图 4 浏览图书模块的用例图

87

软件工程——理论与实践

对用例的说明见表 4。

表 4 对用例的说明

号 功能

名称 使用

部门输入

系统 响应

输出 功能描述

201 浏览

图书

目录

游客

和会

系统自

动转

换,不

需要输

系统自

动切换

页面

显示相

应的图

书目录

页面

用例编号:201

用例名称:浏览图书目录

前置条件:用户在本系统中选择了“浏览图书目录”项

后置条件:用户成功浏览图书目录

活动步骤:

(1)用户选择浏览图书目录或者输入查看的图书信息。

(2)系统处理用户请求成功并返回用户查看的相应的图书目录页面。

扩展点:无

异常处理:系统在数据库中没有找到与用户输入相关

的信息,系统返回提示信息

202 浏览

图书 游客

和会

系统自

动转

换,不

需要输

系统自

动切换

页面

显示相

应的图

书信息

页面

用例编号:202

用例名称:浏览图书

前置条件:用户必须在浏览商品目录时查看某个商品

的详细信息

后置条件:用户查看图书

活动步骤:

(1)用户选择查看图书的详细信息。

(2)系统返回图书的详细信息。

扩展点:无

异常处理:该书暂时无详细信息,系统给出相应的提示

(3)会员购书 会员购书的用例图如图 5 所示。

图 5 会员购书模块的用例图

88

第 2 章 可行性研究及需求分析

对用例的说明见表 5。 表 5 对用例的说明

编号 功能

名称 使用

部门输入

系统 响应

输出 功能描述

301 添加

图书 会员 系统自

动转换,

不需要

输入

系统将

相应的

图书信

息添加

到数据

库中

购物车

页面中

新增相

应的图

书信息

用例编号:301 用例名称:添加图书 前置条件:用户必须是已注册并已登录的会员 后置条件:用户添加图书成功 活动步骤: (1)用户在看中的图书中选择添加图书。 (2)系统返回添加成功,并弹出结账还是继续购物的提示窗口。 (3)用户选择结账。 (4)系统返回购物车页面。 扩展点:用户选择继续购物,系统返回购买图书

的页面。 异常处理: (1)用户未登录,返回登录页面。 (2)系统异常,系统给出相应的提示信息。

302 查看

购物

会员 系统自

动转换,

不需要

输入

系统自

动切换

页面

相应会

员的购

物车页

用例编号:302 用例名称:查看购物车 前置条件: (1)用户选择“查看购物车”项。 (2)系统返回购物车页面。 后置条件:用户打开购物车页面 活动步骤: (1)用户选择“查看购物车”。 (2)系统返回购物车页面。 扩展点:无 异常处理: (1)该用户不是会员,系统给出提示,要求此用户先登录,并返回登录页面。 (2)系统给出一个提示:该购物车内没有图书。 (3)系统异常,系统给出相应的提示信息。

303 删除

图书 会员 系统自

动转换,

不需要

输入

系统将

相应的

图书信

息从数

据库中

删除

购物车

界面中

相应的

图书信

息消失

用例编号:303 用例名称:删除图书 前置条件: (1)该用户是已登录的会员。 (2)购物车中含有图书。 (3)在购物车管理页面中选择删除图书。 后置条件:相应的图书被删除 活动步骤: (1)会员选择购物车管理,选中相应的图书,点击删除图书。 (2)系统提示会员删除成功并返回购物车页面。 扩展点:无 异常处理:系统异常,系统给出相应的提示信息

89

软件工程——理论与实践

续表

编号 功能

名称 使用

部门输入

系统 响应

输出 功能描述

304 修改

图书

数量

会员 会员输

入要修

改的图

书的数

系统对

数据库

中相应

图书的

数量进

行修改

购物车

页面内

相应图

书的数

量被修

用例编号:304 用例名称:修改图书数量 前置条件: (1)用户是已登录的会员。 (2)购物车内不能为空。 后置条件:购物车内相应图书的数量被成功修改 活动步骤: (1)用户选择购物车并对相关图书的数量做出修改。 (2)系统返回确认修改信息。 (3)用户选择确认。 (4)系统提示修改成功并返回购物车。 扩展点:无 异常处理: (1)用户修改的图书数量没有改变,提示无更改并返回购物车页面。 (2)用户取消修改。 (3)系统异常,系统给出相应的提示信息。

305 清空

购物

会员 系统自

动转换,

不需要

输入

系统将

所有图

书信息

从相应

的数据

库中删

购物车

页面中

的图书

为空

用例编号:305 用例名称:清空购物车 前置条件: (1)该用户为已登录的用户。 (2)购物车内不能为空。 后置条件:购物车被成功清空 活动步骤: (1)用户选择购物车管理并点击清空购物车。 (2)系统提示购物车已清空并返回购物车页面。 扩展点:无 异常处理: (1)购物车为空,系统给出相应的提示信息。 (2)系统异常,系统给出相应的提示信息。

(4)订单管理 订单管理的用例图如图 6 所示。

图 6 订单管理模块的用例图

90

第 2 章 可行性研究及需求分析

对用例的说明见表 6。 表 6 对用例的说明

编号 功能

名称 使用

部门输入

系统 响应

输出 功能描述

401 提交

订单 会员 系统自

动转换,

不需要

输入

系统自

动修改

数据库

中相应

的信息

订单信

息存在

相应的

订单中

用例编号:401

用例名称:提交订单

前置条件:

(1)该用户为已成功登录的会员。

(2)会员购物车内不能为空。

后置条件:会员提交订单成功

活动步骤:

(1)会员确认购买提交。

(2)系统返回支付页面(如收货人信息、送货方式、信用卡号、密码、是否开发票和备注说

明等)。

(3)会员填写并提交。

(4)系统处理支付并提示结账成功,然后给出购买信息。

扩展点:无

异常处理:

(1)购物车为空,系统给出相应的提示。

(2)信用系统处理支付失败,系统给出相应的提示。

(3)系统处理异常,系统给出相应的提示。

402 查看

所有

订单

会员 系统自

动转换,

不需要

输入

系统返

回订单

目录页

系统显

示订单

目录页

用例编号:402

用例名称:查看所有订单

前置条件:

(1)该用户为已成功登录的会员。

(2)该会员在该系统中下过订单。

后置条件:会员查看所有订单成功

活动步骤:

(1)会员单击“查看订单”项。

(2)系统返回订单目录页面。

扩展点:无

异常处理:

(1)系统提示无订单。

(2)系统处理异常,系统给出相应的提示。

403 查看

单个

订单

信息

会员 系统自

动转换,

不需要

输入

系统返

回相应

的订单

信息页

系统显

示相应

的订单

信息

用例编号:403

用例名称:查看单个订单信息

前置条件:

(1)该用户为已成功登录的会员。

(2)会员拥有该订单。

后置条件:会员查看该订单成功

91

软件工程——理论与实践

续表

编号 功能

名称 使用

部门输入

系统 响应

输出 功能描述

403 查看

单个

订单

信息

会员 系统自

动转换,

不需要

输入

系统返

回相应

的订单

信息界

系统显

示相应

的订单

信息

活动步骤:

(1)会员点击相应的订单。

(2)系统返回该订单的详细信息。

扩展点:无

异常处理:系统处理异常,系统给出相应的提示

404 取消

订单 会员 系统自

动转换,

不需要

输入

系统对

数据库

中相应

的订单

信息进

行删除

系统显

示相应

的订单

被取消

用例编号:404

用例名称:取消订单

前置条件:

(1)该用户为已成功登录的会员。

(2)会员拥有该订单。

后置条件:会员取消该订单成功

活动步骤:

(1)会员点击取消订单。

(2)系统返回确认取消提示。

(3)会员确认取消。

(4)系统提示已经取消该订单并返回订单目录页面。

扩展点:无

异常处理:

(1)该订单取消的时间已过,会员不能取消该订单。

(2)系统处理异常,系统给出相应的提示。

(5)图书管理 图书管理的用例图如图 7 所示。

图 7 图书管理模块用例图

对用例的说明见表 7。

92

第 2 章 可行性研究及需求分析

表 7 对用例的说明

编号 功能

名称 使用

部门输入

系统 响应

输出 功能描述

501 查询

图书 管理

员 图书的

相关信

系统在

数据库

中查找

相关的

图书

系统查

找成功

返回相

应的图

书信息

页面或

系统提

示用户

未找到

用例编号:501 用例名称:查询图书 前置条件:该用户必须是已登录的管理员且拥有此权限 后置条件:管理员查询图书信息成功 活动步骤: (1)管理员选择“查看图书”选项。 (2)系统处理,返回相应图书页面(如图书名称、图书作者、图书价格、图书出版社、入库时间和图书库

存等数据库中具有的相应信息)。 扩展点:无 异常处理: (1)系统提示暂无此图书。 (2)系统提示查询异常,并给出相应的提示信息。

502 添加

图书 管理

员 图书的

相关信

系统将

相关图

书的信

息存入

数据库

系统提

示用户

添加成

功或失

用例编号:502 用例名称:添加图书 前置条件: (1)该用户必须是已登录的管理员且拥有此权限。 (2)数据库中无此图书信息。 后置条件:管理员添加此图书信息成功 活动步骤: (1)管理员提交添加图书信息(如图书名称、图书作者、图书价格、图书出版社、入库时间和图书库存等

数据库中具有的相应信息)。 (2)系统处理并提示添加图书信息成功。 扩展点:无 异常处理: (1)添加失败,数据库中已存在该图书信息。 (2)系统处理异常,系统给出相应的提示信息。

503 删除

图书 管理

员 相关图

书的关

键信息

系统将

数据库

中相应

的图书

信息删

系统提

示用户

删除成

功或失

用例编号:503 用例名称:删除图书 前置条件: (1)该用户必须是已登录的管理员且拥有此权限。 (2)数据库中有此图书的相应信息。 后置条件:管理员删除相应的图书信息成功 活动步骤: (1)管理员提交要删除的图书名称或 ISBN 等有关图书的关键信息。 (2)系统处理请求并提示删除成功。 扩展点: (1)管理员选中要删除的图书单击删除按钮。 (2)系统处理请求并提示删除成功。 异常处理: (1)系统返回删除失败,数据库中已无此图书信息。 (2)系统处理异常,系统给出相应的提示信息。

93

软件工程——理论与实践

续表

编号 功能

名称 使用

部门输入

系统 响应

输出 功能描述

504 修改

图书 管理

员 要修

改图

书的

相关

信息

系统在数

据库中用

修改后的

信息替换

原来相应

图书的信

系统提

示用户

修改成

功或失

用例编号:504 用例名称:修改图书 前置条件: (1)该用户必须是已登录的管理员且拥有此权限。 (2)数据库中有此图书的相应信息。 后置条件:管理员修改相应的图书信息成功 活动步骤: (1)管理员提交修改图书信息(图书信息包括图书名称、图书作者、图书价格、图书出版社、入库时间和

图书库存等数据库中具有的相应信息)。 (2)系统处理请求并提示修改成功。 扩展点:无 异常处理:系统返回修改失败,相应的图书信息没

有修改 505 会员

查询 管理

员 相关

会员

的关

键信

系统在数

据库中查

找相关的

会员

系统返

回查找

到的相

关会员

的页面

或提示

用户未

找到

用例编号:505 用例名称:会员查询 前置条件: (1)该用户必须是已登录的管理员且拥有此权限。 (2)数据库中已注册有该会员信息。 后置条件:管理员查询到该会员信息 活动步骤: (1)管理员选择“查询会员”项,并输入相关会员的关键信息(如会员用户名、系统内部编号)。 (2)系统处理请求,返回查询结果页面(查询结果包括会员用户名和会员名称等)。 扩展点:无 异常处理: (1)数据库中无相应的会员信息,系统提示查询失败。 (2)系统处理异常,系统给出相应的提示信息。

506 订单

查询 管理

员 订单

关键

信息

系统在数

据库中查

找此订单

系统返

回相关

订单的

页面或

提示用

户未找

用例编号:506 用例名称:订单查询 前置条件: (1)该用户必须是已登录的管理员且拥有此权限。 (2)数据库中有相应的订单信息。 后置条件:相应的订单查询成功 活动步骤: (1)管理员选择“订单查询”项,并输入相关订单的关键信息(如订单号),根据某会员信息查询其订单。 (2)系统处理,返回相应的查询订单结果页面。 扩展点:无 异常处理: (1)没有相应的订单。 (2)系统处理异常,系统给出相应的提示信息。

94

第 2 章 可行性研究及需求分析

续表

编号 功能

名称 使用

部门输入

系统 响应

输出 功能描述

507 订单

删除 管理

员 相关订

单的关

键信息

系统在

数据库

中将相

关订单

的内容

删除

系统提

示用户

删除成

功或失

用例编号:507

用例名称:订单删除

前置条件:

(1)该用户必须是已登录的管理员且拥有此权限。

(2)数据库中有相应的订单信息。

后置条件:相应的订单删除成功

活动步骤:

(1)管理员选择“订单删除”项,并输入相关订单的关键信息(如订单号),根据某会员信息查询

其订单)。

(2)系统处理,提示订单删除成功。

扩展点:无

异常处理:

(1)系统提示没有相应的订单或相应的订单已经被删除。

(2)系统处理异常,系统给出相应的提示信息。

508 添加

新折

管理

员 相关新

折扣的

信息

系统在

数据库

中在相

应图书

的折扣

上添加

上新的

折扣

系统返

回相关

图书的页

面,其上

有相关

的新折

扣的信

用例编号:508

用例名称:添加新折扣

前置条件:

(1)该用户必须是已登录的管理员且拥有此权限。

(2)数据库中有相应的图书信息。

后置条件:相应的图书添加新折扣成功

活动步骤:

(1)管理员选择“添加折扣”项。

(2)系统显示添加折扣页面。

(3)管理员填写并提交折扣信息(包括折扣类别名、打折原因、折扣价格以及对应图书等关键信息)。

(4)系统处理,提示添加成功。

扩展点:无

异常处理:

(1)添加新折扣信息失败,系统给出相应的提示。

(2)信息填写失败,系统返回错误页面。

(3)系统处理异常,系统给出相应的提示信息。 4 目标系统性能需求 性能需求点列表见表 8。

表 8 性能需求点列表

编号 性能名称 使用部门 性能描述 输入 系统响应 输出

1 相应的图书

查询 游客、会员、

管理员 在数据库中查

找相应的图书

图书的相关信息

(如图书名称、

ISBN、作者等)

在 3 秒内列出所有的记录

输出符合要

求的记录

95

软件工程——理论与实践

续表

编号 性能名称 使用部门 性能描述 输入 系统响应 输出

2

信息的录入、

修改、删除 会员、管理员

在数据库中录

入、修改、删除

相应的信息

录入、修改、

删除的信息

在 0.5秒内对数据进行录入、修改和

删除,并输出提示

信息

输出提示信息

3 检查信息的

规范性 游客、会员、

管理员

检查录入、修

改、删除的信息

的正确性 输入各种信息

在 0.1秒内对信息进行检查

输出信息是

否符合规范

4 报表输出 会员、管理员 用报表形式显

示出数据库中

的所有记录

输入需要显示

的报表 在 10秒内显示出所有数据库中的记录

输出需要显

示的报表

5 目标系统界面与接口需求 5.1 界面需求

输入设备:键盘,鼠标。 输出设备:显示器。 显示风格:IE 界面。 显示方式:1024×768。 输出格式:网页方式。

5.2 接口需求点列表 暂无。

6 目标系统的其他需求 6.1 安全性

尽量提高数据传输的安全性,使用安全链接加强保密性,通过防火墙加强网站的安全性。 6.2 可靠性

使网站管理人员和用户访问网站时都能正常操作。 6.3 灵活性

支持多种付款方式、多种货物搜索方式以及多种送货方式。网站支持后续更新。 6.4 特殊需求

暂无。 7 目标系统的假设与约束条件

该系统面向中小型网上书店,以整个企业为单位,不涉及企业内部业务以及部门之间的业

务交流。

小 结

本章主要介绍了软件工程中与可行性研究和需求分析相关的内容。可行性研究是指在项目开

发之前,对它的必要性和可能性进行探讨,通过对软件产品能否解决存在的问题以及能否带来预

期的价值做出评估,从而避免了盲目的软件开发。

96

第 2 章 可行性研究及需求分析

可行性研究的内容主要包括技术可行性研究、经济可行性研究和社会可行性研究 3个方面。典型的可行性研究的步骤为确定系统的目标,分析研究正在运行的系统,设计新系统的高层逻辑

模型,提出可行的解决方案并对其进行评估和比较,选择合适的解决方案,撰写可行性研究报告。 可行性研究回答目标系统是否值得去开发的问题,而需求分析旨在回答“系统做什么”的问

题。需求分析是一个非常重要的过程,它完成的好坏会直接影响后续软件开发的质量。需求分析

的步骤为获取需求,识别问题;分析需求,建立目标系统的逻辑模型;将需求文档化;需求验证。

获取需求是需求分析的基础,常用的需求分析的方法有问卷调查、访谈、实地操作、建立原型和

研究资料等。在获得需求后,开发人员应对问题进行分析,并在此基础上从高层建立目标系统的

逻辑模型。软件需求规格说明书是常用的需求阶段的输出文档,它主要描述软件部分的需求,从

开发者的角度对目标系统的业务模型、功能模型和数据模型等内容进行描述。需求验证是对需求

分析的成果进行评估和验证的过程。 在需求分析部分,本章介绍了结构化需求分析方法和面向对象需求分析方法。结构化需

求分析方法基于“分解”和“抽象”的基本思想,逐步建立目标系统的逻辑模型,进而描绘

出满足用户要求的软件系统。常用的结构化需求分析工具有数据流图、数据字典和 E-R 图。数据流图把软件系统看成是由数据流联系的各种功能的组合,可以用来建立目标系统的逻辑

模型。数据字典用于定义数据流图中各个图元的具体内容,为数据流图中出现的图形元素做

出确切的解释。E-R图可以用于描述应用系统的概念结构数据模型,它采用实体、联系和属性这 3个基本概念来进行建模。 面向对象需求分析方法主要基于面向对象的思想,以用例模型为基础进行需求分析。面向对

象的概念中主要涉及了对象、类、封装、继承和多态等概念。因为面向对象的软件工程方法更符

合人类的思维习惯,稳定性好,而且可复用性好,所以在目前的软件开发领域中最为流行。 本章还介绍了 UML的部分内容。UML是一种标准的图形化建模语言,主要用于软件的分析

与设计。它使问题表述标准化,有效地促进了软件开发团队内部各种角色人员之间的交流,提高

了软件开发的效率。 最后,本章介绍了利用 Visio绘制网上书店系统的数据流图,利用 Rose创建网上书店系统的

用例模型、需求规格说明书编写指南以及网上书店系统的规格说明书。

习 题

1.可行性研究的内容有哪些? 2.如何理解需求分析的作用和重要性? 3.常用的需求获取的方法有哪些?对比各种方法的优缺点? 4.如何理解结构化需求分析方法的基本思想。 5.请阐述面向对象的基本概念。 6.对比面向对象需求分析方法和结构化需求分析方法。 7.利用 Visio绘制“网上书店系统”的“订单信息管理”模块和“图书信息管理”模块的数

据流图。 8.利用 Rose绘制“网上书店系统”的“会员购书”模块和“浏览图书”模块的底层用例图。

97

98

第3章 软件设计

本章目标 ● 熟悉软件设计的基本概念。 ● 掌握概要设计和详细设计的内容及各自的侧重点。 ● 熟悉软件设计的原则。 ● 理解结构化软件设计方法与面向对象软件设计方法的区别。 ● 熟悉面向数据流的软件设计方法,掌握数据流图的画法。 ● 熟悉 Jackson 面向数据结构的设计方法,认识 Jackson 图的基本逻辑符号。 ● 了解程序流程图、N-S 图和 PAD 图。 ● 掌握面向对象软件设计方法,尤其是系统设计和对象设计的内容。 ● 了解软件体系结构的相关概念。 ● 掌握顺序图的绘制方法。 ● 掌握利用 Visio 绘制结构图的方法。 ● 掌握利用 Rose 绘制顺序图的方法。

3.1 软件设计的基本概念

完成了需求分析,回答了软件系统能“做什么”的问题,软件的生命周期就进入了设计阶段。

软件设计是软件开发过程中的重要阶段,在此阶段中,开发人员将集中研究如何把需求规格说明

书里归纳的分析模型转换为可行的设计模型,并将解决方案记录到相关的设计文档中。实际上,

软件设计的目标就是要回答“怎么做”才能实现软件系统的问题,也可以把设计阶段的任务理解

为把软件系统能“做什么”的逻辑模型转换为“怎么做”的物理模型。 软件设计在软件开发中处于核心地位。 什么是设计?设计是让你身处两个世界—技术世界和人类的目标世界—而你尝试将这

两个世界结合在一起。 ——Mitch Kapor

3.1.1 软件设计的分类

一般来说,软件设计分两个阶段进行。前期进行概要设计,得到软件系统的基本框架;后期

第 3章 软件设计

99

进行详细设计,明确系统内部的实现细节。 概要设计也称总体设计,它以需求规格说明书为基础,概要地说明软件系统的实现方案,

包括: (1)目标系统的总体架构; (2)每个模块的功能描述、数据接口描述及模块之间的调用关系; (3)数据库、数据定义和数据结构等。 其中,目标系统的总体架构为软件系统提供了一个结构、行为和属性的高级抽象,由构成系

统的元素的描述、这些元素之间的相互作用、指导元素集成的模式以及这些模式的约束组成。 在进行概要设计的过程中,开发人员应该首先设计出系统的总体架构,然后把功能分解为多

个模块,再明确每个模块的功能以及模块之间的关系。此后,还要对系统的数据库和数据结构进

行设计。在完成概要设计之前,编写相关的概要设计说明书也是非常必要的。 详细设计也称为过程设计,它对每个模块的功能和架构进行细化,明确要完成相应模块的预

定功能所需要的数据结构和算法,并将其用某种形式描述出来。详细设计的目标是得到实现系统

的最详细的解决方案,明确对目标系统的精确描述,从而在编码阶段可以方便地把这个描述直接

翻译为用某种程序设计语言书写的程序。 在进行详细设计的过程中,设计人员的工作涉及的内容有过程、数据和接口等。 (1)过程设计主要是指描述系统中每个模块的实现算法和细节。 (2)数据设计是对各模块所用到的数据结构的进一步细化。 (3)接口设计针对的是软件系统各模块之间的关系或通信方式以及目标系统与外部系统之间

的联系。 详细设计针对的对象与概要设计针对的对象具有共享性,但是两者在粒度上又有差异。详细

设计更具体,更关注细节,更注重最底层的实现方案。此外,详细设计要在逻辑上保证实现每个

模块功能的解决方案的正确性,同时还要将实现细节表述得清晰、易懂,从而方便编程人员的后

续编码工作。

3.1.2 软件设计的原则

为了提高软件开发的效率及软件产品的质量,人们在长期的软件开发实践中总结出一些软件

设计的原则,其基本内容如下。 1.模块化

模块是数据说明、可执行语句等程序对象的集合,是构成程序的基本组件,可以被单独命名

并通过名字来访问。过程、函数、子程序、宏都可以作为模块。模块的公共属性如下。 (1)每个模块都有输入/输出的接口,且输入/输出的接口都指向相同的调用者。 (2)每个模块都具有特定的逻辑功能,完成一定的任务。 (3)模块的逻辑功能由一段可运行的程序来实现。 (4)模块还应有属于自己的内部数据。 模块化就是把系统或程序划分为独立命名并且可以独立访问的模块,每个模块完成一个特定

的子功能。模块集成起来可以构成一个整体,完成特定的功能,进而满足用户需求。 在模块化的过程中,要注意以下几点。 (1)模块的规模要适中。模块的规模可以用模块中所含语句的数量来衡量。如果模块的规模

过小,那么势必模块的数目会较多,增大了模块之间相互调用关系的复杂度,同时也增大了花费

软件工程——理论与实践

100

在模块调用上的开销。如果模块的规模过大,那么模块内部的复杂度就会较大,也就加大了日后

测试和维护工作的难度。虽然并没有统一的标准来规范模块的规模,但是一般认为,程序的行数

在 50~100范围内比较合适。 不要过度模块化。每个模块的简单性将被集成的复杂性所掩盖。

——Roger S. Pressman (2)提高模块的独立性,降低模块间的耦合程度。模块的独立性是指软件系统中的每个模块

只完成特定的单一的功能,而与其他模块没有太多的联系。提高模块的独立性有助于系统维护以

及软件的复用。 模块的独立性与耦合密切相关。耦合是对各个模块之间互连程度的度量。耦合的强弱取决于

接口的复杂性,即与信息传递的方式、接口参数的个数、接口参数的数据类型相关。不同模块之

间互相依赖得越紧密则耦合程度越高。 为了提高模块的独立性,应该尽量降低模块之间的耦合程度。这是因为: ● 模块之间的耦合程度越低,相互影响就越小,发生异常后产生连锁反应的概率就越低; ● 在修改一个模块时,低耦合的系统可以把修改范围尽量控制在最小的范围内; ● 对一个模块进行维护时,其他模块的内部程序的正常运行不会受到较大的影响。 为了降低模块间的耦合度,可行的举措有: ● 采用简单的数据传递方式; ● 尽量使用整型等基本数据类型作为接口参数的数据类型; ● 限制接口参数的个数等。 与耦合相关的 7个等级的示意图如图 3-1所示。 无直接耦合、数据耦合和标记(特征)耦合属于低强

度的耦合。无直接耦合是指调用模块和被调用模块之间不

存在直接的数据联系。如若调用模块和被调用模块之间存

在数据联系,对于简单变量这样的数据传递针对的是数据

耦合,对于数组、结构、对象等复杂数据结构的数据传递

针对的是标记耦合。当模块之间的联系不是数据信息而是

控制信息时,这样的耦合是控制耦合。控制耦合是中强度

的耦合。较强耦合包括外部耦合和公共耦合。外部耦合是

指系统允许多个模块同时访问同一个全局变量。公共耦合

是指允许多个模块同时访问一个全局性的数据结构。内容耦合是最高强度的耦合,它允许一个模

块直接调用另一个模块中的数据。 在软件设计时,开发人员应该尽量使用数据耦合,较少使用控制耦合,限制公共耦合的使用

范围,同时坚决避免使用内容耦合。 数据耦合是一个理想的目标。

——Stephen R. Schach (3)提高模块的内聚程度。模块的内聚是指模块内部各个元素之间彼此结合的紧密程度。内

聚和耦合往往密切相关,模块的高内聚通常意味着低耦合。在软件设计时,应该尽量提高模块的

内聚程度,使模块内部的各个组成成分都相互关联,使其为了完成一个特定的功能而结合在一起。

图 3-1 耦合的等级划分

第 3章 软件设计

101

与内聚相关的 7个等级的示意图如图 3-2所示。 偶然内聚、逻辑内聚和时间内聚属于低内聚。偶然

内聚是指模块内各元素之间无实质性的联系,而只是偶

然地组合在一起。逻辑内聚是指模块内部各组成成分的

处理动作在逻辑上相似,但是功能却彼此不同。时间内

聚是指将若干在同一时间段内进行的却彼此不相关的

工作集中在一个模块中。中内聚包括过程内聚和通信内

聚。过程内聚是指模块内部各个成分按照确定的顺序进

行并无相关联系的工作。通信内聚是指模块内部各个成

分的输入数据和输出数据都相同。顺序内聚和功能内聚

属于高内聚。顺序内聚是指模块内的各个组成部分顺序

执行,前一个成分的输出就是后一个成分的输入。功能

内聚是指模块内的各个组成部分都为完成同一个功能而存在,在这里强调完成并且只完成单一

的功能。 在软件系统中,要避免使用低内聚的模块,多使用高内聚尤其是功能内聚的模块。如果能做

到一个模块完成一个功能,那么就达到了模块独立性的较高标准。 (4)加强模块的保护性。保护性是指当一个模块内部出现异常时,它的负面影响应该尽量局

限在该模块内部,从而保护其他模块不受影响,降低错误的影响范围。 2.抽象

在哲学中,抽象可以理解为以缩减一个概念或是一个现象的资讯含量来将其广义化的过程,

从而只保存与一些特定目的有关的资讯。比如,将一辆银色的女式自行车抽象为一辆交通工具,

只保留一般交通工具的属性和行为等资讯;将抑郁抽象为一种情绪,以减少其在情绪中所含的资

讯量;将某高校的计算机专业的研究生抽象为学生。 抽象主要是为了降低问题的复杂度,以得到问题领域中较简单的概念,好让人们能够控制其

过程或以宏观的角度来了解许多特定的事态。 抽象还可以理解为人们认识复杂的客观世界时所使用的一种思维工具。在客观世界中,

一定的事物、现象、状态或过程之间总存在着一些相似性,忽略它们之间非本质的差异,而

把其相似性进行概括或集中的求同存异的思维方式也可以被看作是抽象。例如,把小学生、

中学生、大学生、研究生的共同本质抽象出来之后,形成一个概念“学生”,这个概念就是抽

象的结果。 抽象在软件开发过程中起着非常重要的作用。一个庞大、复杂的系统可以先用一些宏观

的概念构造和理解,然后再逐层地用一些较微观的概念去解释上层的宏观概念,直到最底层

的元素。 抽象使得设计人员能够明确说明过程和数据而同时忽略低层细节。

——Roger S. Pressman 3.逐步求精

在面对一个新问题时,开发人员可暂时忽略问题非本质的细节,而关注于与本质相关的宏观

概念,集中精力解决主要问题,这种认识事物的方法就是逐步求精。逐步求精是抽象的逆过程。

开发人员认识问题是逐步求精的过程,同时也是抽象程度逐渐降低的过程(见图 3-3)。

图 3-2 内聚的等级划分

软件工程——理论与实践

102

实际上,可以把软件生命周期各阶段活动的进展看成是对解决方案抽象层次的细化。在可行

性研究阶段,开发人员关注于整个目标系统,即把

目标系统看成是一个完整的元素。在需求分析阶段,

开发人员从不同的方面将目标系统划分为多个模

块,即将一个完整的元素精化为若干个部分。在软

件设计阶段,抽象化的程度会逐渐降低,开发人员

关注于各模块的实现细节。在编码阶段,抽象的层

次最低,系统的实现被完全精化。 4.信息隐藏

信息隐藏与模块化的概念相关。当一个系统被

分解为若干个模块时,为了避免某个模块的行为干扰同一系统中的其他模块,应该让模块仅仅公

开必须让外界知道的信息,而将其他信息隐藏起来,这样模块的具体实现细节相对于其他不相关

的模块而言就是不可见的,这种机制就叫做信息隐藏。 信息隐藏提高了模块的独立性,加强了外部对模块内部信息进行访问的限制,它使得模块的

局部错误尽量不影响其他模块。信息隐藏有利于软件的测试和维护工作。 通常,模块的信息隐藏可以通过接口来实现。模块通过接口与外部进行通信,而把模块的具

体实现细节(如数据结构、算法等内部信息)隐藏起来。一般来说,一个模块具有有限个接口,

外部模块通过调用相应的接口来实现对目标模块的操作。

3.2 结构化软件设计方法

相对于面向对象的方法而言,结构化软件设计方法更关注于系统的功能,采用自顶向下、逐

步求精的设计过程,以模块为中心来解决问题。采用结构化软件设计方法开发出来的软件系统可

以看成是一组函数或过程的集合。结构化软件设计从系统的功能入手,按照工程标准和严格的规

范将目标系统划分为若干功能模块。 结构化软件设计方法可以划分为面向数据流的设计方法和面向数据结构的设计方法。

3.2.1 面向数据流的设计方法

面向数据流的设计方法是常用的结构化设计方法,多在概要设计阶段使用。它主要是指依据

一定的映射规则,将需求分析阶段得到的数据描述从系统的输入端到输出端所经历的一系列变换

或处理的数据流图转换为目标系统的结构描述。 面向数据流的设计方法是由 IBM 公司 L. Constantine 和 E. Yourdon 等人于 1974 年提出的。

在数据流图中,数据流分为变换型数据流和事务型数据流两种。所谓变换,是指把输入的数

据处理后转变成另外的输出数据。信息沿输入路径流入系统,在系统中经过加工处理后又离开系

统,当信息流具备这种特征时就是变换流。 所谓事务,是指非数据变换的处理,它将输入的数据流分散成许多数据流,形成若干个加工,

图 3-3 逐步求精与抽象的关系

知识小卡片

第 3章 软件设计

103

然后选择其中一个路径来执行。例如,对于一个邮件分发中心,把收进的邮件根据地址进行分发,

有的用飞机邮送,有的用汽车邮送。信息沿输入路径流入系统,到达一个事务中心,这个事务中心

根据输入数据的特征和类型在若干个动作序列中选择一个执行方式,这种情况下的数据流称为事务

流,它是以事务为中心的。变换型数据流和事务型数据流的示意图分别如图 3-4和图 3-5所示。

图 3-4 变换型数据流 图 3-5 事务型数据流

通常,在一个大型系统中,可能同时存在变换型数据流和事务型数据流。对于变换型数据流,

设计人员应该重点区分其输入和输出分支,通过变换分析将数据流图映射为变换结构,从而构造

出目标系统的结构图。针对变换型数据流的设计可以分为以下几个步骤。 (1)区分变换型数据流中的输入数据、变换中心和输出数据,并在数据流图上用虚线标明分界线。 (2)分析得到系统的初始结构图。 (3)对系统结构图进行优化。 下面以某个“学生档案管理系统”为例,对其进行面向数据流的系统设计。已知该系统的数

据流图如图 3-6所示。

图 3-6 学生档案管理系统的数据流图

学生档案管理系统的数据流都属于变换型数据流,其数据流图中并不存在事务中心。区分数

软件工程——理论与实践

104

据流图中的输入流、变换流和输出流,得到该系统具有边界的数据流图,如图 3-7所示。

图 3-7 学生档案管理系统的具有边界的数据流图

经分析,得到学生档案管理系统的系统结构图,如图 3-8所示。

图 3-8 学生档案管理系统的系统结构图

由于使用系统时,需要对用户的身份进行验证,因此可对“统计分析数据”等模块进行进一步的

细分。对初步得到的系统结构图进行优化,可以进一步得到该系统优化的系统结构图,如图 3-9所示。

图 3-9 学生档案管理系统优化的系统结构图

第 3章 软件设计

105

对于事务型数据流,设计人员应该重点区分事务中心和数据接收通路,通过事务分析将数据

流图映射为事务结构。针对事务型数据流的设计可以分为以下几个步骤。 (1)确定以事务为中心的结构,找出事务中心、接收数据、处理路径 3个部分。 (2)将数据流图转换为初始的系统结构图。 (3)分解和细化接收分支和处理分支。 例如,对于一个“产品管理系统”,其数据流的示意图如图 3-10所示。

图 3-10 产品管理系统的数据流示意图

该系统的数据流中以事务型数据流为中心,加工“确定事务类型”是它的事务中心。经分析

可以得到该系统的结构图,如图 3-11所示。

图 3-11 产品管理系统的系统结构图

3.2.2 面向数据结构的设计方法

顾名思义,面向数据结构的设计方法就是根据数据结构设计程序处理过程的方法。具体地说,

面向数据结构的设计方法按输入、输出以及计算机内部存储信息的数据结构进行软件结构设计,

从而把对数据结构的描述转换为对软件结构的描述。使用面向数据结构的设计方法时,分析目标

系统的数据结构是关键。 面向数据结构的设计方法通常在详细设计阶段使用。比较流行的面向数据结构的设计方法包

括 Jackson方法和Warnier方法。在这里,主要介绍 Jackson方法。 Jackson方法把数据结构分为 3种基本类型:顺序型结构、选择型结构和循环型结构。它的基

本思想是:在充分理解问题的基础上,找出输入数据、输出数据的层次结构的对应关系,将数据

软件工程——理论与实践

106

结构的层次关系映射为软件控制层次结构,然后对问题的细节进行过程性描述。Jackson 图是Jackson方法的描述工具,Jackson方法的基本逻辑结构如图 3-12所示。 在顺序型结构中,数据由一个或多个元素组成,每个元素按照确定的次序出现一次。在图 3-12

的顺序型图示中,数据 A由 B、C和 D 3个元素顺序组成。在选择型结构中,数据包含两个或多个元素,每次使用该数据时,按照一定的条件从罗列的多个数据元素中选择一个。在图 3-12的选择型图示中,数据 A根据条件从 B或 C或 D中选择一个,元素右上方的符号“ °”表示从中选择一个。在循环型结构中,数据根据使用时的条件由一个数据元素出现零次或多次构成。在图 3-12的循环型图示中,数据 A根据条件由元素 B出现零次或多次组成。元素 B后加符号“*”表示重复。

图 3-12 Jackson图的基本逻辑符号

运用 Jackson 图表达选择型或循环型结构时,选择条件或循环结束条件不能在图上直接表现出来,并且框间连线为斜线,不易在打印机上输出,所以产生了改进的 Jackson 图,其基本逻辑符号如图 3-13所示。

图 3-13 改进的 Jackson图的基本逻辑符号

选择型结构图上 S 右边括号中的 i 代表分支条件的编号。在可选型结构中,A 或者是元素 B或者不出现。在循环型结构图中,i代表循环结束条件的编号。 运用 Jackson图进行程序设计的优点是: (1)可以清晰地表示层次结构,易于对自顶向下的结构进行描述; (2)结构易懂、易用,并且比较直观、形象; (3)不仅可以表示数据结构,也可以表示程序结构; 运用 Jackson方法进行程序设计的步骤可以归纳为以下几点:

第 3章 软件设计

107

(1)分析并确定输入数据和输出数据的逻辑结构,并用 Jackson结构来表示这些数据结构; (2)找出输入数据结构和输出数据结构中有对应关系的数据单元; (3)按照一定的规则,从描绘数据结构的 Jackson图导出描绘程序结构的 Jackson图; (4)列出基本操作与条件,并把它们分配到程序结构图的适当位置; (5)用伪代码表示程序。

3.3 结构化软件设计工具

3.3.1 流程图

流程图是对过程、算法、流程的一种图形表示,它对某个问题的定义、分析或解法进行描述,

用定义完善的符号来表示操作、数据、流向等概念。 根据国家标准 GB/T 1526-1989的规定,流程图分为数据流程图、程序流程图、系统流程图、

程序网络图和系统资源图 5种。这里主要介绍程序流程图。 程序流程图也称程序框图,是一种比较直观、形象地描述过

程的控制流程的图形工具。它包含 5种基本的控制结构:顺序型、选择型、先判定型循环(WHILE-DO)、后判定型循环(DO-WHILE)和多分支选择型。 程序流程图中使用的基本符号如图 3-14所示。程序流程图的

5种基本控制结构的图符如图 3-15所示。 利用基本符号和控制结构图符就可以画出简单的程序流程图

了。某程序片断的程序流程图如图 3-16所示。

图 3-15 程序流程图的控制结构图符 图 3-16 程序流程图示例

图 3-14 程序流程图的基本符号

软件工程——理论与实践

108

程序流程图的主要优点是: (1)采用简单规范的符号,画法简单; (2)结构清晰,逻辑性强; (3)便于描述,容易理解。 程序流程图的主要缺点是: (1)不利于逐步求精的设计; (2)图中可用箭头随意地对控制进行转移,与结构化程序设计精神相悖; (3)不易于表示系统中所含的数据结构; (4)当目标系统比较复杂时,流程图会变得很繁杂,不清晰。

3.3.2 N-S 图 N-S图是由 Nassi和 Shneiderman提出的,又被称为盒图,是一种符合结构化程序设计原则的

图形工具。N-S图的基本符号如图 3-17所示。

图 3-17 N-S图的基本符号

可见,N-S 图用类似盒子的矩形以及矩形之间的嵌套来表示语句或语句序列。N-S 图内部没有箭头,因此,它所表示的控制流程不能随便进行转移。N-S图的主要特点可以归纳为: (1)不允许随意的控制转移,有利于严格的结构化程序设计; (2)可以很方便地确定一个特定控制结构的作用域以及局部数据和全局数据的作用域; (3)可以很方便地表示嵌套关系以及模块之间的层次关系。 如图 3-18所示为求两数最大公约数的 N-S图表示。

图 3-18 N-S图示例

用 N-S图表示算法,思路清晰,结构良好,容易设计,因而可有效地提高程序设计的质量和

第 3章 软件设计

109

效率。求解 10!问题的算法用程序流程图转换为 N-S图的示例如图 3-19所示。

图 3-19 程序流程图改为 N-S图示例

3.3.3 PAD图

PAD图(Problem Analysis Diagram)也叫问题分析图,它是由日本日立公司于 1973年发明的。PAD图基于结构化程序设计思想,用二维树形结构的图来表示程序的控制流及逻辑结构。 在 PAD图中,一条竖线代表一个层次,最左

边的竖线是第一层控制结构,随着层次的加深,

图形不断地向右展开。PAD图的基本控制符号如图 3-20所示。

PAD 图为常用的高级程序设计语言的各种控制语句提供了对应的图形符号,它的主要特

点是: (1)表示的程序结构的执行顺序是自最左边

的竖线的上端开始,自上而下,自左向右; (2)表示的程序片断结构清晰、层次分明; (3)支持自顶向下、逐步求精的设计方法; (4)只能用于结构化的程序设计; (5)不仅可以表示程序逻辑,还能表示数据结构。

3.4 面向对象软件设计方法

设计阶段的任务是及时地把分析阶段得到的需求转变成符合各项要求的系统实现方案。与传

统的软件工程方法不同的是,面向对象的方法不强调需求分析和软件设计的严格区分。实际上,

图 3-20 PAD图的基本控制符号

软件工程——理论与实践

110

面向对象的需求分析和面向对象的设计活动是一个反复迭代的过程,从分析到设计的过渡是一个

逐渐扩充、细化和完善分析阶段所得到的各种模型的过程。 设计是一个复杂的、迭代的过程。最初的设计方案可能是错误的,当然也不是最优的。

——Robert L.Glass 与结构化的设计相比,面向对象的设计更符合复杂的、随机性较强和考虑并发性的系统软件

设计,而不适合逻辑性很强的系统软件设计。结构化软件设计一般从系统功能入手,按照需求将

系统功能分为若干个子功能模块。但是,用户的需求是在不断变化的。需求的改变往往会对功能

模块产生影响,从而对整个系统产生影响,而面向对象的设计基于类、对象、封装、继承等概念,

相比之下,需求的变化对系统的局部影响并不容易扩展到全局。因此,面向对象设计方法比结构

化设计方法更具有优势,使用范围更广。 面向对象的设计可以分为系统设计和对象设计两个阶段。在进行面向对象的设计的时候,开

发人员应该注意的有: (1)面向对象的设计原则; (2)面向对象设计的启发规则; (3)系统设计; (4)对象设计。 面向对象的设计原则基本遵循传统软件设计应该遵循的基本原理,同时还要考虑面向对象的

特点。设计原则具体如下。 (1)模块化。在结构化的设计中,一个模块通常为一个过程或一个函数,它们封装了一系列的

控制逻辑;而在面向对象的设计中,一个模块通常为一个类或对象,它们封装了事物的属性或操作。 (2)抽象化。类是对一组具有相似特征的对象的抽象。可以说,类是一种抽象的数据类型。同

时,对象也是对客观世界中事物的抽象。它用紧密结合的一组属性和操作来表示事物的客观存在。 (3)信息隐藏。对于类而言,其内部信息(比如属性的表示方法和操作的实现算法)对外界

是隐藏的。外界通过有限的接口来对类的内部信息进行访问。类的成员都具有相应的访问控制的

属性。 (4)低耦合。在面向对象的设计中,耦合主要是指对象之间的耦合,即不同对象之间相互关

联的紧密程度。低耦合有利于降低由于一个模块的改变而对其他模块造成的影响。 (5)高内聚。内聚与耦合密切相关,低耦合往往意味着高内聚。提高模块的内聚性有利于提

高系统的独立性。 (6)复用性。构造新类时,都需要考虑该类将来被重复利用的可能。提高类的复用性可以节

约资源,精简系统结构。 面向对象设计的启发规则是人们在长期的基于面向对象思想的软件开发实践中总结出来的经

验,有利于提高开发人员进行软件设计的质量。启发规则具体如下。 (1)设计结果应该清晰易懂。设计结果清晰易懂可以为后续的软件开发提供便利,同时还能

够提高软件的可维护性。要做到这一点,首先应该注意对类、属性或操作的命名。如果名称能与

所代表的事物或代表的含义一致,那么开发人员就能很方便地理解特定类、属性或操作的用途。

要尽量避免模糊的定义。其次,如果开发团队内已经为软件开发设立了协议,那么开发人员在设

计新类时应该尽量遵循已有的协议,从而与整个系统设计保持一致。此外,如果已定义了标准的

消息模式,开发人员也应该尽量遵守这些消息模式,尽量减少消息模式的数量。

第 3章 软件设计

111

设计良好的建筑应该展示出坚固、适用和令人赏心悦目的特点。对好的软件来说也是如此。

——Roger S. Pressman (2)类等级深度应该适当。虽然类的继承与派生有诸多优点,但是不能随意创建派生类。应

该使类等级中包含的层次数适当。对于中等规模的系统,类的等级层次数应该保持在 5~9。 (3)要尽量设计简单的类。简单的类便于开发和管理。如果一个类过于庞大,势必会造成维

护困难、不灵活等问题。为了保持类的简洁,要尽量简化对象之间的合作关系,为每个类分配的

任务应该尽量简单。此外,要控制类中包含的属性及提供的操作。 (4)使用简单的协议。减少消息的参数个数是减少类间耦合程度的有效手段。一般来说,消

息的参数最好控制在 3个以内,而且要尽量使用简单的数据类型。 (5)使用简单的操作。控制操作中的源程序语句的行数或语句的

嵌套层数可以简化操作。 (6)把设计的变动减至最小。虽然设计的变动是正常情况,但是

由于设计的变动会造成资源或时间上的消耗,开发人员应该尽量把设

计的变动概率降至最低。一般来说,设计的质量越高,出现设计被修

改情况的概率就越低,即使需要修改设计,修改的范围也会比较小。 面向对象的设计可以划分为系统设计和对象设计两个阶段。系统

设计关注于确定实现系统的策略和目标系统的高层结构。开发人员将

问题分解为若干个子系统,子系统和子系统之间通过接口进行联系。

一般来说,常用的系统设计的步骤如图 3-21所示。 将系统分解为若干子系统要按照一定的拓扑关系,比如树形、星

形等。问题域是指与应用问题直接相关的类或对象。对问题域子系统的设计,即定义这些类或对

象的细节。虽然在面向对象的需求分析过程中已经标识和定义了系统的类与对象以及它们之间的

各种关系,但是,随着对需求理解的加深和对系统认识程度的逐步提高,在面向对象的设计阶段,

开发人员还应该对需求分析阶段得到的目标系统的分析模型进行修正和完善。 我主张在系统设计中,概念完整性应该是最重要的考虑因素。也就是说为了反映一系列连

贯的设计思路,宁可省略一些不规则的特性和改进,也不提倡孤立和无法整合的系统,哪怕它

们包含了许多很好的设计。 ——Frederick P.Brooks, Jr.

对象设计是指对面向对象的需求分析阶段得到的对象模型进行扩充、细化和完善。对象设计

的内容包括: (1)对象中对属性和操作的详细描述; (2)对象之间发送消息的协议; (3)类之间的各种关系的定义; (4)对象之间的动态交互行为等。 进行结构化的软件设计时,开发人员可能会用到流程图、N-S图、PAD图等工具。在进行面

向对象的软件设计时,开发人员通常会利用 UML来表述设计成果。UML适用于面向对象软件开发的全过程,即应用于需求分析、设计、编码和测试的所有阶段。由于在面向对象的需求分析阶

段和面向对象的设计阶段使用的图形符号完全相同,面向对象的设计是对面向对象的需求分析所

图 3-21 系统设计的步骤

软件工程——理论与实践

112

获得的分析模型的进一步完善和修正,所以并不需要严格区分这两个阶段的工作。这里就不详细

介绍借助 UML工具进行面向对象的设计的相关内容了。

3.5 数据库结构设计

数据库结构设计包括概念结构设计、逻辑结构设计和物理结构设计。 (1)数据库的概念结构是系统中各种数据模型的共同基础,

它描述了系统最基础的数据结构,独立于特定的数据库系统。 (2)数据库的逻辑结构提供了比较接近数据库内部构造的逻

辑描述,它能够为数据库的物理结构创建提供便利。 (3)数据库的物理结构是指数据库的物理数据模型,它包括

数据库服务器物理空间上的表、存储过程、字段、视图、触发器、

索引等,与特定的数据库系统密切相关。 数据库结构设计的示意图如图 3-22所示。 通常,数据库的概念结构用 E-R图(参考 2.4.3节)来表示。

在一个学生选课系统中,“学生”与“课程”的 E-R图如图 3-23所示。

图 3-23 “学生”与“课程”的 E-R图

在设计数据库的逻辑结构的过程中,首先要将概念结构中的实体、属性、联系映射为数据表

结构。在关系型数据库中,数据表是数据的存储单位。在映射的过程中,可以遵循以下规则。 (1)将数据库概念结构中的“实体”映射为逻辑结构中的“数据表”,实体的属性可以用数据

表中的字段来表示,实体的主关键字作为数据表的主键。 (2)数据库概念结构中的 1:1 联系可以映射为一个独立的数据表,也可以与跟它相连的任意

一端或两端的实体合并组成数据表。 (3)数据库结构中的 1:n 联系可以映射为一个独立的数据表,也可以与跟它相连的 n 端实体

合并组成数据表。 (4)数据库结构中的 m:n关系可以映射为一个独立的数据表,各实体的主关键字的组合形成

数据表的主键。 根据以上规则,“学生”与“课程”E-R图可以映射为如下数据表结构: 学生(学号,姓名,班级,年龄) 课程(编号,名称,教师,学时,学分) 选课(编号,学号,成绩) 形成初始的数据表后,要对其进行规范,在这里引入范式的概念。一个好的关系模式应当不

图 3-22 数据库结构设计

第 3章 软件设计

113

会发生插入异常、更新异常、删除异常,数据冗余尽可能少,在设计关系数据库时应该考虑上述

问题。各范式的定义如下。 (1)第一范式:所有关系中的每一个分量都必须是不可分的数据项。第一范式是建立关系型

数据表的最基本的要求。 (2)第二范式:满足第一范式的条件,并且每个非键属性都由整个键决定。 (3)第三范式:满足第二范式的条件,并且每个非键属性不依赖于其他非键属性值。 显然,数据表的范式级别越高,其规范性也就越强。对于小型软件开发项目而言,所设计的

逻辑模式能满足第二范式的要求即可。但是,如果项目对数据库中数据的完整性要求较高,应保

证所设计的关系模式满足第三范式甚至更高范式的要求。 设计好数据表后,若数据表之间存在关联关系,那么可以采用主键、外键的方法,这是数据

表之间参照完整性规则的依据。此外,为了使数据具有更高的安全性,方便对数据的组织和操作,

人们还会采用数据视图的方法来进一步完善数据库的逻辑结构设计。 得到数据库的逻辑结构之后,就可以将模型进一步表现为物理空间上的表、字段、索引、存

储过程、触发器及相应的数据字典了。 数据库与数据垃圾堆之间的差别就在于数据的质量。

——Jarrett Rosenberg

3.6 软件的体系结构

3.6.1 软件的体系结构概述

体系结构是研究系统各部分组成及相互关系的技术学科。每一个建筑物都有体系结构,体系

结构就相当于一个系统的整体框架的草图,描述系统组成的骨架。同样,软件系统也具有自己的

体系结构。软件体系结构对于一个软件系统具有至关重要的作用,它的好坏直接决定软件系统是

否能合理高效地运行。可以说,软件体系结构既决定系统的框架和主体结构,又决定系统的基本

功能及某些细节特征。软件体系结构是构建计算机软件实践的基础。 软件体系结构描述的对象是直接构成系统的抽象组件。它由功能各异、相互作用的部件按照

层次构成,包含了系统的基础构成单元、单元之间的相互作用关系、在构成系统时它们的合成方

法以及对合成约束的描述。 具体来说,部件包括客户、服务器、数据库、程序包、过程、子程序等一切软件的组成部分。相互

作用的关系可以是过程调用、消息传递、共享内存变量、客户/服务器的访问协议、数据库的访问协议等。 在建筑学中,建筑师通常用不同种类的蓝图来描述目标建筑物。在软件设计中,开发人员也

经常用各种视图来描述目标系统,如功能视图、逻辑视图、结构视图、过程视图、物理视图、部

署视图等。目前,UML已经提供了一套软件体系结构视图的标准。 系统的架构师就像建筑业的建筑师一样,是用户的代言人。架构师的工作是运用专业技术

知识来维护用户的真正利益,而不是维护销售人员、制作者所鼓吹的利益。 ——Frederick P. Brooks, Jr.

软件工程——理论与实践

114

在介绍软件体系结构时,一定要介绍分层的概念。分层可以让我们从不同的角度、不同的层

面来观察软件系统,方便我们对软件系统进行描述、分析、设计和使用。软件体系结构的分层模

型如图 3-24所示。 (1)计算机硬件层是软件实现的物质基础,比如存储

器、时钟、高速缓存等。 (2)软件硬件层实现了软件与硬件的分离,既是对

软件实现的最底层描述,也是对硬件实现的操作和控制

的描述。 (3)基础控制描述层、资源和管理调度层是体系结构

部件和连接的内在构成模型。基础控制描述层描述了高级

语言支持的所有顺序、选择、循环、过程、函数等程序控

制的概念和数组、队列、链表等数据描述概念。资源和管

理调度层描述了基于特定操作系统的进程管理、消息通信

等机制,协调和控制一系列数据对象和操作。 (4)系统结构模式层是软件的上层体系结构,它是最

高层次的软件结构概念,其涉及的概念通常有客户/服务器、解释器、编译器、框架等。 (5)应用层是建立在软件概念之上的领域问题描述,它是基于纯粹的应用领域的。 客户/服务器是属于系统结构模式层的概念,当它用于企业管理建立了某个特定的数据库时,

就产生了应用领域的概念。可见,不同层次的描述反映了对软件系统不同方面和角度的认识。 设计软件的体系结构在设计阶段非常重要。软件体系结构就好比软件系统的骨骼,如果骨骼

确定了,那么软件系统的框架就确定了。在设计软件体系结构的过程中应当完成的工作至少包括

以下几项。 (1)定义软件系统的基本构件、构件的打包方式以及相互作用的方式。 (2)明确系统如何实现功能、性能、可靠性、安全性等各个方面的需求。 (3)尽量使用已有的构件,提高软件的可复用性。 两种常用的软件体系结构如图 3-25和图 3-26所示。

图 3-25 树形结构 图 3-26 网状结构

3.6.2 软件系统的设计模式

所谓模式,就是指解决某一类相似问题的方法论。某个模式描述了一个在我们的日常生活中

不断出现的问题,然后描述了该问题的解决方案的核心。人们可以使用已有的解决方案来解决新

图 3-24 软件体系结构的分层模型

第 3章 软件设计

115

出现的问题。模式应用在不同的领域中,在软件系统的设计领域中也出现了很多设计模式。 模式是冠名的洞察力财宝,对于竞争事件中某确定环境下重复出现的问题,它承载了已证

实的解决方案的精髓。 ——Christopher Alexander

每种设计模式都包含 4个要素,如图 3-27所示。 (1)模式名称相当于模式的助记符。 (2)问题描述了模式的使用场景,即模式可以解决的某种

设计问题。 (3)解决方案描述了针对特定的设计问题可以采用怎样的

设计方法,包括设计的组成成分、各成分的职责和协作方式以

及各成分之间的相互关系。 (4)效果描述了特定模式的应用对系统灵活性、扩展性、

可移植性等各种特性的影响,它对评价设计选择以及对模式的

理解非常有益。 目前,比较常用的是由 Erich Gamma、Richard Helm、Ralph Johnson和 John Vlissides所提出的

23种设计模式,它们分为 3种类型,即创建型模式、结构型模式和行为型模式,如图 3-28所示。

图 3-28 设计模式的分类

图 3-27 设计模式的要素

软件工程——理论与实践

116

Christopher Alexander 是一位世界著名的建筑设计师。他在 1977 年编写的一本有关设计模

式的著作中描述了一种体系结构模式语言。1988 年,Erich Gamma 尝试着将 Christopher Alexander 的思想改写,使之适用于软件开发。后来,Erich Gamma、Richard Helm、Ralph Johnson和 John Vlissides 合作出版了 Design Patterns—Elements of Reusable Object-Oriented Software 一书,共收录了 23 种设计模式。

创建型模式通过创建对象而不直接实例化对象的过程,使得程序在判定给定的情况下更加灵

活地创建对象。很多时候,创建对象的本意随程序需求的不同而不同,如果将创建过程抽象成一

个专门的“创造器”类,那么程序的灵活性和通用性将有很大提高。下面以描述工厂模式为例,

对创建型模式作进一步的介绍。

模式名称:工厂模式 问题:在软件系统中,由于需求的变化,一些对象的实现可能会发生变化。为了应对这种“易

变对象”的变化,人们提出了工厂模式。 解决方案:为对象的创建提供接口,使子类决定实例化哪一个类。如图 3-29 所示,Produce

方法使类的创建延迟到子类中。

图 3-29 工厂模式

效果:使用工厂方法在类的内部创建对象通常比直接创建对象更加灵活。而且,可以将对象

的创建工作延迟到子类中,这对于客户不清楚对象类型的情况非常有益。 结构型模式提供了不同类或对象之间的各异的静态结构,它描述了如何组合类或对象以获得

更大的结构,如复杂的用户界面或报表数据。下面以描述桥接模式为例,对结构型模式作进一步

的介绍。

模式名称:桥接模式 问题:在软件系统中,有些类型可能存在着多个维度的变化。为了降低变化的发生对系统的

影响,可以使用桥接模式。 解决方案:将不变的内容框架用抽象类定义,将变化的内容用具体的子类分别实现。并且,

将类的抽象与实现分离,从而使两端都可以独立变化。实际上,一个普通的控制多个电器设备的

知识小卡片

第 3章 软件设计

117

开关就是桥接的例子,如图 3-30 所示。开关可以是简单的拉链开关,也可以是调光开关。开关的

实现,根据其控制的设备的不同也有不同。由开关例子的桥接类图可以进一步抽象出表示桥接模

式的示意图,如图 3-31 所示。Abstraction 相当于对某一概念的高级抽象,它包含有对 Implementor的引用。Implementor 是对上述概念实现方式的抽象。RefinedAbstraction 和 ConcreteImplementor分别代表了具体的概念及其实现方式。

图 3-30 开关的例子 图 3-31 桥接模式

效果:桥接模式最大的优点在于使抽象和实现可以独立地变化。如果软件系统需要在构件的

抽象角色和实现角色之间增加更多的灵活性,那么可以使用该模式。 行为型模式定义了系统内对象间通信以及复杂程序中的流程控制。下面以描述策略模式为例,

对行为型模式作进一步的介绍。

模式名称:策略模式 问题:在软件系统中,多个算法之间通常具有相似性。它们的单独实现将增加代码的冗余度,

增大系统的开销。 解决方案:把一系列的算法封装为具有共同接口的类,将算法的使用和算法本身分离,如图

3-32 所示。Context 表示算法使用的上下文环境,它含有对算法 Strategy 的引用。Strategy 抽象了所

有具体策略,形成了一个共同的接口。ConcreteStrategyX 和 ConcreteStrategyY 代表具体的算法实现。

图 3-32 策略模式

效果:策略模式降低了代码的耦合度,当系统的业务策略改变时,仅需要少量的修改即可。 若想熟悉其他模式,请参见表 3-1。

表 3-1 设计模式的定义

分类 模式名称 定 义

工厂 提供了一个简单的决策层,能够根据提供的数据返回一个抽象基类的多个子类中的一个 创建型

模式 抽象工厂 提供了一个创建并返回一系列相关对象的接口

软件工程——理论与实践

118

续表

分类 模式名称 定 义

单件 在某个类只能有一个实例的前提下,提供了一个访问该实例的全局访问点

构造器 将对象的构建与表示分离 创建型

模式 原型 先实例化一个类,然后通过该类来创建新的实例

适配器 可以将一个类的接口转换成另一个接口,从而使不相关的类在一个程序里一起工作

桥接 将抽象部分和实现部分分离

组合 组合就是对象的集合,可以构建部分—整体层次结构或构建数据的树形表示

装饰 可以在不需要创建派生类的情况下改变单个对象的行为

外观 可以将一系列复杂的类包装成一个简单的封闭接口,从而降低程序的复杂性

享元 用于共享对象,其中的每个实例都不包含自己的状态,而是将状态存储在外部

结构型

模式

代理 通常用一个简单的对象代替一个比较复杂的、稍后会被调用的对象

责任链 把请求从链中的一个对象传递到下一个对象,直到请求被响应

命令 用简单的对象表示软件命令的执行

解释器 提供一个把语言元素包含在程序中的定义

迭代器 提供了一个顺序访问一个类中的一系列数据的方式

中介者 定义了一个简化对象之间通信的对象

备忘录 定义了保存一个类的实例的内容以便日后能恢复它的方式

观察者 可以把一种改动通知给多个对象

状态 允许一个对象在其内部状态改变时修改它的行为

策略 将算法封装到类里

模板方法 提供了算法的抽象定义

行为型

模式

访问者 在不改变类的前提下,为一个类添加多种操作 设计模式和风格的运用在工程学科中无处不在。

——Mary Shaw 和 David Garlan

3.7 分布式系统结构

在 20世纪 80年代之前,计算机主要采用集中式结构,主流应用基本都是使用大型机/小型机计算模型。这种计算模型是通过一台物理宿主机连接多个非智能终端来完成应用程序。在多用户

环境中,用户的交互、数据处理等全部由宿主机完成,终端只负责显示和输入。由于数据的爆炸

性增长,对宿主机的要求越来越高,部署成本也随着升高,高昂的成本使得一般人根本无条件使

用,严重阻碍了计算机的普及。 20世纪 80年代之后,PC开始出现,其相对低廉的使用成本使其得到了迅猛的发展。随着网

络技术的成熟,个人计算机和工作站的分布式组网结构永久地改变了大型机/小型机计算模型,从而产生了分布式计算模型。如今,只有在一些有密集数据处理要求,使用分布式系统不能胜任的

第 3章 软件设计

119

地方,比如数据中心、银行核心业务等,大型机/小型机计算模型仍旧占据牢固的统治地位。 目前,硬件技术的发展有两个主要趋势: (1)多处理器的计算机系统正在更广泛地进入小型办公场所,比如基于 x86/x64结构的Window

NT、Unix/Linux、Mac OS 等,甚至是如今正在兴起的移动设备(如高端智能手机)都已经有多核产品在市场上流行; (2)这些设备通过网络互联在一起,形成无数的物理局域网或虚拟局域网(如 VPN)。 分布式计算模型主要具有以下的优点: (1)资源共享。分布式系统允许硬件、软件等资源共享使用。 (2)经济型。分布式系统的使用成本要远低于大型机/小型机系统。 (3)性能和可扩展性。通过越来越多的设备互连以及高效的任务分配,分布式系统的性能正

在接近甚至超越大型机/小型机系统的性能。而且,分布式系统天生的高可扩展性是大型机/小型机系统望尘莫及的。 (4)固有分布性。有些应用是固有分布的,如遵循客户机/服务器模型的数据库应用程序,这

类应用只能部署在分布式系统中。 (5)健壮性。多数情况下,分布式系统中某些节点的崩溃并不会危及整个系统(但中心节点,

如文件服务器等例外,但这类通常会采用热备份系统及时接管工作)。

3.7.1 多处理器体系结构

多处理器系统是分布式系统的最简单模型,系统同时运行许多进程,这些进程分布在不同的

处理器上,可以极大地提高系统的性能。 由于大型实时系统对响应时间要求很高,故多采用这种模型。大型实时系统需要实时采集信

息,并利用采集到的信息进行决策,然后发送信号给执行机构。虽然信息采集、决策和执行可以

在一个处理器上统一调度完成,但多处理器的并行计算比单处理器的分时片计算能极大地提高系

统的性能,而且可靠度也相对较高。

3.7.2 客户机/服务器体系结构

客户机/服务器(Client/Server,C/S)体系结构是为了共享不对等的资源而提出来的,是 20世纪 90年代成熟起来的技术,C/S体系结构定义了客户机如何与服务器连接,以将数据和应用系统分布到多个处理机上。

C/S体系结构有 3个主要的组成部分: (1)服务器。负责给其子系统提供服务,如数据库服务器提供数据存储和管理服务,文件服

务器提供文件管理服务,搜索服务器提供数据检索等。 (2)客户机。通常是独立的子系统,通过向服务器请求约定的资源获取数据。一台服务器可

以同时为许多客户机提供服务。 (3)网络。连接服务器和客户机。有时客户机和服务器位于同一台物理主机上,但多数情况

下它们分布在不同主机上。网络可以有各种形式,包括有线和无线等。 在 C/S体系结构中,客户机可以通过远程调用获取服务器提供的服务,因此,客户机必须知

道服务器的地址和它们提供的服务。 C/S系统的设计必须考虑应用系统的逻辑结构。在逻辑上,我们通常将应用系统划分为 3层,

即数据管理层、应用逻辑层和表示层。数据管理层主要处理数据存储和管理操作,一般由成熟的

软件工程——理论与实践

120

关系型数据库来承担这部分工作。应用逻辑层处理与业务相关的逻辑。表示层处理用户界面以及

用户的交互。在集中式系统中,不需要将这些清楚地分离,但在分布式系统中,不同层常常被部

署在不同的主机上,因此必须严格地分离不同层。 如图 3-33所示是典型的 C/S分布式结构,各类客户机设备通过有线或无线的 Internet或 Intranet

连接到服务器,而服务器则通过以太网连接数据库和文件服务器以及其他外设。

图 3-33 C/S体系结构

C/S体系结构通常有两层或三层,也可根据需要划分为更多层。 两层 C/S结构一般有两种形态。 (1)瘦客户机模型。在瘦客户机模型中,数据管理和应用逻辑都在服务器端执行,客户机只

负责表示部分。瘦客户机模型的好处是业务核心逻辑都在服务器端执行,安全性相对较高,但缺

点是所有的负荷都放在了服务器端,无疑加重了服务器端的负担,而且也增大了通信的网络流量,

也不能发挥客户机的计算能力。最初的浏览器其实就是瘦客户机的变种(当然, Javascript 等应用也正在将越来越多的计算处理转移到客户端部分)。 (2)胖客户机模型。在这种模型中,服务器只负责对数据的管理。客户机上的软件实现应用

逻辑以及与系统的交互。胖客户机模型能够充分利用客户机的处理能力,在分布处理上比瘦客户

机模型高效得多。但另一方面,随着企业应用规模的日益增大,软件的复杂度在不断提高,胖客

户机模型逐渐暴露出以下缺点。 ● 开发成本高。C/S体系结构对客户机软硬件配置要求较高,尤其是软件的不断升级,对硬

件处理能力要求不断提高,增加了整个系统的成本,同时使得客户端越来越臃肿。 ● 用户界面风格不一,使用繁杂,不利于推广使用。 ● 软件移植困难。采用不同开发工具和平台开发的软件之间一般不兼容,所以难以移植到

其他平台上运行。有时不得不因此开发针对另一平台的版本。

第 3章 软件设计

121

● 软件维护和升级困难。由于应用程序安装在客户机上,需要维护时,必须升级和维护所有的客户端。 两层 C/S结构中,一个重要问题是将 3个逻辑层(数据管理层、应用逻辑层和表示层)映射

到两个系统。如果使用瘦客户机模型,则存在伸缩性和性能问题;如果使用胖客户机模型,则可

能存在系统管理上的问题。 三层 C/S结构就避免了这个问题,将数据管理层和应用逻辑层分别放在两个物理层或物理主

机上,客户端仍然保留在客户机上。对于三层 C/S结构,各层的功能或职责如下: (1)表示层。表示层是应用系统的用户界面部分,担负着用户与应用程序之间的对话功能。

比如检查用户的输入,显示应用的输出等,通常采用图形界面的方式呈现。 (2)应用逻辑层。应用逻辑层为应用系统的主体,包含全部的业务逻辑。比如数据处理,用

户管理,与其他系统交互以及记录系统日志等。通常是应用服务器。 (3)数据层。数据层一般只负责数据的存取、管理和维护(如备份等),通常是关系型数据库

服务器。 三层 C/S结构的优点如下: (1)通过合理地划分三层结构,使之在逻辑上保持相对独立性,提高系统的可维护性和可扩

展性。 (2)能更灵活地选用相应的平台和应用系统,使之在处理负荷能力上与处理特性上分别适应

各层的要求;并且这些平台和组成部分可以具有良好的可升级性和开放性。 (3)应用的各层可以独立地并行开发,每层可以根据自己的特点选用合适的开发语言。 (4)安全性相对较高,因为应用层屏蔽了客户直接访问数据库的权利,使得未授权用户或黑

客难以绕过功能层直接获取敏感数据,为数据的安全管理提供了系统结构级的支持。 但三层结构必须细心地设计通信模块(通信方法、通信频度、数据流量等),一旦通信成为瓶

颈,那么应用服务器和数据服务器的性能再高也无法发挥出来。这和如何提高各层的独立性一样

是三层结构设计的核心问题。 浏览器/服务器(Browser/Server,简称 B/S)结构是三层应用结构的一种实现,其具体结构为

浏览器/Web 服务器/数据库服务器。B/S 结构利用不断成熟的 WWW 浏览器技术,结合多种脚本语言,用通用的浏览器就可以实现原来需要复杂的专用软件才能实现的强大功能,尤其是近年来

流行的 Javascript以及基于其上的 Ajax等技术。而且,越来越多的浏览器开始支持 HTML5标准(尽管正式的标准还未发布),B/S结构能实现的功能越来越接近甚至可以跟 C/S结构相媲美。

但 B/S结构有一些 C/S结构所无法企及的优势,比如: (1)基于 B/S体系结构的软件,系统安装、修改和维护全在服务器端进行。用户使用时,仅

仅需要一个浏览器(而且浏览器如今已成为各类操作系统标配的一部分)即可使用全部功能,实

现了“零客户端”,升级维护十分容易。 (2)B/S 结构提供异种机、异种网、异种应用服务的联机、联网和统一服务的最现实的开放

性基础。

3.7.3 分布式对象体系结构

在客户机/服务器模型中,客户机和服务器的地位是不同的。客户机必须知道服务器的存在以及其提供什么样的服务,而服务器无需知道客户机的存在(HTTP 协议本身就是一个无状态协议)。在设计者设计系统时,设计者必须考虑服务在何处以何种方式提供,而且系统的伸缩性必须考虑,

软件工程——理论与实践

122

尤其是当大量客户机同时访问系统时,如何平衡负载。 分布式系统设计的更一般方法是去掉客户机与服务器之间的差异,用分布式对象体系结构来

设计系统。分布式对象的实质是在分布式异构环境下建立应用程序系统框架和对象构件,将应用

服务分割成功能独立的构件,各个构件可以放在同一台或不同的多台服务器上运行。构件之间的

通信最通常的设计方法是通过一个中间件通信,类

似计算机中主板上的数据总线。中间件一般称为软

件总线或对象请求代理,它的作用是在对象之间提

供一个无缝接口,如图 3-34所示。 分布式对象技术的应用目的主要是为了降低

服务器负荷,共享网络的资源,平衡分配计算任务

到不同的主机,提高系统的协同处理能力。分布式

对象技术的基础是构件,构件是独立的代码封装体,可以是一个简单的对象,也可以是对象的组

合体。当前的主流分布式对象技术规范有 OMG的 CORBA、Microsoft的.NET和 Sun公司的 J2EE。

3.7.4 对等端体系结构

对等端体系结构可以视为客户端/服务器体系结构和分布式对象体系结构的融合。它没有严格的客户机、服务器划分,所有的分布的对等端根据需要既能充当服务器,又能充当客户端。但有

些情况下,对等端体系结构仍然需要设计一个端节点服务器,用于存储端节点信息。在通信之时,

对等端首先连接到端节点服务器上,下载可用的对等端节点信息。之后的通信就是根据这些端节

点信息连接到其他对等端请求信息,这时,该节点常常充当客户端,其他被请求的端充当服务器。 对等端体系结构常常用于数据共享类系统的设计。比如多数下载软件使用的 P2P

(peer-to-peer)模式,下载开始时,首先从服务器请求资源列表,然后连接到列表中的资源上请求数据分包。如果有很多节点拥有资源,就能同时从这些节点上请求分包,所以理论上,P2P 模式通信速度的上限就是请求节点网络速度的上限。P2P 模式还有一种变种,有时网络中不存在拥有资源的对等节点或数量很少,这时端节点服务器也能充当对等端,这样的体系结构叫做

P2SP模式。 对等端体系结构也用于设计一些难以存在稳定服务器的特殊环境中使用的系统。比如利用车

载网络传输数据,所有车辆的位置都是无法提前精确预测的,此时的通信节点只能通过自组织的

方式进行连接。

3.7.5 代理

代理可以用于构件包含隔离组件的软件系统,软件通过远程服务调用进行交互。代理者负责

协调通信,诸如转发请求和传递结果、异常等。 1991 年,OMG 基于面向对象技术,给出了以对象请求处理(ORB)为中心的分布式应用体

系结构,如图 3-35所示。 在 OMG的对象管理结构中,ORB是核心通信机制,以实时互操作性为主要目标,处理对象

之间的消息交互。 在 ORB上有 4个对象接口。 (1)对象服务:定义加入 ORB 的系统级服务,如安全性、命名、事务处理,这类与应用领

域无关。

图 3-34 分布式对象体系结构

第 3章 软件设计

123

图 3-35 以 ORB为中心的分布式应用体系结构

(2)公共设施:定义应用程序级服务。 (3)领域接口:面向特定领域接口。 (4)应用接口:面向指定的外界应用,一般是供应商或用户借助 ORB、公共对象服务以及公

共设施而开发的特定产品。

3.8 体系结构框架

3.8.1 模型-视图-控制器

MVC(Model-View-Controller 模型-视图-控制器)模型由 Trygve Reenskaug 博士在 20 世纪70年代提出,并在最早的面向对象编程语言 Smalltalk-80中实现。

MVC 强调将用户的输入、数据模型和数据表示方式分开设计,一个交互式应用系统由模型、视图、控制器 3部分组成,分别对应内部数据、数据表示和输入/输出控制部分,结构图如图 3-36所示。

图 3-36 MVC模型处理流程图

(1)模型。模型对象代表应用领域中的业务实体和业务逻辑规则,是整个模型的核心,独立于外在的显示内容和显示形式。模型对象的变化通过事件通知视图和控制器对象,采用了发布者/订阅者方式,模型是发布者,视图和控制器是订阅者。对于模型来说,并不知道自己对应的视图

控制器;但控制器可以通过模型提供的接口改变模型对象,接口内封装了业务数据和行为。 (2)视图。视图对象代表 GUI对象,以用户熟悉和需要的格式表现模型信息,是系统与外

界的交互接口。视图订阅模型可以感知模型的数据变化,并更新自己的显示。视图对象也可以

包含子视图,用于显示模型的不同部分。在多数的 MVC 实现技术中,视图和控制器常常是一一对应的。 (3)控制器。控制器对象处理用户的输入,并给模型发送业务事件,再将业务事件解析为模

型应执行的动作;同时,模型的更新与修改也将通过控制器来通知视图,保持视图与模型的一致。

软件工程——理论与实践

124

MVC的整个处理流程为:系统拦截到用户请求,根据相应规则(多数采用路由技术),将用户请求交给控制器,控制器决定哪个模型来处理用户的请求;模型根据业务逻辑处理完毕后,将结果

返回给控制器;然后控制器将数据提交给视图;视图把数据组装之后呈现给用户。其中,模型处理

所有的业务逻辑和规则,视图只负责显示数据,控制器负责用户的请求,这样将业务和表现层分离,

以便业务代码可以被用于任何相似的业务中,视图代码也可以根据需要随意替换。相比于传统将业

务逻辑和视图混合在一起的实现方式,MVC可以最大化地重用代码,且灵活性极高。

MVC的发展史与挪威船运

1973 年,挪威奥斯陆的 Central Institute for Industrial Research 的 Trygve Reenskaug 教授坐

在当地造船厂中(挪威当地有很多类似的造船厂),对着进进出出的船沉思,希望设计出一个更

好的信息管理系统。看着船只在船厂中进进出出,思考着与建造船只有关的过程,Reenskaug开始构思在模块化和过程与角色分离的基础上进行系统设计。这些内容都在其里程碑式的论文

“Administrative Control in the Shipyard”中提出来: 现代的船舶是一项极为复杂的产品,需要各种技术、生产材料和机器的密切配合…… 本论文将提供一个通用的框架,目的是为了构件用于数据管理目的的各种数据处理系统。

架构是建立在 Communicating Information Processes 原则的基础上。其主要目标是建立一个新的

信息系统来找到组织事物的现有方法,最终得到的系统应具有足够的弹性以轻松适应组织中的

变化。 这篇论文的主要思想可以总结为以下几个方面: ● 重写任何系统的能力 ● 模块化、可插入的透明子系统的存在 ● 每个系统的细分 ● 系统的可伸缩性 对于 Reenskaug 博士来说,最宝贵的事情是他的思想最终依靠的原则成了面向对象编程

(OOP)。1973 年,虽然几年前 Simula 就开始生产 Smalltalk,OOP 的概念也开始出现,但却没

有任何的主流编程语言支持 OOP。那是一个程序的世界,至少大部分情况下是如此。仅仅过了

几年,Reenskaug 就发现自己深深地陷入到了面向对象方法论的研究当中。 1978 年夏天,Reenskaug 博士作为访问科学家在美国加利福尼亚州的 Palo Alto 度过了一年

的时间。在那里,他接触到了 Smalltalk-80—最早的面向对象编程语言之一。使用 Smalltalk,Reenskaug 博士可以进一步提炼他的 Shipyard 思想并将其综合处理成一个新的体系结构模式:

1978 年,我在 Xerox PARC 上实现并编写了最初的 MVC 笔记……MVC 本质的目标是为了

弥合人类用户的精神模型与计算机中存在的电子模型之间的差距。理想的 MVC 解决方案支持

用户直接看到和操纵域信息的构想。如果用户需要从不同的上下文中和/或从不同的视角同时看

到相同的模型元素,这个结构是很有用的。 —“MVC Xerox PARC,1978-79”

http://heim.ifi.uio.no/~trygver/themes/mvc/mvc-index.html

自那以后,MVC 模式逐渐发展成为计算机科学中最受欢迎的应用程序模式之一。这种减少复杂度以及分割应用程序责任的能力极大地支持开发人员构建可维护性更高的应用程序——这正

是我们希望通过 ASP .NET MVC能够发展并构建的能力。

知识小卡片

第 3章 软件设计

125

MVC应用非常广泛,既可以应用于本地系统,也可以用于分布式系统,但MVC的最大用武之处在当今的 Web 应用上。尤其是 2004 年美国人 David 使用 Ruby 语言构建使用 MVC 模式的Rails开发框架以来,越来越多的基于MVC的框架开始涌现。 如今,主流的MVC框架有基于 Ruby的 Rails,基于 Python的 Django,基于 Java的 Structs、

Spring和 JSF,基于 PHP的 Zend,基于.NET的MonoRail以及另一个被视为最具潜力的微软的架构 ASP.NET MVC(当前版本为 ASP.NET MVC 3,与 ASP.NET WebForm一起成为微软目前最强大的两种Web开发框架,两者各有所长)。

3.8.2 模型-视图-表示器

模型-视图-表示器(Model-View-Presenter,MVP)是近年来流行起来的一种体系结构。从名字上就可以看出,MVP与 MVC十分类似,事实也确实如此。甚至有程序员开玩笑说 MVP不过是将MVC中的 C换成了字母 P,这种说法一定程度上确实有些道理。

MVP 与 MVC 的主要差异体现在“请求在何处访问系统”以及“各部分如何联系在一起”。MVP的处理流程如图 3-37所示。

图 3-37 MVP模型处理流程图

(1)用户直接与视图进行交互(图中步骤 1)。 (2)视图通过引发一个事件,通知表示器有事件发生(步骤 2),然后表示器访问视图通过其

IView接口公开的属性(步骤 3)。这些属性是视图实际 UI元素的包装器。 (3)此后表示器调用模型(步骤 4),再返回结果(步骤 5)。 (4)表示器转换数据,然后设置 UI的值,该操作通过 IView接口完成(步骤 6)。 (5)视图将最终页面显示给用户(步骤 7)。 MVP中的视图比MVC中的视图更加“被动”,视图引发事件,但是由表示器读取并设置 UI

的值。事实上,MVP模式设计的目的就是为了增强MVC模式,以尝试使视图更加被动,以便更换视图更加容易。

但 MVP 模式存在的问题是视图和表示器之间的联系比 MVC 模式中更加复杂,每个视图都有自己的接口,并且视图的接口特定于页面的内容,所以难以委托框架来创建视图,而

必须由程序员手工完成创建。这也是 Microsoft 等公司采用 MVC 实现框架而不用 MVP 的 原因。

3.8.3 J2EE 体系结构框架

MVC是很多现代体系结构框架的基础,主要应用于企业和电子商务系统中。J2EE的核心体系结构就是在 MVC 框架的基础上进行扩展得到的,如图 3-38 所示。J2EE 模型是分层结构,中间的 3层(表示层、业务层和集成层)包含应用构件,客户层和资源层处于应用的外围。

软件工程——理论与实践

126

图 3-38 J2EE的核心体系结构框架

(1)客户层。客户层是用户与系统交互的入口。该层可以是各种类型的客户端,比如 C/S客户端、浏览器、移动设备等。 (2)资源层。资源层可以是企业的数据库、电子商务解决方案中的外部系统或者 SOA服务。

数据可以采用分布式方式部署在多个服务器上。 (3)表示层。表示层也称为 Web 层或服务器端表示层,是用户和应用之间的桥梁。在基于

Web的应用系统中,表示层由用户界面代码和运行在Web服务器或应用服务器上的应用程序组成。参考MVC框架,表示层包括视图和控制器部分。 (4)业务层。业务层包含业务逻辑和应用逻辑。负责确认和执行企业范围内的业务规则和事

务,并管理从资源层加载到应用程序中的业务对象。参考MVC框架,业务层包括模型部分。 (5)集成层。集成层负责建立和维护与数据源的连接。例如,通过 JDBC与数据库通信,利

用 Java消息服务(JMS)与外部系统联合等。 在企业与电子商务系统的开发和集成中,产生了多种经过较大调整、关注不同复杂度的 J2EE

技术。这些技术支持 MVC 的实现,比如 Struts。有些技术还扩展了企业服务,如 Spring 框架技术和应用服务器(如 JBoss、Websphere应用服务器)。在应用服务器中,与 JMS实现集成则将应用领域扩展到了电子商务。

3.8.4 PCMEF

表示-控制-中介-实体-基础(Presentation-Control-Mediator-Entity-Foundation,PCMEF)是一个垂直层次的分层体系结构框架。每一层是可以包含子包的包。

PCMEF 框架包含 4 层:表示层、控制层、领域层和基础层。领域层包含两个预定义的包:实体(Entity)和中介(Mediator)。参考MVC框架,表示层对应MVC中的视图,控制层对应MVC中的控制器,领域层的实体对应MVC中的模型。MVC中没有与中介和基础层对应的部分,因为 MVC 本身只是上层框架,中介和基础层多使用底层框架实现。

PCMEF框架中包的依赖性主要是向下依赖,如图 3-39所示。表示层依赖于控制层,控制层依赖于领域层,中介层依赖于实体

和基础层。 (1)表示层。该层包含定义 GUI对象的类。在微软操作系统

中,很多表示类是MFC(微软基础类)的子类。在 Java环境中,表示类可以建立在 Java Swing基础类库上。用户通过表层与系统通信。因此,包含主函数的类常常处于表示层中。 (2)控制层。该层处理表示层的请求,负责大多数程序逻辑、算法、业务计算以及维护用户会话等。

图 3-39 PCMEF框架结构图

第 3章 软件设计

127

(3)领域层。该层包含代表“业务对象”的类,很多实体类是容器类。领域层的实体包处理控制请求。中介包创建协调实体类和基础类的通信信道。协调工作主要有两个目的:一方面是为

了隔离包,这样当一个发生变化时不会直接影响到另一个;二是当需要从数据库中读取新的实体

对象时,控制类不需要直接与基础类通信。 (4)基础层。该层负责Web服务与数据库的所有通信,管理应用程序所需要的所有数据。

3.8.5 PCBMER

现在主流使用的是 PCMEF框架的扩展,划分为 6个层次,意思是表示-控制器-Bean-中介-实

体-资源(Presentation-Controller-Bean-Mediator-Entity-Resource,简称 PCBMER),如图 3-40 所示。PCBMER 遵循了当前体系结构设计中广泛认可的发展趋势。 和 PCMEF 类似,PCBMER 体系中各层也用包

来表示并具有向下依赖关系。例如,表示层依赖于

控制器层和 Bean层,控制器层向下依赖于 Bean、中介和实体层等。但 PCBMER框架各层之间并不是严格线性依赖的,一个上层可以依赖多个相邻下层。 (1)表示层。表示呈现给用户的 UI 对象。当

Bean改变时,表示层负责维护表示层上的数据一致性,所以表示层依赖于 Bean 层。这种依赖可以两种方式实现,可以使用拉模型直接调用方法(信息

传递)来实现,也可以使用推模型(或推拉模型)

通过消息传递及事件处理来实现。 (2)Bean层。表示那些预定呈现给用户界面的

数据类和对象。除了用户输入外,Bean数据由实体对象(实体层)创建。由于 Bean 层不依赖于其他层,所以 PCBMER框架并没有指定或核准对 Bean对象的访问是通过消息传递还是事件处理。 (3)控制器层。表示应用逻辑,控制器响应来自表示层的 UI 请求,UI 请求可以是菜单的选

择、按钮的按下或者 Http请求的 get或 post。 (4)中介层。该层建立实体类和资源类媒介的通信管道,管理业务处理,强化业务规则,实例化

实体层的业务对象。中介的用途主要有两个:一是隔离了实体层和资源层,这样当两者中的一个发生

改变之时,不会直接影响到另一个;二是当控制器发出数据请求但不确定数据已经加载还是尚未读取

时,中介在控制器层和实体/资源层之间充当媒介。中介还常常用于管理应用程序的高速缓冲存储器。 (5)实体层。响应控制器和中介层。由描述“业务对象”的类组成,在程序的空间中存储从

数据库取回的对象数据,或者为了存入数据库而创建对象。多用容器类实现。 (6)资源层。负责所有与外部持久数据资源的通信,如建立数据库连接和 SOA服务,创建持

久数据查询以及启动数据库事务等。 现在很多大型商务平台的开发使用这种框架,比如基于.NET 平台的系统中,常常使用

ASP .NET MVC构建上层应用,中间使用领域驱动技术设计业务层,底层则使用 LinqToSQL技术和 Entity Framework构建,甚至进一步将整个系统封装在 IoC(Inversion of Control,控制反转)

图 3-40 PCBMER框架结构图

软件工程——理论与实践

128

容器中以实现低耦合。

3.9 利用 Visio 绘制网上书店系统的结构图

在第 2章的实践部分,我们绘制出了网上书店系统的三层数据流图,本节我们将在底层数据流图的基础上,运用面向数据流的方法对该系统进行设计,得到网上书店系统的结构图。设计的

过程可以分为以下 3步。 (1)区分数据流中的变换型数据流和事务型数据流。 (2)对于变换型数据流,识别变换型数据流中的输入流、变换流和输出流;对于事物型数据

流,识别事务中心和数据接收通路。 (3)设计软件系统结构,绘制系统结构图。 在本章的理论部分,我们了解了变换型数据流和事务型数据流的相关概念。变换型数据流强

调对输入信息流的加工与处理,而事务型数据流强调根据输入信息流的特征,在若干处理方式中

选择一个合适的加工。以网上书店系统的订购图书数据流图和订单信息查询数据流图为例,我们

可以分辨出:订购图书数据流图中的数据流为变换型数据流,而订单信息查询中的数据流为事务

型数据流,其中“分析查询”为其事务中心。 下面分别以“订购图书”和“订单信息查询”的设计为例,介绍利用数据流图绘制系统结构

图的方法。 对于变换型数据流,要重点识别变换型数据流中的输入流、变换流和输出流。输入流对应的

输入控制模块完成数据输入及与数据输入相关的操作。变换流对应的中心控制模块包括所有对数

据的核心操作。输出流对应的输出控制模块协调输出信息的产生过程。经分析,“订购图书”具有

边界的数据流图如图 3-41所示。

图 3-41 订购图书具有边界的数据流图

第 3章 软件设计

129

图 3-41中用虚线标识了 3个区域。自左向右,这 3个区域分别为输入部分、数据处理部分和输出部分。可见,“登录系统”流程属于输入部分。模块内部对数据的变换处理包括“书籍信息查

询”和“订单登记与提交”。“显示订单”为输出部分。 根据“订购图书”具有边界的数据流图,我们可以将其映射为结构图,如图 3-42所示。

图 3-42 订购图书的结构图

对于事务型数据流图,可以通过事务分析得到对应的结构图。在事务分析的过程中,重点在

于对事务中心的识别。在“订单信息查询”的数据流图中,“分析查询”为其事务中心,如图 3-43所示。

图 3-43 订单信息查询的事务中心

对于每一个事务中心,外界必须输入相应的信息来帮助系统判断将选择何种事务处理方式。

例如,在“订单信息查询”中,必须输入有关查询类型选择的信息来使系统判断在 3种查询方式(按订单编号查询、按日期查询、按会员编号查询)中选择哪一种。这样,输入部分不仅包括与登

录信息相关的数据,还包括查询类型信息。 经分析,“订单信息查询”的结构图如图 3-44所示。 根据本节所介绍的方法,可以利用 Visio绘制网上书店系统其他功能的结构图。

软件工程——理论与实践

130

图 3-44 订单信息查询的结构图

3.10 利用 Rose 绘制网上书店系统的顺序图

系统顺序图是根据用例来组织的,用例图描述用户与系统之间的交互过程,而系统顺序图则显

示出随着时间的变化,对象之间是如何通信的。顺序图主要包含的模型元素有对象、消息和时间。 顺序图是一个二维图形,其水平方向为对象维,沿水平方向排列参与交互的对象类角色;竖

直方向为时间维,沿垂直向下方向按时间递增顺序列出各对象类角色所发出和接收的消息。消息

表示对象之间的通信,在顺序图中消息用对象角色之间的一条水平带有箭头的直线表示,方向为

从源对象指向目标对象,其上标有消息的内容。 网上书店系统中“登录注册”模块的顺序图如图 3-45所示。

图 3-45 登录注册模块的顺序图

通常,顺序图中的类或对象包括用户、与界面相关的类或对象、与控制逻辑相关的类或对象

以及与数据库中的关系表相关的类或对象。在图 3-45中包含操作员、用户登录界面、用户登录控

第 3章 软件设计

131

制类和系统用户实体类。每个对象下有一条竖直的虚线,它表示该对象的生命线,象征对象的生

命周期。生命线上有若干矩形框,这些矩形框代表对象处在激活期,即正在执行某个动作。生命

线末尾的叉形图标代表对象生命周期的结束。对象之间通过发送消息进行通信,比如“登录系统”、

“验证用户身份”、“查找用户记录”等。这些消息按照从上往下的时间顺序排列。 我们可以利用 Rational Rose 2003来绘制该顺序图。在 Rational Rose 2003中,顺序图的建模

符号如图 3-46所示。 下面,以网上书店系统的“登录注册”模块的顺序图为例,具体介绍利用 Rational Rose 2003

来绘制顺序图的方法。 (1)创建一个新的顺序图。通常,顺序图根据用例图来组织,即顺序图反映用例内部的对象

的交互方式,一个顺序图对应着一个用例图。在浏览窗口中,右击“登录注册”用例,依次选择

“New”和“Sequence Diagram”,如图 3-47所示。得到新的顺序图后,将其命名为“登录注册”。

图 3-46 顺序图的建模符号 图 3-47 创建顺序图

(2)绘制顺序图中的对象。打开顺序图后,单击工具栏中的对象图符,然后在编辑区的合适位置单击鼠标,即可得到一个对象。同时,对对象的名称进行编辑,如图 3-48所示。

图 3-48 添加对象或类

(3)在对象之间添加消息。单击工具栏中的相应的消息图标,然后在编辑区相应的对象的生命线之间划一条线,再编辑消息内容即可。注意,对象之间的消息、对象发送给自身的消息以及

返回的消息具有不同的图标。 (4)输入消息内容。双击表示消息的箭头,在弹出的对话框的Name字段里输入要添加的文本。 (5)在每个对象的生命线末端绘制生命线的终止符图标,表示该对象生命周期的结束。 如果整个顺序图的布局不合理,可以拖动各图符,使图形均匀。最后便可得到完整的顺序图。

软件工程——理论与实践

132

根据本节所介绍的方法,可以利用 Rose绘制网上书店系统的其他模块的顺序图。

3.11 软件设计说明书编写指南

对于大型软件项目,在设计阶段一般要完成概要设计说明书、详细设计说明书和数据库设计

说明书。对于中、小型软件项目,上述 3种说明书可以合并为软件设计说明书。 在实际完成设计阶段的相关文档时,可以不必拘泥于模板的内容和格式,而是应该根据项目

的特点和实际情况对模板有所剪裁。 另外,将概要设计说明书、详细设计说明书和数据库设计说明书合并为一份软件设计说明书

时,可以根据对待开发系统的设计程度、项目特点及开发人员的能力,恰当地选取概要设计说明

书、详细设计说明书和数据库设计说明书模板中的内容,对其在最终的文档中进行描述,而不需

要面面俱到,把 3份文档机械地合在一起。

1 引言

本章对该文档的目的、功能范围、术语、相关文档、参考资料、版本更新进行说明。 1.1 编写目的

本文档的目的旨在推动软件工程的规范化,使设计人员遵循统一的设计书写规范,节省制作

文档的时间,降低系统实现的风险,做到系统设计资料的规范性与全面性,以利于系统的实现、

测试、维护、版本升级等。 1.2 命名规范

变量对象命名规则:申明全局变量、局部变量对象的命名规则。 数据库对象命名规则:申明数据库表名、字段名、索引名、视图名等对象的命名规则。

1.3 术语定义

列出本文件中用到的专门术语的定义和外文首字母缩号词的原词组。 1.4 参考资料

列出有关的参考文件,如: ● 本项目的经核准的计划任务书或合同,上级机关的批文; ● 属于本项目的其他已发表的文件; ● 本文件中各处引用的文件、资料,包括所要用到的软件开发标准。 列出这些文件的标题、文件编号、发表日期和出版单位,说明能够得到这些文件资料的来源。

1.5 相关文档

1.6 版本更新记录

版本更新记录格式见表 1。

表 1 版本更新记录

版本号 创建者 创建日期 维护者 维护日期 维护纪要

V1.0 王林 2009/02/18 — — —

V1.0.1 — — 李丽 2009/02/26 E-R图维护

第 3章 软件设计

133

2 总体设计

2.1 总体结构设计

用一览表及框图的形式说明本系统的系统元素(各层模块、子程序、公用程序等)的划分,

简要说明每个系统元素的标识符和功能,分层次地给出各元素之间的控制与被控制关系。 2.2 硬件运行环境设计

硬件平台: ● 服务器的最低配置要求; ● 工作站的最低配置要求; ● 外设的要求。

2.3 软件运行环境设计

软件平台: ● 服务器操作系统; ● 数据库管理系统; ● 中间件; ● 客户机的操作系统; ● 客户机的平台软件。

2.4 子系统清单

子系统清单见表 2。

表 2 子系统清单

子系统编号 子系统名称 子系统功能简述 子系统之间的关系

SS1 SS2 SS3

2.5 功能模块清单

功能模块清单见表 3。

表 3 功能模块清单

模块编号 模块名称 模块功能简述 模块的接口简述

M1-1 M1-2 M2-1 M2-2

3 模块功能分配

具有功能独立、能被调用的信息单元叫做模块。模块是结构化设计中的概念,部件是面向对

象设计中的概念。 模块功能分配的目的,就是为了将具有相同功能的模块合并,从中提取公用模块,形成

公用部件,按照构件或中间件的方式加以实现,作为本系统的公用资源,甚至作为公司级组

织的公用资源,从而充实公司级的构件库或中间件库,优化系统设计,加快开发速度,提高

开发质量。

软件工程——理论与实践

134

3.1 公用模块功能分配

公用模块功能分配见表 4。

表 4 公用模块功能分配

公用模块编号 模块名称 模块详细功能分配 模块的接口标准

G-1 G-2 G-3

3.2 专用模块功能分配

专用模块功能分配见表 5。

表 5 专用模块功能分配

专用模块编号 模块名称 模块详细功能分配 模块的接口标准

Z1-1 Z1-2 Z2-1 Z2-2

4 数据库设计

4.1 数据库表名列表

数据库表名列表格式见表 6。

表 6 数据库表名列表

序号 中文表名 英文表名 表功能说明

1 2 3

4.2 数据库表之间关系说明

可以用 E-R 图表示,也可以用文字说明。 4.3 数据库表的详细清单

每个表的详细清单内容包括表名,中文字段名,英文字段名,数据类型、宽度、精度,主键/外键,是否允许为空,取值约束(默认值、最大值、最小值),索引否。同时要指出该表的索引:

索引文件名,索引字段名,索引特性(主键索引、唯一索引、聚集索引)。用户可以根据实际情况

进行裁剪。详细清单可以用列表给出,见表 7。

表 7 表名:XXXX

序号 英文字段名 中文字段名 数据类型、宽度、精度 取值约束 是否允许为空 主键/外键 索引否

1 2 3

4.4 视图设计

视图设计中要给出视图的中文名、英文名,视图中的中文列名、英文列名、类型、宽度、精

度,每一列的具体算法,对应的基本表名。

第 3章 软件设计

135

5 其他设计

本章描述前面没有说明的设计,如接口设计、每个功能模块的详细设计、存储过程设计、角

色授权设计等。 6 系统出错处理设计

6.1 出错信息

说明每种可能的错误或故障情况出现时,系统输出信息的形式、含义及处理方法。 6.2 故障预防与补救

说明故障出现前的预防措施以及出现后可能采取的变通措施。 6.3 系统维护设计

说明为了系统维护的方便而在程序内部设计中做出的安排,包括在程序中专门安排用于系统

的检查与维护的检测点和专用模块。 7 测试计划

说明对本程序进行单元测试、集成测试及系统测试的计划,包括对测试的技术要求、输入数

据、预期结果、进度安排、人员职责、设备条件驱动程序及桩模块等的规定。

3.12 网上书店系统的软件设计说明书

1 引言

1.1 编写目的

在完成网上书店系统需求分析的基础上,我们依据网上书店系统《需求规格说明书》对网上

书店系统进行了设计。为了文档化对系统的设计,编写本文档。本文档主要供团队在具体实现网

上书店系统时参考使用。 1.2 命名规范

数据库表名、字段名用大写开头的英文命名。 私有变量用“_”开头的小写英文命名。其他的变量用大写英文字母开头。 所有的函数用大写英文字母开头。

1.3 术语定义

总体结构:软件系统的总体逻辑结构,本系统采用面向对象的方法对系统进行设计。 概念数据模型(CDM):关系数据库的概念设计模型,主要表现为 E-R 图。 物理数据模型(PDM):关系数据库的物理设计模型。

1.4 参考资料

[1]赵池龙,杨林,孙伟. 实用软件工程(第 2 版)北京:电子工业出版社,2006. [2]网上书店系统需求规格说明书。

1.5 相关文档

网上书店系统需求规格说明书。 1.6 版本更新信息

版本更新记录见表 1。

软件工程——理论与实践

136

表 1 版本更新记录

版本号 创建者 创建日期 维护者 维护日期 维护纪要

V1.0 王明华 2009-5-15 王明华

2 总体设计

2.1 硬件运行环境

(1)CPU:Pentium III 500MHz 以上。 (2)内存大小:512MB 以上。 (3)磁盘空间容量:512MB 以上。 (4)鼠标,键盘。

2.2 软件运行环境

(1)操作系统:Windows XP。 (2)Web 服务器:IIS6.0。 (3)数据库:SQL Server 2005 Express。 (4)浏览器:IE6/IE7。

2.3 子系统清单

子系统清单见表 2。

表 2 子系统清单

子系统编号 子系统名称 子系统功能简述

SS1 登录注册

(1)会员登录系统时,对其身份进行检验和识别

(2)游客(新用户)可以进行注册

(3)已注册的用户可以修改个人信息,找回密码,注销等

SS2 浏览图书 用户可以浏览图书的目录或图书

SS3 会员购书 会员可以向购物车中添加或删除图书,可以查看购物车的信息,还可以清空

购物车

SS4 订单管理 会员可以提交订单,并可以查看个人订单信息,必要时还能取消已有订单

SS5 图书管理 管理员能够对与图书相关的各种信息进行添加、删除、查询等操作

2.4 功能模块清单

功能模块清单见表 3。

表 3 功能模块清单

模块编号 名 称 模块功能描述

SS1-1 用户注册 游客注册,成为会员

SS1-2 会员登录 会员登录系统

SS1-3 找回密码 会员将个人密码丢失后,经过审核可以重新获得密码

SS1-4 修改个人信息 会员登录后进行资料管理,如联系方式修改等

第 3章 软件设计

137

续表

模块编号 名 称 模块功能描述

SS1-5 用户注销 会员离开系统时,进行注销

SS2-1 浏览图书目录 用户根据图书类别浏览图书列表

SS2-2 浏览图书 用户浏览某本图书的详细信息

SS3-1 添加图书 会员向购物车中添加待购买的图书信息

SS3-2 查看购物车 会员查看购物车信息

SS3-3 删除图书 会员删除购物车中要购买的图书信息

SS3-4 修改图书数量 会员修改购物车中某本图书的数量

SS3-5 清空购物车 会员清空购物车中的信息

SS4-1 提交订单 会员提交订单

SS4-2 查看所有订单 会员查看所有订单信息

SS4-3 查看单个订单信息 会员根据条件查看部分或单个订单信息

SS4-4 取消订单 会员取消订单

SS5-1 查询图书 管理员对图书进行查询

SS5-2 添加图书 管理员对新增加的图书的信息进行录入

SS5-3 删除图书 管理员对特定的订单进行删除

SS5-4 修改图书 管理员对图书信息进行修改

SS5-5 会员查询 管理员查看某个会员的信息

SS5-6 订单查询 管理员对以往订单进行查询

SS5-7 订单删除 管理员对特定的订单进行删除

SS5-8 添加新折扣 管理员添加某本图书的折扣信息

3 数据库设计

3.1 数据库中表名列表

数据库中表名列表格式见表 4。

表 4 数据库中表名列表

编 号 表 名 表功能说明 编 号 表 名 表功能说明

1 Book 网上书店中书的表 4 OrderItem 订单明细表

2 Customer 会员信息表 5 Publisher 出版社表

3 Order 订单表 6 Category 书的种类表

3.2 数据库表之间的关系

数据库中的表之间的关系如图 1 所示。

软件工程——理论与实践

138

Relationship_1Relationship_2

Relationship_3

Relationship_4

Relationship_5

Book

ISBNTitleAuthorCategoryIdPublisherIdPagesWordsPublishDatePrintDateSizeEditionPriceTotalCountArrivalTimeDiscountCoverComment

<pi> Variable characters (50)Variable characters (50)Variable characters (50)IntegerIntegerIntegerIntegerDateDateVariable characters (20)IntegerFloatIntegerDateFloatVariable characters (20)Variable characters (500)

<M><M><M><M><M>

<M>

ISBN <pi>

Category

CategoryIdCategoryName

<pi> IntegerVariable characters (50)

<M><M>

CategoryId <pi>

Customer

EmailPasswordCustomerNameNickNameSexAddressPhone

<pi> Variable characters (50)Variable characters (10)Variable characters (20)Variable characters (50)Variable characters (10)Variable characters (200)Variable characters (20)

<M><M>

<M><M><M>

CustomerId <pi>

OrderItem

OrderItemIdOrderIdISBNBooksCount

<pi><pi>

IntegerIntegerVariable characters (50)Integer

<M><M><M><M>

OrderItemId <pi>

Order

OrderIdOrderDateShipDateCustomerIdAddressIsShipped

<pi> IntegerDateDateVariable characters (10)Variable characters (200)Integer

<M><M><M><M><M><M>

OrderId <pi>

Publisher

PublisherIdPublisherNamePublisherPhone

<pi> IntegerVariable characters (50)Variable characters (10)

<M><M><M>

PublisherId <pi>

图 1 数据库表之间的关系

3.3 数据库表的详细清单

Book 表见表 5。

表 5 Book表

序 号 英文字段名 中文字段名 数据类型 是否允许为空 主键/外键

1 ISBN 书号 varchar(50) 否 主键

2 Title 书名 varchar(50) 否

3 Author 作者 varchar(50) 否

4 CategoryId 类别标号 int 否

5 PublisherId 出版社编号 int 否

6 Pages 页数 int 是

7 Words 字数 int 是

8 PublishDate 出版时间 datetime 是

9 PrintDate 印刷时间 datetime 是

10 Size 开本 varchar(20) 是

11 Edition 版次 int 是

12 Price 价格 float 否

13 TotalCount 书的数量 int 是

14 ArrivalDate 到货日期 datetime 是

15 Discount 折扣 float 是

16 Cover 包装 varchar(20) 是

17 Comment 备注 varchar(500) 是

第 3章 软件设计

139

Customer 表见表 6。

表 6 Customer表

序号 英文字段名 中文字段名 数据类型 是否允许为空 主键/外键

1 Email 会员编号(用邮箱注册) varchar(50) 否 主键

2 Password 密码 varchar(10) 否

3 CustomerName 会员姓名 varchar(20) 是

4 NickName 会员别名 varchar(50) 是

5 Sex 性别 varchar(10) 否

6 Address 地址 varchar(200) 是

7 Phone 电话 varchar(20) 否 Order 表见表 7。

表 7 Order表

序号 英文字段名 中文字段名 数据类型 是否允许为空 主键/外键

1 OrderId 订单号 int 否 主键

2 OrderDate 开单日期 datetime 否

3 ShipDate 送货日期 datetime 否

4 CustomerId 会员编号 varchar(10) 否

5 IsShipped 订单是否送出 int 否

6 Address 送货地址 varchar(200) 否 OrderItem 表见表 8。

表 8 OrderItem表

序号 英文字段名 中文字段名 数据类型 是否允许为空 主键/外键

1 OrderItemId 订单细则编号 int 否 主键

2 OrderId 订单号 int 否 主键

3 ISBN 书号 varchar(50) 否

4 BooksCount 订书的数目 int 否 Publisher 表见表 9。

表 9 Publisher表

序号 英文字段名 中文字段名 数据类型 是否允许为空 主键/外键

1 PublisherId 出版社编号 int 否 主键

2 PublisherPhone 出版社电话 varchar(10) 否

3 PublisherName 出版社名称 varchar(50) 否 Category 表见表 10。

软件工程——理论与实践

140

表 10 Category表

序号 英文字段名 中文字段名 数据类型 是否允许为空 主键/外键

1 CategoryId 类别编号 int 否 主键

2 CategoryName 类别名称 varchar(50) 否

3.4 数据库的视图设计

1.BookDetailsViewForAdmin

功能:为管理员显示书的详细信息。 脚本: CREATE VIEW BookDetailsViewForAdmin AS SELECT Book.ISBN, Publisher.PublisherName, Book.Title, Book.CategoryId, Book.Author, Book.Edition, Book.Size, Book.Price, Book.Pages, Book.Words, Book.PublishDate, Book.PrintDate, Book.TotalCount, Book.ArrivalDate, Book. Discount, Book.Cover, ook.Comment, Category.CategoryName FROM Book INNER JOIN Publisher ON Book.PublisherId = Publisher.PublisherId INNER JOIN

Category ON Book.CategoryId = Category.CategoryId;

2.BookDetailsViewForCustomer

功能:为会员显示详细的图书信息。 脚本: CREATE VIEW BookDetailsViewForCustomer AS SELECT Book.ISBN, Book.Title, Book.Author, Category.CategoryName, Publisher.PublisherName, Book.PublishDate, Book.Pages, Book.Words, Book.Size, Book.Edition, Book.Price, Book.Discount, Book.Cover, Book.Comment FROM Book INNER JOIN Publisher ON Book.PublisherId = Publisher.PublisherId INNER JOIN Category ON Book.CategoryId = Category.CategoryId

3.BookShortViewForAdmin

功能:为管理员显示缺货图书的信息。 脚本: CREATE VIEW BookShortViewForAdmin AS SELECT Book.ISBN, Book.Title, Book.Author, Category.CategoryName, Publisher.PublisherName, Publisher.PublisherPhone, Book.Price FROM Book INNER JOIN Publisher ON Book.PublisherId = Publisher.PublisherId INNER JOIN Category ON Book.CategoryId = Category.CategoryId WHERE (Book.TotalCount = 0)

4.BookSummaryViewForCustomer

功能:为会员显示简略的图书信息。 脚本: CREATE VIEW BookSummaryViewForCustomer AS SELECT Category.CategoryName, Book.Title, Book.Author, Publisher.PublisherName, Book.Price, Book.Discount FROM Book INNER JOIN Publisher ON Book.PublisherId = Publisher.PublisherId INNER JOIN Category ON Book.CategoryId = Category.CategoryId

第 3章 软件设计

141

5.OrderViewForCustomer

功能:为会员显示订单信息。 脚本: CREATE VIEW OrderViewForCustomer AS SELECT Order.OrderId, Order.OrderDate, OrderItem.OrderItemId,OrderItem. ISBN, Book.Title, OrderItem.BooksCount FROM Order INNER JOIN OrderItem ON Order.OrderId = OrderItem.OrderId INNER JOIN Book ON OrderItem.ISBN = Book.ISBN

6.OrderViewForAdmin

功能:为管理员显示订单。 脚本: CREATE VIEW OrderViewForAdmin AS SELECT TOP (100) PERCENT Order.OrderId, OrderItem.BooksCount, OrderItem. OrderItemId, Book.Price, Book.Discount,Book.CategoryId, Order.ShipDate FROM OrderItem INNER JOIN Order ON OrderItem.OrderId = Order.OrderId INNER JOIN Book ON OrderItem.ISBN = Book.ISBN WHERE (dbo.Order.IsShipped = 1) ORDER BY Order.OrderId DESC, Order.ShipDate DESC

7.SalesViewForReport

功能:为销售报表显示而创建的视图,实现按类别按月份显示。 脚本: CREATE VIEW SalesViewForReport AS SELECT Category.CategoryName, Order.ShipDate, Book.Price * Book.Discount * OrderItem.BooksCount AS TotalMoney FROM Book INNER JOIN Category ON Book.CategoryId = Category.CategoryId INNER JOIN OrderItem ON Book.ISBN = OrderItem.ISBN INNER JOIN Order ON OrderItem.OrderId = Order.OrderId WHERE (Order.IsShipped = 1)

4 功能模块设计

此项目中共涉及 10 个页面,分别是:Login.aspx、CustomerInfo.aspx、BookList.aspx、BookDetails.aspx、MyShoppingCart.aspx、MyOrders.aspx、AdminPage.aspx、Admin_BooksManagement.aspx、Admin_BookDetailsMan.aspx 和 Admin_OrdersManage- ment.aspx。 1.登录页面:Login.aspx

参数:type=?,指定登录之后跳转的页面。 type=CustomerInfo 表明登录之后跳转到 CustomerInfo.aspx(?type=buy&CustomerId=?)页面,

type=Orders 表明登录之后跳转到 MyOrders.aspx?CustomerId=?页面。 调用背景: (1)当“我的订单”项被单击时,跳转至此页面; (2)在 MyShoppingCart.aspx 页面中单击“结账“时,跳转至此页面。 (3)若是在后台进行登录,输入用户名、密码,选择“管理员”登录。若成功,跳转至

AdminPage.aspx 页面,否则显示出错信息。 页面组成:由一个登录框组成。登录框包含用户名和密码两个文本框、一组单项选择按钮、

一个登录按钮和一个注册按钮。

软件工程——理论与实践

142

调用描述: (1)当前用户没有登录,在用户名和密码填入后,单击“登录”按钮。在数据库中进行查询,

若存在此记录,根据 type 参数跳转到相应的页:若 type=CustomerInfo,则跳转到 CustomerInfo. aspx(?type=buy&CustomerId=?)页进行用户信息的核对,以便书店的送货人员按照这些信息进行联

系。若 type=Orders,则跳到 MyOrders.aspx?CustomerId=?页面,浏览订单信息。若没有此记录,

则在登录框中提示登录失败信息。 (2)单击“注册”按钮,则页面跳转到 CustomerInfo.aspx(?type=register)页面。游客进行注册。

若注册成功,则弹出对话框提示成功,之后,页面跳转至 MyShoppingCart.aspx (?CustomerId=?)进行结账。

(3)若为管理员,在选择“管理员”选项之后,登录到 AdminPage.aspx 页面中。 2.注册页面:CustomerInfo.aspx

参数:type=?,指定这个页面的功能。type=register 指明这个页面是供用户注册的,type=buy指明这个页面是用于用户核对自己的接货信息的。此时,type 后还有一项 CustomerId=?,指明当

前的用户。 调用背景: (1)当用户在 Login.aspx 中单击“注册”时,跳转至此页面; (2)当用户在 Login.aspx(?type=CustomerInfo=?)中单击“登录”时,跳转至此页面。 页面组成:由一个表格构成,表格中的项即是要填充的详细个人信息。在表格下面有“确认”

按钮。 调用描述:单击“确认”按钮之后,会在数据库中检索是否有重复的 CustomerId(CustomerId

是用户的邮箱号,一般不会重复),并且检验是否有没填的必填项(必填项用*标出),如填写正确,

则弹出对话框提示正确信息,最后跳转到主页。 3.图书列表页面:BookList.aspx

参数:CategoryId=?,Title=?,指定书的类别和名称。 调用背景:在主页的书类型下拉列表、书名的文本框中输入,单击“查询”之后,此页面被

调用。 页面组成:页面左部是类别列表,右部是书的查询结果列表。 调用描述:这个页面是由于在主页中用户填入了相应的信息而出现的。 (1)若 CategoryId 为空,Title 为空,则显示所有的图书的简略信息:书号、书名、作者、出

版社、折扣。 (2)若 CategoryId 为空,Title=?,则显示书名为?的图书的简略信息:书号、书名、作者、出

版社、折扣。 (3)若 CategoryId=?,Title=?,则显示书名为?,类别为?的简略信息:书号,书名、作者、出

版社、折扣。当单击图书的图片时,将跳转到 BookDetails.aspx?ISBN=?页面,显示详细信息。 4.图书明细页面:BookDetails.aspx

参数:ISBN=?,指定要详细显示的书的书号。 调用背景:在 BookList.aspx 页面中,单击图书的图片时,此页面被调用。 页面组成:这个页面由左右两个部分组成。左边是同类别的图书名称列表,右边是图书的详

细信息的表格,表格中的前几行中显示字数较少的图书信息(书号、书名、出版社、价格、折扣),

后几行显示字数较多的信息(备注等)。表中还有一个“购买”的图像按钮。

第 3章 软件设计

143

调用描述:单击“购买”的图像按钮,图书被添加到购物车。 5.会员的购物车页面:MyShoppingCart.aspx

参数:CustomerId=?,指定会员的 ID。 调用背景:单击导航栏中的“我的购物车”。若用户已登录,则跳转至此页;若没有登录,则

先登录,再跳转至此页面。 页面组成:一个数据绑定控件,控件的头部给出了要显示的项:图片、市场价、卖价、节

省、数量。其中数量是文本信息,可以更改。下面有“结账”和“取消”两个按钮和一个“总

计”标签。 调用描述:单击“取消”按钮,则清空购物车。单击“结账”按钮,跳转到 CustomerInfo.aspx

(?type=buy&CustomerId=?)页面,进行信息确认,单击页面下的“确认”按钮后,修改数据库中的

订单和订单明细记录。 6.我的订单页面:MyOrders.aspx(视图OrderViewForCustomer)

参数:CustomerId=?,指定用户的 ID。 调用背景:单击导航栏中的“我的订单”后,若用户已登录,则直接跳转至该页;若没有登

录,则先跳转至 Login.aspx(?type=Orders?)页面,再跳转至此页面。 页面组成:这个页面由左右两个部分组成。左边是搜索部分,即两个下拉列表,分别提供按

月搜索和按订单号搜索。下拉列表的项是月份、订单号的集合。右边是一个数据控件,它要显示

的项为订单日期(OrderDate)、订单号(OrderId)、订单细则号(OrderItemId)、书号(ISBN)、

书名(Title)、订书的数量(BooksCount)。 调用描述:改变两个下拉列表的项,右边的数据控件进行动态显示。

7.管理员用户首页:AdminPage.aspx

参数:AdminID=?,管理员的 ID。 调用背景:管理员从后台成功登录后,从 Login.aspx 页面跳转至此页。 页 面 组 成 : 存 在 一 个 大 的 导 航 栏 , 分 别 导 航 至 AdminBooksManagement.aspx 、

Book-DetailsMan.aspx 或 Admin_OrdersManagement.aspx 页面。 8.管理员图书管理首页:Admin_BooksManagement.aspx

参数:无。 调用背景:当单击 AdminPage.aspx 页面导航栏中的“图书管理”项时,此页被调用。 页面组成:分左右两个部分。左边有 4 个链接:“现存图书”、“添加新书”、“图书类别”和“处

理缺货”。“现存图书”链接下方还有两个文本框,供输入书号和书名。右边有 4 个面板: Panel_ExitBookList、Panel_NewBook、Panel_Category 和 Panel_ShortBookList。通过隐藏或显示这

几个面板来实现。 调用描述: (1)单击“现存图书”链接,面板 Panel_ExistBookList 显示。Panel_ExistBookList 中的数据

源控件显示满足查询条件的图书信息:图片、书号、书名、类别、出版社、价格、折扣、数量。

单击图书图片时,进入 Admin_BookDetailsMan.aspx(?ISBN=?)页面。 (2)单击“添加新书”链接时,Panel_NewBook 面板显示,其他面板隐藏。 (3)单击“图书类别”链接时,Panel_Category 面板显示,其他面板隐藏。 (4)单击“处理缺货”链接时,Panel_ShortBook 面板显示,其他面板隐藏。 面板说明:

软件工程——理论与实践

144

(1)面板 Panel_NewBook。 组成:一个表格,表格填充图书的基本信息。表格下面有“提交”按钮。 调用描述:填完数据之后,单击“提交”按钮。数据库进行更新。填充对话框显示提示信息。 (2)面板 Panel_Category。 组成:一个列表框、一个文本框、两个按钮(“增加”和“删除”)。 调用描述:当在文本框中填入要新增加的类别名称后,单击“增加”按钮,更新数据库的

Category 表,并在列表框显示。在列表框中选择一项后,单击“删除”按钮,更新数据库表,并

在列表框中显示更新。 (3)面板 Panel_ExistBookList。 组成:一个数据源绑定控件。 调用描述:数据源控件显示满足查询条件的图书列表。控件的标题由以下几项组成:图片、

书号、书名、类别、出版社、价格、折扣、数量。当单击图片时,跳转到 Admin_Book DetailsMan.aspx(?ISBN=?)页面。

(4)面板 Panel_ShortBook。 组成:一个数据源绑定控件。 调用描述:列出目前缺货的书目。数据源控件的标题由以下几项组成:图片、书号、书名、

类别、出版社、价格、折扣。 9.图书细则管理页面:Admin_BookDetailsMan.aspx

参数:ISBN=?,指定要显示的图书的书号。 调用背景:当在页面 Admin_BooksManagement.aspx 中单击某图书的图片时,此页面被

调用。 页面组成:这个页面由左右两个部分组成。左边有 4 个链接:“现存图书”、“添加新书”、“图

书类别”和“处理缺货”。“现存图书”链接下方还有两个文本框,供输入书号和书名。 右边是一

个表格,显示了图书的详细信息。表格下面有“提交”按钮。 调用描述:在表格中填入相应的图书信息,单击“提交”按钮,图书的信息更新至数据库中。

更新成功或失败都将弹出提示框。 10.管理员订单管理首页:Admin_OrdersManagement.aspx

参数:无。 页面组成:这个页面由左右两个部分组成。左边由一组选择按钮、两个下拉列表和一个“提

交”按钮组成,右边是两个面板,两个面板分别装有数据源控件和报表。 调用描述:两个链接是“按月份查询订单”和“查看图表”。当选择“按月份查询订单”选项

时,在下面的文本框中输入月份后,单击“提交”按钮。右边的 Panel_Order 面板显示,面板上

的数据源控件显示满足查询条件的信息。若文本框为空,则按日期由大到小的顺序显示所有的订

单信息。当选择“查看图表”选项时,必须在下拉列表中输入月份信息,右面的 Panel_Report 面板中的报表显示相应的表,否则提示报错。

面板说明: (1)面板 Panel_Order。 组成:一个数据源控件。 调用描述:显示满足查询条件的信息,数据源控件显示的项为订单号、订单明细号、结单时

间、书号、数量、价格、折扣。

第 3章 软件设计

145

(2)面板 Panel_Report。 组成:一个 CrstalReport 报表。 调用描述:显示相应月份的各类别图书的销售信息。

5 存储过程设计

5.1 涉及 Order 表的存储过程

1.GetAllOrders()

功能描述:得到所有的订单记录集。 入口参数:无。 出口参数:订单的记录集。 伪语言实现: CREATE PROCEDURE GetAllOrder() AS SELECT * FROM Order; RETURN;

2.GetCurrentOrderId()

功能描述:由于 OrderId 是按种子递增的,故有必要得到当前的 OrderId。此过程得到当前的

OrderId。 入口参数:无。 出口参数:当前的 OrderId。 伪语言描述: CREATE PROCEDURE GetCurrentOrderId() AS SELECT COUNT(*) FROM Order; RETURN;

3.InsertNewOrder()

功能描述:将会员的购物车中的订单信息更新到数据库。 入口参数:无。 出口参数:无。 伪语言实现: CREATE PROCEDURE InsertNewOrder(@OrderId int, @OrderItemId int,@ISBN varchar(50), @BooksCount int, @OrderDate datetime,@CustomerId varchar(10), @Address varchar(200),@IsShipped int ) AS DECLARE left int; INSERT INTO Order values(@OrderId, @OrderDate, @CustomerId, @Address,1);

INSERT INTO OrderItem values(@OrderItemId, @OrderId,@ISBN, @BooksCount);

left = SELECT count(*) FROM Book WHERE ISBN = @ISBN; IF left > 0 THEN UPDATE Book SET TotalCount = TotalCount-@BooksCount WHERE ISBN = @ISBN; END IF; RETURN;

4.DeleteOrder()

功能描述:管理员删除指定的订单。 入口参数:OrderId。

软件工程——理论与实践

146

出口参数:无。 伪语言实现: CREATE PROCEDURE DeleteOrder(@OrderId int) AS DELETE FROM Order WHERE OrderId = @OrderId; RETURN;

5.GetOrdersByShipDate()

功能描述:管理员根据指定月份查询订单。 入口参数:ShipDate。 出口参数:指定月份的订单集。 伪语言实现: CREATE PROCEDURE GetOrdersByShipDate(@ShipDate datetime) AS SELECT OrderId, OrderItemId, ISBN, BooksCount, Price, Discount FROM OrderViewForAdmin; RETURN;

5.2 涉及 Book 表的存储过程

1.GetAllBooks()

功能描述:得到所有书的信息记录集。 入口参数:无。 出口参数:书的信息记录集。 伪语言实现: CREATE PROCEDURE GetAllBooks() AS SELECT * FROM Book; RETURN;

2.GetBookByISBN()

功能描述:根据书号得到书的详细信息。 入口参数:ISBN。 出口参数:指定 ISBN 的书的信息。 伪语言实现: CREATE PROCEDURE GetBookByISBN(@ISBN varchar(50)) AS SELECT * FROM Book WHERE ISBN = @ISBN; RETURN;

3.GetBooksByTitle()

功能描述:根据书名得到书的详细信息。 入口参数:Title。 出口参数:指定书名的书的详细信息。 伪语言实现: CREATE PROCEDURE GetBooksByTitle(@Title varchar(50)) AS SELECT * FROM Book WHERE Title=@Title; RETURN;

4.GetBooksByCategory()

功能描述:根据书的类别得到书的详细信息。

第 3章 软件设计

147

入口参数:category。 出口参数:指定书的类别的书的记录集。 伪语言实现: CREATE PROCEDURE GetBooksByCategory(@Category int) AS SELECT * FROM Book WHERE Category = @Category; RETURN;

5.GetBooksByTitleCategory()

功能描述:根据书的类别和书名得到书的详细信息。 入口参数:Category、Title。 出口参数:指定书的类别的书的记录集。 伪语言实现: CREATE PROCEDURE GetBooksByTitleCategory(@Category int, @Title varchar(50)) AS SELECT * FROM Book WHERE Category = @Category AND Title=@Title RETURN;

6.GetShortBooks()

功能描述:得到缺货的书的记录集。 入口参数:无。 出口参数:缺货的书的记录集。 伪语言描述: CREATE PROCEDURE GetShortBooks() AS SELECT * FROM BookShortViewForAdmin; RETURN;

7.UpdateBook()

功能描述:根据书号和书名等更新书的信息。 入口参数:ISBN、Title 等。 出口参数:无。 伪语言实现: CREATE PROCEDURE UpdateBook(@ISBN varchar(50), @Title varchar(50)...) AS UPDATE Book SET Title=@Title ... WHERE ISBN = @ISBN RETURN;

8.UpdateCategory()

功能描述:更新图书的类别名称。 入口参数:CategoryId。 出口参数:无。 伪语言实现: CREATE PROCEDURE UpdateCategory(@Categoryid int, @CategoryName varchar(50)) AS UPDATE Category SET CategoryName = @CategoryName WHERE CategoryId = @CategoryId; RETURN;

软件工程——理论与实践

148

9.InsertNewCategory()

功能描述:增加图书的类别名称。 入口参数:CategoryName。 出口参数:无。 伪语言实现: CREATE PROCEDURE InsertNewCategory(@CategoryName varchar(50)) AS INSERT INTO Category values(@CategoryName); RETURN;

10.DeleteCategory()

功能描述:删除选择的类别。 入口参数:CategoryId。 出口参数:无。 伪语言实现: CREATE PROCEDURE DeleteCategory(@CategoryId int ) AS DELETE FROM Category WHERE CategoryId = @Categoryid; RETURN;

11.DeleteBookByISBN()

功能描述:删除特定的书的信息。 入口参数:ISBN。 出口参数:无。 伪语言实现: CREATE PROCEDURE DeleteBookByISBN(@ISBN varchar(50)) AS DELETE FROM Book WHERE ISBN = @ISBN; RETURN;

5.3 涉及 Customer 表的存储过程

1.InsertNewCustomer()

功能描述:添加新的会员。 入口参数:Customer、password 等。 出口参数:无。 伪语言实现: CREATE PROCEDURE InsertNewCustomer(@CustomerId varchar(20), @CustomerName...) AS INSERT INTO Customer values(@CustomerId,@CustomerName...) RETURN;

2.UpdateCustomer()

功能描述:更新会员信息。 入口参数:Customer、Email、Password 等。 出口参数:无。 伪语言实现: CREATE PROCEDURE UpdateCustomer(@CustomerId varchar(20), @CustomerName...) AS

UPDATE Customer SET CustomerId = @CustomerId, CustomerName = @CustomerName…;

第 3章 软件设计

149

RETURN;

6 角色授权设计

角色授权见表 11。

表 11 角色授权

模 块 游 客 会 员 管 理 员

图书管理模块 ●

登录注册模块 ● ● ●

会员购书模块 ● ●

浏览图书模块 ● ● ●

订单管理模块 ● ●

7 系统错误处理

7.1 出错信息

(1)对会员输入的各项内容均进行有效性、安全性检查,减少错误发生的几率。 (2)对程序运行中的异常均进行捕获,按统一的方式将出错提示信息提供给会员。 (3)当会员访问自身权限以外的信息时,将其导航到统一的出错提示页面。

7.2 故障预防与补救

以统一的机制进行网站权限的控制。对程序中用到的数据尽量进行加密,以减少黑客攻击的

危害。定期对数据库中的数据进行海量备份及增量备份。 7.3 系统维护设计

(1)编码实现时应采用模块化和分层的思想,提高模块内部的内聚,减少模块间的耦合。使

系统逻辑结构清晰,从而增强可读性和可维护性。 (2)面向数据与面向对象相结合,模块划分符合面向对象思想。 (3)在编码过程中注意标识符命名的意义,添加适量注释。

8 测试计划

测试计划作为本系统的测试指导,测试成员按计划和规定进行测试。本系统的测试将从单元

测试、集成测试、系统测试 3 个方面来设计。

小 结

本章主要介绍软件设计的相关内容,重点是软件设计的基本原则和软件设计的常用方法。 软件设计在软件开发中处于核心地位,一般分为概要设计和详细设计两个阶段。概要设计也

称为总体设计,它以需求规格说明书为基础,概要地说明软件系统的实现方案。详细设计也称为

过程设计,它对每个模块的功能和架构进行细化,明确要完成该模块的预定功能需要的数据结构

和算法,并将其用某种形式描述出来。 在软件设计的过程中,开发人员最好遵循一些既定的原则。这些原则是人们在长期的软件开

发实践中总结出来的经验,有利于提高软件开发的效率和质量。软件设计的原则有模块化、抽象

化、逐步求精、信息隐藏。

软件工程——理论与实践

150

结构化软件设计方法和面向对象软件设计方法是两种主流的软件设计方法。结构化软件设计

方法更关注于系统的功能,采用自顶向下、逐步求精的设计过程,以模块为中心来解决问题,按

照工程标准和严格的规范将目标系统划分为若干功能模块。面向数据流的方法和面向数据结构的

方法是两种常用的结构化软件设计方法。面向数据流的设计方法多在概要设计阶段使用,它借助

于数据流图来进行设计工作,而面向数据结构的设计方法通常在详细设计阶段使用,它按输入、

输出以及计算机内部存储信息的数据结构进行软件结构的设计,从而把对数据结构的描述转换为

对软件结构的描述。 合适的工具对于方便我们的软件设计工作非常有帮助。常用的结构化软件设计工具有流程图、

N-S图和 PAD图等。 与结构化软件设计方法相比,面向对象软件设计方法的使用范围更广。与传统的软件工程方

法不同的是,面向对象的方法不强调需求分析和软件设计的严格区分。从分析到设计的过渡是一

个逐渐扩充、细化和完善分析阶段所得到的各种模型的过程。面向对象的设计可以分为系统设计

和对象设计两个阶段。系统设计关注于确定实现系统的策略和目标系统的高层结构,而对象设计

是对需求分析阶段得到的对象模型的进一步完善、细化或扩充。 数据库结构的设计包括概念结构设计、逻辑结构设计和物理结构设计。概念结构设计多采用

E-R 图来表示,逻辑结构设计就是要将概念结构中的实体、属性、联系映射为数据表结构,物理结构设计要将模型进一步表现为物理空间上的表、字段、索引、存储过程、触发器及相应的数据

字典。 软件体系结构由功能各异、相互作用的部件按照层次构成,包含了系统的基础构成单元、单

元之间的相互作用关系、在构成系统时它们的合成方法以及对合成约束的描述。这对一个软件系

统起着至关重要的作用。在软件的设计模式部分,我们介绍了设计模式的 4个要素以及目前比较流行的 23种设计模式。 在体系结构中,我们深入介绍了 5类分布式的系统结构,其实,系统结构还有很多种,笔者

以为,系统结构是一种设计层次上的艺术,在实际应用中,有时会结合使用多种体系结构,例如,

C/S 结构的服务器端采用多处理器体系结构分担负载等。使用时,结合自己的系统要求,灵活运用才是问题的关键,毕竟技术的目的在于应用,而不是框架限制。 本章介绍了 5 种比较常见的框架,尤其是最后的 PCBMER 框架结构,在很多大型商务领域

设计中经常使用,而且各种编程语言都有对应的技术实现。 本章还介绍了利用 Visio绘制网上书店的系统的结构图,利用 Rose绘制网上书店系统的顺序

图,软件设计说明书指南以及网上书店系统的软件设计说明书。

习 题

1.比较概要设计和详细设计的目标,并分别阐述概要设计和详细设计的内容。 2.为什么说“高内聚、低耦合”的设计有利于提高系统的独立性? 3.如何理解抽象的概念? 4.对基于面向对象思想的设计而言,有哪些方法或机制可以实现信息隐藏? 5.改进的 Jackson图与传统的 Jackson图相比有哪些优点? 6.如果要求两个正整数的最小公倍数,请用程序流程图、N-S 图和 PAD 图分别表示出求解

第 3章 软件设计

151

该问题的算法。 7.比较结构化软件设计方法和面向对象软件设计方法。 8.如何理解软件体系结构设计的重要性。 9.利用 Visio分别绘制网上书店系统的“订单信息管理”功能模块和“图书信息管理”功能

模块的结构图。 10.利用 Rose分别绘制网上书店系统的“会员购书”模块和“浏览图书”模块的顺序图。

第4章 编码及实现

本章目标 ● 了解编程语言的重要性。 ● 熟悉编程语言的发展历程。 ● 了解选择编程语言时所需考虑的因素。 ● 掌握提高编程风格的一些方法和规则。 ● 熟悉 Visual Studio 的使用方法。 ● 掌握利用 Visual Studio 编程的方法。

4.1 编 程 语 言

在软件设计阶段,我们得到了实现目标系统的解决方案,并用模型图、伪代码等设计语言表

述出来。编码的过程就是把软件设计阶段得到的解决方案转化为可以在计算机上运行的软件产品

的过程。 选择合适的编程语言是编码过程的关键。可以说,编程语言是人与计算机交互的基本工具,

它定义了一组计算机的语法规则,通过这些语法规则可以把人的意图、思想等转化为计算机可以

理解的指令,进而让计算机帮助人类完成某些任务。软件开发人员通过使用编程语言来实现目标

系统的功能。

4.1.1 编程语言的发展与分类

编程语言是人与计算机交流的重要工具。对于软件开发人员而言,编程语言是除了计算机本

身之外的所有工具中最重要的。从计算机问世至今,人们一直在努力研制更优秀的编程语言。目

前,编程语言的种类已有成千上万种,但是能得到广泛认可的语言却屈指可数。 计算机程序是从人传递到机器的一些信息。为了将人的意图清晰地传达给不会说话的机器,

程序采用了严格的语法和严谨的定义。 —《人月神话》

最早的编程语言是机器语言,它是计算机可以识别、执行的指令代码。机器语言采用“0”和

“1”为指令代码来编写程序,它可以直接被计算机的 CPU识别,从而操纵计算机硬件的运行。由于机器语言直接操纵计算机硬件,所以语言必须基于机器的实现细节,也就是说,不同型号的计

152

第 4章 编码及实现

算机其机器语言是不同的。用一种计算机的机器指令编写的程序不能在另一种计算机上执行。因

为机器语言直接操纵底层硬件,所以其执行速度较快,但是程序员必须熟悉计算机的全部指令代

码和代码的含义。用机器语言编写程序对程序员的要求较高,花费的时间往往较长,直观性差,

容易出错。由于机器语言具有“面向机器”的特点,它不能直接在不同体系结构的计算机间移植。 像机器语言一样,汇编语言也是一种“面向机器”的低级语言。它通常为特定的计算机或系

列计算机专门设计,可高效地访问、控制计算机的各种硬件设备。汇编语言采用一组助记符来代

替机器语言中晦涩、难懂的二进制代码,用地址符号或标号来代替地址码,使得代码比较直观,

容易被程序员理解。由于机器不能直接识别汇编语言,所以在执行时,汇编语言必须由特定的翻

译程序转换为相应的机器语言才能由计算机执行。把汇编语言转换为机器语言的过程叫做汇编,

相应的翻译程序就是汇编程序。 汇编语言保持了机器语言简捷、快速的特点,比机器语言容易编写、理解。常用的汇编语言

有 Z-80机上的 Z-80汇编语言,PC上使用的 8080A、8086(8088)汇编语言等。 因为汇编语言中大量的助记符难以记忆,而且汇编语言对硬件体系有较强的依赖性,人们又

发明了高级语言。高级语言采用类似英文的语句来表示语义,更加方便了软件开发人员的理解和

使用。此外,高级语言不再依赖于特定的计算机硬件,所以移植性较强,同种高级语言可以用在

多种型号的计算机上。 使用高级语言最主要的原因是生产率和调试速度。

—《人月神话》 一些高级语言是面向过程的,如 Fortran、COBOL、ALGOL和 BASIC,这些语言基于结构化

的思想,它们使用结构化的数据结构、控制结构、过程抽象等概念体现客观事物的结构和逻辑含

义。Fortran语言常用于大规模的科学计算。COBOL是广泛用于商业领域里数据处理方面的语言,能有效地支持与商业处理有关的过程技术。ALGOL 语言并没有被广泛地应用,但是它包含的丰富的过程和数据结构值得其他语言借鉴。BASIC语言是一种解释或编译执行的会话语言,广泛地应用在微型计算机系统中。 还有一些高级语言是面向对象的,以 C++语言为典型代表,这类语言与面向过程的高级语言

有着本质的区别。它们将客观事物看成具有属性和行为的对象,并通过抽象把一组具有相似属性

和行为的对象抽象为类。不同的类之间还可以通过继承、多态等机制实现代码的复用。面向对象

的高级语言可以更直观地描述客观世界中存在的事物及它们之间的相互关系。 毋庸置疑,高级语言的出现是计算机编程语言发展的一个飞跃。 第四代语言是超高级语言,它是对数据处理和过程描述的更高级的

抽象,一般由特定的知识库和方法库支持,比如与数据库应用相关的查

询语言、描述数据结构和处理过程的图形语言等,它们的目的在于直接

实现各种应用系统。

图 4-1 编程语言的发展

编程语言发展状况的示意图如图 4-1所示。 Tiobe 排行榜是编程语言活跃度的一个比较有代表性的统计排行,

每月更新一次,统计数据来源于世界范围内的资深软件工程师和第三方

提供商以及各大搜索引擎(如 Google)的关键字搜索等,其结果经常作为业内程序开发语言的流行使用程度的有效指标。而且排行榜也反映了

编程语言的发展趋势,也可以用来查看程序员自身的知识技能是否与主

153

软件工程——理论与实践

流趋势相符,具有一定的借鉴意义。但必须注意的是,排行榜代表的仅仅是语言的关注度、活跃

度和流行情况等,并不代表语言的好坏,因为每种语言都有自己的优点和缺点。而就一般的编程

任务而言,基本各种语言都能胜任,开发效率也和使用者熟练程度以及开发平台密切相关,所以

Tiobe排行榜从长期的趋势分析,则更有参考价值。 图 4-2显示了 2011年 10月的 Tiobe排行。从中可以看出,Java、C、C++仍然占据前三位,

PHP、C#和 Objective-C紧随其后。排行比较能反映实际的技术发展状况。比如,近年来移动智能设备的开发逐渐升温,尤其是苹果公司 iPad、iPhone等,导致 Objective-C和用于为其进行游戏编程的 Lua语言活跃度大幅上升;而Web和 Native开发当前仍旧无法取代彼此,所以,Java和 C/C++仍然将在较长的时间里稳居前三(当然,微软的 C#或将有一日与 Java抗衡)。纵观编程语言近十年来的消长,虽然前三甲的地位一直比较稳定,但总的份额却在下降;处于主导地位的编程语言,

其地位正在被新兴的语言侵蚀。从语言分类来看,总体上以 PHP、Javascript等为代表的动态语言前景比较好,尤其是在正在飞速发展的 Web 和云计算领域上的应用;而函数式编程(如 F#等)也正越来越受到重视,但过程式语言,尤其是面向对象语言仍将在未来相当长的一段时间里不可

取代。越来越多的语言在向多泛型的方向发展,而且在不断地相互融合,互补长短,静态和动态地

融合(比如 C#从 4.0开始引入动态语言特征),函数式编程和面向对象地融合(比如 F#对面向对象的支持也非常的出色)。任何一种编程语言都有优劣,不同的编程语言在不同的领域有其独特乃至

不可取代之处。所以编程语言不存在哪个更好,而是要根据具体的项目特点,选择合适的编程语言。

图 4-2 2011年 10月 Tiobe语言排行榜

只有两种编程语言:一种是天天挨骂的,另一种是没人用的。

—Bjarne Stroustrup,C++之父

154

第 4章 编码及实现

下面对比较流行的几种编程语言做简单介绍。 (1)Java最初由 Sun Microsystems于 1995年推出,广泛应用于个人 PC、数据中心、移动设

备和互联网产品的设计,具有极好的跨平台特性,拥有目前全球最大的开发者社群。Java语言是一个纯面向对象的编程语言。它继承了 C/C++风格,但舍弃了 C++中难以掌握且非常容易出错的指针(改为引用取代)、运算符重载、多重继承(以借口取代)等特性;但增加了垃圾自动回收等

功能,使程序员在设计程序的同时,不用再小心翼翼地关注内存管理的问题。编译时,Java编译器首先将源代码编译为虚拟机中间代码(字节码),然后字节码可以在具体的应用平台中的虚拟机

上执行,这正是 Java跨平台特性的原因所在。 (2)C语言是一种面向过程的计算机程序语言,既有高级语言特点,又具有汇编语言的特征。

因此,常用于系统级别的程序设计,比如操作系统和驱动程序等。由于 C语言相比其他高级语言更接近底层,因此其执行效率非常高。在国内常常作为程序员入门的学习语言,也是多数大学里

计算机相关专业的必修课程。 (3)C++出现于 20世纪 80年代的美国AT&T贝尔实验室,最新的版本为C++ 2011(C++ 0x)。

最初作为 C语言的增强版,即增加了面向对象和一些新特性。后来逐渐加入虚函数、运算符重载、多重继承、模板、异常、RTTI、命名空间等特性。由于 C++是 C 的扩展,因此既具有接近 C 一样的执行效率,又具有高级语言的面向对象特征,如今仍然是 Native应用程序开发的首选语言。虽然开发成本相对于 Java、C#等语言高出很多,但其部署方便、执行效率高和更接近底层的特性却是二者无法取代的。例如,一些对性能要求极高的图形程序、3D游戏的开发,就必须使用 C/C++实现核心代码(事实上,为了实现更高的性能,一些核心代码甚至采用汇编来实现,因此相对于

C/C++,汇编更接近底层,执行效率更高)。 (4)C#是微软为推行.NET战略为.NET平台量身定制的纯面向对象编程,也是.NET平台开发

的首选语言。C#汲取了 C/C++和 Java的特性,具有 Java语言的简单易用性以及 C/C++的强大特性。不过 C#不像 Java 一样彻底地摒弃了指针,而是不推荐使用指针,这个特性在一些应用中非常有效,毕竟指针在解决某些应用中是最高效的方式。C#自 4.0开始引入动态语言特性,这使得C#可以采用类似 Javascript、Python或 Ruby的方式编程,动态特性可以解决一些静态语言无法解决的事情,因此,这极大地提升了 C#的功能。在Web开发方面,C#也是微软的主推语言,尤其是基于 C#的 ASP .NET,是在Windows/IIS平台上的首选。微软仍然在快速地扩展 C#的功能,越来越多的语言优点被融合到 C#中。 (5)PHP是一种嵌入在 HTML内部的在服务器端执行的脚本语言,融合了 C、Java、Perl等

的语法特性。由于其程序内嵌入 HTML 中,所以执行效率比完全生成 HTML 标记的 CGI 高出许多;PHP也可以执行编译后的代码,以达到加密和优化的作用。PHP的当前版本为 PHP,支持几乎所有的主流数据库以及操作系统,而且还可以使用 C/C++进行扩展。由于语法简单,容易上手,开发快捷,跨平台性强(可以运行在多种服务器操作系统上),效率高,面向对象等特

性,使得 PHP 成了目前学习 Web 编程的首选语言。而且 PHP 是开源的,所有的源代码都可以找到,给学习 PHP带来极大的便利;在 Open Source大行其道的今天,PHP也已成为中流砥柱之一。 (6)Javascript是 Netscape公司开发的面向对象的动态类型的区分大小写的客户端脚本语言,

主要用来解决服务器端语言的速度问题(因为完全由客户端执行,没有网络传输带来的时间延迟)。

Javascript常用于给 HTML页面添加动态脚本,比如各种客户端数据验证。近年来流行的 Ajax也是基于 Javascript 的后台通信机制,用于实现浏览器无刷新响应,当前几乎所有浏览器都支持

155

软件工程——理论与实践

Javascript。如今,多数动态页面都采用 Javascript实现,是事实上的动态 Web 开发的行业标准技术。不过,Javascript有一些不可克服的弱点,比如调试困难和天生的不安全性,对恶意攻击及数据窃取非常脆弱等。对此,Google在 2011年 10月新推出的语言 Dart有望解决这些问题,并取代Javascript网络开发通用语言地位。

4.1.2 选择编程语言需考虑的因素

进行系统开发时,应该根据待开发系统的特征及开发团队的情况考虑使用合适的编程语言。

因为不同的编程语言有各自不同的特点,有些时候,软件开发人员在选择时经常感到很矛盾。这

时候,软件开发人员应该从主要问题入手,对各个因素进行平衡。 在选择编程语言时,通常需考虑以下因素。 (1)待开发系统的应用领域,即项目的应用范围。不同的应用领域一般需要不同的语言。对

于大规模的科学计算,可选用 Fortran 语言或者 C 语言,因为它们有大量的标准库函数,可用于处理复杂的数值计算;对于一般商业软件的开发,可选用 C++、C#、Java,它们是面向对象语言,相对于面向过程语言而言,它们更具灵活性;在人工智能领域,则多使用 LISP,Prolog和 OPSS;对于与数据处理和数据库应用相关的应用,可使用 SQL 数据库语言、Oracle 数据库语言或 4GL(第 4代语言),当然,还要考虑数据库的类型;实时处理软件对系统的性能要求较高,选择汇编语言、ADA语言比较合适。 (2)用户的要求。如果用户熟悉软件所使用的语言,那么对软件的使用以及日后的维护工作

会带来很多方便。软件开发人员应该尽量满足用户的要求,使用他们熟悉的语言。 (3)软件开发人员的喜好和能力。采用开发人员熟悉的语言进行软件开发,可以节省开发人

员进行学习和培训的资源,加快软件开发的速度。 (4)系统的可移植性要求。可移植性好的语言可以使系统方便地在不同的计算机系统上运行。

如果目标系统要适用于多种计算机系统,那么编程语言的可移植性是非常重要的。 (5)算法和数据结构的复杂性。有些编程语言可以完成算法和数据结构复杂性较高的计算,

如 C和 Fortran。但是,有些语言则不适宜完成复杂性较高的计算,如 Lisp、Prolog等。所以在选择语言时,还应根据语言的特点,选取能够适应项目算法和数据结构复杂性的语言。一般来说,

科学计算、实时处理、人工智能领域中解决问题的算法比较复杂,数据处理、数据库应用、系统

软件开发领域内的问题的数据结构比较复杂。 (6)平台支持。某些编程语言只在指定的部分平台上才能使用。例如为 iPad和 iPhone开发,

则只能选用 Objective-C;为 Android开发,则只能使用 Java等。在这种情况下,程序员选择语言时,必须考虑具体的平台支持特性。

4.2 编 程 风 格

编程风格是指源程序的书写习惯,比如变量的命名规则,代码的注释方法、缩进等。具有

良好编程风格的源程序具有较强的可读性、可维护性,同时还能提高团队开发的效率。在大型

软件开发项目中,为了控制软件开发的质量,保证软件开发的一致性,遵循一定的编程风格尤

为重要。

156

第 4章 编码及实现

编程为什么有趣?作为回报,它的从业者期望得到什么样的快乐? 首先,这种快乐是一种创建事物的纯粹的快乐。 其次,这种快乐来自于开发对他人有用的东西。 第三,这种快乐来自于整个过程体现的一股强大的魅力。 第四,这种快乐是持续学习的快乐,它来自于这项工作的非重复性。 最后,这种快乐来自于在易于驾驭的介质上工作。

—《人月神话》 要做到按照良好的编程风格进行编程,可以从以下几点入手。 1.源程序文档化

这里的文档是指存在于源程序内部的文档,它与存在于源程序外部的文档一样,对提高程序

的可读性、可理解性都非常重要。源程序的内部文档包括恰当的标识符命名、有效的注释和良好

的布局等。 对标识符进行命名时,要注意以下几点。 (1)按照标识符的实际意义命名,使其名称具有直观性,能够体现标识符的语义。这样可以

帮助开发人员对标识符进行理解和记忆。 (2)遵循一定的命名规则,比如缩写的使用、字母大小写的选择、对常量和变量命名的区分

等。例如,在有些软件开发项目的命名规则里,常量名称选用大写字母,变量名称选用小写字母。

一般不推荐使用单词缩写进行命名,因为使用缩写在阅读时容易产生歧义。例如,表示班级名称

的变量 className不宜改成 cName。 (3)变量名不要过于相似,这样容易引起误解。 (4)在定义变量时,最好对其含义和用途做出注释。 注释是软件开发人员之间以及开发人员和用户之间进行交流的重要途径,它阐述了程序的细

节,有利于日后的维护工作。注释也需要遵循一定的规则,比如注释需要提供哪些方面的信息、

注释的格式、注释的位置等。 注释可以分为序言注释和行内注释。

序言注释位于模块的起始部分,对模块的详细信息进行说明,如模块的用途、模块的参数描述、模块的返回值描述、模块内捕获的异常类型、实现该模块的软件开发人员及实现时间、对

该模块做过修改的开发人员及修改日期等。

图 4-3 采用不同布局的代码示例

行内注释位于模块内部,经常对较难理解、逻辑性强或比较重要的代码进行解释,从而提高代码

的可理解性。 良好的布局结构应该能体现出程序的层次。对空

行、空格的使用及对代码缩进的控制与程序的视觉效

果密切相关。比较图 4-3 中的两段代码就不难发现,采用了缩进和空行的第 2段代码在布局上更清晰。

2.数据说明

为了使数据更容易理解和维护,在数据说明时需要遵循一定的原则。 (1)在进行数据说明时应该遵循一定的次序,比如哪种数据类型的说明在前,哪种在后。如

果数据说明能够遵循标准化的次序,那么在查询数据时就比较容易,这样能够加速测试、调试和

157

软件工程——理论与实践

维护的进程。 (2)当在同一语句中说明相同数据类型的多个变量时,变量一般按照字母顺序排列。 (3)对于复杂数据结构的说明,为了容易理解,需要添加必要的注释。 3.语句构造

语句构造是编写代码的一个重要任务。语句构造的原则和方法在编码阶段尤为重要。人们在

长期的软件开发实践中总结出来的语句构造原则有以下几点。 (1)不要为了节省空间而把多条语句写在一行。 (2)合理地利用缩进来体现语句的不同层次结构。 (3)将经常使用并且具有一定独立功能的代码封装为一个函数或公共过程。 (4)避免使用 goto语句。 (5)对于含有多个条件语句的算术表达式或逻辑表达式,使用括号来清晰地表达运算顺序。 (6)避免使用多层嵌套语句。 (7)避免使用复杂的判定条件。 4.输入/输出

软件系统的输入/输出部分与用户的关系比较紧密,良好的输入/输出的实现能够直接提高用户对系统的满意度。一般情况下,对软件系统的输入/输出模块要考虑以下原则。 (1)对所有的输入数据都要进行严格的数据检验。 (2)为了方便用户,对输入格式的限制不要太严格,输入的操作要尽量简洁,步骤尽量少。 (3)允许默认输入。 (4)对于交互式的输入,系统应该给予用户正确的提示。 (5)设计良好的输出报表。 (6)对输出数据添加必要的注释。 5.效率

效率是对计算机资源利用率的度量,它主要是指程序的运行时间和存储器容量两个方面。源

程序的运行时间主要取决于详细设计阶段确定的算法。可以使用用于代码优化的编译程序来减少

程序的运行时间。使用较少的存储单元可以提高存储器的效率。提高效率的具体方法有以下几种。 (1)减少循环嵌套的层数。在多层循环中,可以把有些语句从外层移到内层。 (2)将循环结构的语句用嵌套结构的语句来表示。 (3)简化算术和逻辑表达式,尽量不使用混合数据类型的运算。 (4)避免使用多维数组和复杂的表。 效率主要来自于优秀的设计,而不是优秀的编码。

—Robert L. Glass

4.3 Visual Studio 的使用方法介绍

4.3.1 Visual Studio 概述

Visual Studio 是微软公司开发的一套完整的软件开发工具,它集成了编辑器、编译器、连接

158

第 4章 编码及实现

器、调试器和其他多种辅助工具于一体,可以用于生成桌面或基于团队的企业级Web应用程序,而且集成了用于开发云项目的 Azure工具。Visual Studio 2010是目前 Visual Studio系列产品的最新版本,包括 Ulimate、Premium、Professional 版,其中 Ulimate 版包含全部功能,Premium 和Professional版各有不同的功能限制(其中 Professional版又包含 3个不同的子版),用于满足不同的用户群体。相对于旧版本而言,Visual Studio 2010中新增的功能有很多,其中比较典型的有以下几个。 (1)新的外观和行为。Visual Studio 2010对 IDE的界面进行了重新设计,如图 4-4所示。“代

码编辑器”和“设计”视图等文档窗口可以从 IDE中拖出,甚至可以放入不同的显示器中分屏显示,使得在编辑代码的同时可以查看输出结果,给程序员带来极大的方便。而且重新设计的 IDE删除了行和渐变,提高了程序的可读性。

图 4-4 Visual Studio 2010 新的 IDE界面

(2)新的快速浏览代码的工具。 代码编辑器支持按住 Ctrl 键同时滚动鼠标滚轮对代码进行缩放,这使得代码字体过小时

可以方便地查阅,这是因为在 VS 2010中代码编辑器使用了WPF技术进行了重写;而且在 Visual C#和 Visual Basic 中单击某个符号时,该符号的所有实例会被自动突出显示,而且可以使用“Ctrl+Shift+↓”快速定位到下一个符号位置。

搜索功能使得在输入代码时能够即时显示提示,通过按预设的快捷键(如 Enter、空格、运算符等)录入提示代码,极大地提升了代码的输入速度,而且支持 Camel大小写格式和下画线缩写搜索,比如可以使用 AOH搜索“AddOrderHeader”。

搜索调用层次结构功能可以迅速定位一个成员的所有被调用位置。比如在一个变量上单击鼠标右键,单击“查找所有引用”,在下方的输出窗口中就会显示出所有的对该变量的引用的位置,

单击这些位置,可以迅速定位到特定的行。 (3)重新设计的“线程”窗口提供筛选、调用堆栈搜索与展开以及分组功能。此外,还可以

组织和搜索断点并与其他开发人员共享。 (4)IDE中的“添加引用”和“工具箱”将会自动匹配目标.NET Framework或 Silverlight版

本。比如当目标是.NET Framework 2.0时,IDE会自动屏蔽 4.0中才有的 IntelliSense提示。 (5)支持测试驱动的开发。IDE 可以在定义新类型和成员之前,从它们的用法中生成代码存

159

软件工程——理论与实践

根。这样就可以先编写测试,然后再生成编译测试所需要的代码。 (6)C#语言中引入 dynamic支持,不需要使用显示的类型转换就可以引用对象。同时简化了

Microsoft Office API编程,用 COM方法时,不用再为每个可选形式参数指定值,IDE将会自动为这些参数指定默认值。 (7)简化了 Web 部署,增强了部署过程、一键式发布和 Web 配置自动转换的功能,比如

web.config中的配置会自动根据调试、临时和生产服务器的设置配置。 (8)对 C++新标准的支持。Visual C++编译器引入了 C++ 0x 标准中的 5 种新功能:Lambda

表达式、rvalue引用、编译时断言、表达式类型发现和自动类型推导。 (9)增强的并行编程。在 VS 2010中无须直接处理线程和线程池,就能在多个处理器上分配

工作的程序,还包含了 C运行库和.NET Framework的并行计算库;可以使用调试器中新的多线程工具来调试本机或托管的应用程序。 (10)增强的 SharePoint可以在 Visual Studio中创建、编辑、调试、打包、部署和激活 SharePoint

项目。站点部署甚至只需按 F5键就可以自动完成。 (11)云计算工具。Visual Studio中集成了Windows Azure Tools用于生成基于其上的可扩展

Web应用程序和服务。 (12)增强的 Team System。使得依赖 Team Foundation的团队开发时更加便捷。 微软公司在发布了 Visual Studio 2010以后,又发布了 Visual Studio 2010SP1,对 Visual Studio

2010中的一些问题进行了修复并升级了一些应用,比如 Help View 1.1和对 Silverlight 4、IIS7.5的支持等。 利用 Visual Studio 2010进行开发时,可以完成多种任务。 (1)创建基于用户界面或命令行的应用程序。应用程序包括多种类型,如分布式应用程序,

智能设备应用程序,以数据为中心的应用程序,基于Web服务(WCF Web服务、XML Web 服务)的应用程序,工作流应用程序(利用Windows Workflow Foundation可以在Windows上创建和使用工作流应用程序),基于Windows Azure 的云计算服务。 (2)创建Office开发解决方案。用户可以使用托管代码自定义Microsoft Office文档和Microsoft

Office Outlook。 (3)创建自定义控件或组件。 (4)自动处理任务或扩展环境。 (5)代码的生成、调试或测试。 (6)部署应用程序。 Visual Studio 2010在完成以上各种功能的过程中利用了多种技术,下面简单介绍几种。 (1).NET Framework 4.0。.NET Framework 4.0包含公共语言运行库和 .NET Framework类库

两个组件,是支持生成和运行下一代应用程序和 XML Web Services的Windows内部组件。它旨在向用户提供一个一致的面向对象的编程环境,提高代码的安全性,同时通过提供一个将软件部

署和版本控制冲突最小化的代码执行环境,使开发人员可以开发各种类型的应用程序。 (2)WPF(Windows Presentation Foundation)。WPF是用于生成能带给用户震撼视觉体验的

Windows 客户应用程序的显示技术。用户可以利用 WPF 来创建独立的应用程序或浏览器承载的应用程序。 (3)WCF(Windows Communication Foundation)。WCF是一个运行库和一组 API,用于创建

在服务器与客户之间发送消息的系统。通过使用相同的基础结构和 API,不同计算机上的应用程

160

第 4章 编码及实现

序可以通过因特网进行通信。 (4)Windows Workflow Foundation。Windows Workflow Foundation用于在Windows上快速生

成启用工作流的应用程序,允许用户在编写的应用程序中创建系统或人工工作流,如订单处理、

工作审查等。 (5)Silverlight。Silverlight 是一种跨浏览器、跨平台的客户端技术,可以帮助用户在网站上

设计、开发和提供各种各样的交互式应用程序,并创造支持多媒体的用户体验。 (6)Windows Forms。Windows Forms可以帮助用户开发图形丰富且易于部署和更新的应用程

序。与基于Windows的传统应用程序相比,Windows Forms在访问本地资源时更安全。 (7)ASP.NET。ASP是微软公司开发的可以与数据库和其他程序进行交互的一种简单、方便

的编程工具,常用于各种动态网站中。ASP也可以说是一种服务器端脚本编写环境,可以用来创建和运行动态网页或 Web 应用程序。ASP 网页可以包含 HTML标记、普通文本、脚本命令以及COM组件等。ASP.NET是 ASP的升级版本,它建立在.NET平台架构上,利用了.NET架构的强大、安全、高效的平台特性。ASP.NET MVC 3 支持在.NET 上进行MVC架构的开发。 (8)Ajax。Ajax 是一种创建交互式网页应用的网页开发技术。传统的 Web 应用模型的工作过

程是:界面上的用户动作触发一个连接到Web服务器的 HTTP请求;服务器完成一些处理,如接收数据、处理计算,再访问其他的数据库系统,最后返回一个 HTML页面给客户。这种方法的缺点是:服务器进行处理时,用户需要等待。

Ajax 通过在用户和服务器之间引入一个 Ajax 引擎,用异步的方式实现用户与程序的交互,它就像在程序中增加了一层机制,使它响应更灵敏。Ajax 的特点在于异步交互,动态更新 Web页面,适用于交互较多或频繁读取数据的Web应用。在留言板等需要经常刷新数据的页面中应用Ajax,可以在页面加载以后通过 Ajax引擎在后台进行定时的轮询,向服务器发送请求,查看是否有最新的消息。如果有就将新的数据下载并且在页面上动态更新,通过一定的方式通知用户。这

样既避免了用户不断手工刷新页面的不便,也不会因为重复刷新页面造成资源浪费。 使用 Ajax技术可以有效地降低服务器负担,提高用户操作反应速度,让用户体验到人性化的

服务。 (9)XMAL。XMAL(即可扩展应用程序标记语言)是一种声明性应用程序编程标记语言。

WPF能实现 XMAL加载程序并为WPF类型提供 XMAL语言支持,使用户可以使用 XMAL标记创建大部分应用程序的用户界面。 (10)LINQ。LINQ(即集成语言查询功能)为 C#和 Visual Basic语言语法提供强大的查询

功能。 (11)F#。F#是一种新的.NET Framework语言,支持函数编程和传统的面向对象和过程编程。

F#将函数编程的简介、表现力和组合风格与.NET的运行时、类库、互操作能力和对象模式结合起来,使得能够同时得到两种方式的长处。

4.3.2 利用 Visual Studio 进行开发

上一节对 Visual Studio 2010进行了概要性的介绍,本节将具体演示如何用 Visual Studio 2010进行项目开发。我们以最简单的“Hello World!”程序为例,首先开发一个命令行的“Hello World!”程序,然后再开发一个基于用户界面的“Hello World!”程序。

Visual Studio 2010开发命令行的“Hello World!”程序的具体步骤如下。 (1)启动 Visual Studio 2010,启动后的界面如图 4-5所示。

161

软件工程——理论与实践

图 4-5 Visual Studio 2010的启动界面

(2)选择“文件”→“新建”→“项目”,在如图 4-6所示的对话框中选择要采用的开发语言以及新建项目的类型。在这里,我们选择利用 Visual C#语言来开发一个最简单的 Windows 控制台应用程序。

图 4-6 新建控制台应用程序

在新建项目的时候,我们还可以选择基于.NET Framework版本,如图 4-7所示。如果选择了

162

第 4章 编码及实现

低版本的.NET Framework,那么一些新技术(如 LINQ、Ajax)将不被支持。

图 4-7 选择.NET Framework版本

(3)新建好一个项目后,得到如图 4-8 所示的界面。在界面左侧的解决方案窗口下,可以看到有一个 Program.cs文件以及 Properties和“引用”两个文件夹。

图 4-8 Visual Studio 的工作界面

选择“Properties”,单击鼠标右键,选择“打开”,可以得到如图 4-9 所示的各种有关该项目的配置信息。

163

软件工程——理论与实践

图 4-9 属性设置窗口

用户可以在如图 4-9 所示的窗口中修改项目的各种配置信息,例如目标框架、输出类型、调试、代码分析等。 如图 4-7 所示窗口的“引用”下显示了项目引用的各种命名空间。选择“引用”,单击鼠

标右键,选择“添加引用”,出现如图 4-10所示窗口,用户可根据需要在这个窗口中增加新的引用。

图 4-10 添加引用

(4)可以在 Program.cs文件里输入相应的代码。代码段如图 4-11所示。 (5)写好代码后,对代码进行 Build,使之成为可以运行的程序。选择“生成”→“生成解决

方案”即可,如图 4-12 所示,也可使用快捷键 F7。实际上,生成的过程是编译和链接的过程,Visual Studio把这两个过程统一在了一起。编译的结果在下方的“输出”窗口中显示。

164

第 4章 编码及实现

图 4-11 代码段

图 4-12 生成代码

在图 4-12中可以看到,在“生成”菜单下有多项选择,其中包括对解决方案的操作和对某个项目的操作。操作方式里还包括“生成解决方案”、“重新生成解决方案”、“清理解决方案”。对于

“生成解决方案”而言,它只对解决方案里更改过

的文件进行操作,而“重新生成解决方案”会对

解决方案里所有的文件进行操作,“清理解决方

案”会删除解决方案下生成的所有编译文件。

图 4-13 运行情况

(6)生成成功后,就可以查看代码的运行情况了。使用命令行工具“cmd.exe”,转到工程的“bin\debug”目录,运行“ConsoleApplication3.exe”。除了先编译再运行,也可直接选择“调试”→“开

始执行(不调试)”,可以看到代码在命令行下的

运行情况,如图 4-13所示。

165

软件工程——理论与实践

在完成了基于命令行的“Hello World!”程序之后,我们再来完成一个基于图形界面的“Hello World!”程序。 (1)在现有的解决方案下新建一个项目文件。用鼠标右键单击“解决方案”,选择“添加”→

“新建项目”,如图 4-14所示。

图 4-14 添加新项目

(2)在新项目的设置对话框里,选择其模板为“Windows 窗体应用程序”,新建成功后,得到如图 4-15所示的界面。

图 4-15 新建WindowsFormsApplication后的界面

166

第 4章 编码及实现

(3)打开“工具箱”,将一个 Label和 Button分别拖动到“Form1”窗口上,如图 4-16所示。 (4)选择“label1”,打开属性窗口,可以看到有关控件 label1的各种属性设置。将 Text的值

设为“Hello World!”,如图 4-17所示。

图 4-16 添加控件 图 4-17 修改控件属性

还可以对 label1所显示的文字的字体进行设置,选择属性 Font,在如图 4-18所示的对话框中对字体信息进行设置即可。然后,按照同样的方法,将 Button1的 Text值改为“修改显示文本”。

图 4-18 设置字体

(5)双击 Button1,打开 Form1.cs的编码文件,在 Visual Studio 2010自动产生的与 Button1的鼠标点击事件相关的函数中,输入如图 4-19所示的后台代码。 (6)现在需要设置WindowsFormsApplication1为主项目,在“解决方案资源管理器”窗口选

择 WindowsFormsApplication1 项目,用鼠标右键单击“设为启动项目”。然后对 WindowsForms Application1进行 Build。在这里,对单个项目进行操作即可,不需要对整个解决方案进行 Build,选择“生成”→“生成WindowsFormsApplication1”。也可以直接选择“调试”→“开始执行(不

调试)”执行。 (7)编译成功之后,就可以运行程序了。在解决方案中用鼠标右键单击“WindowsForms

Application1”,选择“调试”→“启动新实例”,可以得到如图 4-20 所示的窗口。单击“修改显

167

软件工程——理论与实践

示文本”按钮,窗口中的文本可以进行切换,如图 4-21所示。

图 4-19 后台代码

图 4-20 运行情况 图 4-21 切换后的运行情况

4.3.3 利用 Visual Studio 调试

调试是跟踪程序执行步骤,进而发现代码中存在的错误的过程。Visual Studio 2010的调试器功能非常强大,它可以调试所有 Visual Studio 2010所支持的编程语言及其相关联的类库。使用调试器可以中断程序的执行以检查代码,计算和编辑程序中的变量,查看寄存器,查看从源代码创

建的指令,查看应用程序所占据的内存空间,此外,用户还可在调试的过程中对代码进行更改。

可以说,调试器是软件开发人员在编码过程中查找错误的最重要的工具。 本节以对一段计算连续 50个整数和的代码进行调试为例,演示 Visual Studio 2010的调试器

的使用。 (1)创建一个新的Windows控制台应用程序,将其命名为 DebugInstance,然后在其 Program.cs

文件中输入如图 4-22所示的代码。 (2)启动调试器。要启动调试器,可以在菜单栏下选择“调试”→“启动调试”,也可以将光标置

于代码段中,用鼠标右键单击选择“运行到光标处”。第 1种方法在调试之前,需要先设置断点,代码会在断点处中断执行,然后用户可以查看当前情况下程序的各种执行信息。第 2种方法代码会在光标处

168

第 4章 编码及实现

中断执行。这里采用第 1种方法。将鼠标置于第 2行代码前,单击,便将断点设置好了,如图 4-23所示。(再左击,断点会被取消。)设置好断点后,选择“调试”→“启动调试”,启动调试器。

图 4-22 代码段

图 4-23 设置断点

(3)查看各种执行信息,比如数据显示、错误列表、断点信息等。将光标置于代码中断的地方,可以看到相关标识符或变量的数据显示,如图 4-24所示。同时,在 Visual Studio界面下方还有多个窗口,如调用堆栈、命令窗口、即时窗口、监视、断点、输出、错误列表等,如图 4-25和图 4-26所示。

图 4-24 数据显示功能

169

软件工程——理论与实践

图 4-25 监视窗口

图 4-26 断点窗口

(4)使调试继续执行。使调试继续执行的方式有两种,分别是使程序执行直接跳到指定的代码处或者单步执行。如果采用前者,可以在菜单栏里选择“调试”→“继续”,程序会直接执行到

下一个断点处中断。如果采用后者,会有 3种方法,它们都支持调试器逐步执行代码的方式,分别是“逐语句”、“逐过程”和“跳出”。其中,“逐语句”和“逐过程”都指示调试器执行下一行

代码。但是,如果下一行代码中包含函数调用,“逐语句”只执行调用本身,然后在函数内的第 1行代码处停止;而“逐过程”将执行整个函数,然后在函数外的第 1行停止。如果位于函数调用的内部并想返回到函数调用,可以使用“跳出”,“跳出”将一直执行代码,直到函数返回,然后

在调用函数中的返回点处中断。本例中采用“逐语句”,使调试逐句执行。选择“调试”→“逐语

句”即可。 (5)终止调试。当调试执行到程序结束时会自动终止,也可以在菜单栏里选择“调试”→“停

止调试”,手动终止调试。

4.3.4 Visual Studio 的进程调试

Visual Studio 的进程调试功能非常强大,对于已经部署的程序,如果在程序的运行过程中发生错误,就必须使用进程调试的方式。例如已部署的 Web 站点在某个时刻发生错误,由于 Web站点部署在服务器上,而在开发机器上调试站点,就需要使用远程的进程调试方式将工程源码挂

载到远程Web服务器的站点进程上,然后在源代码中设置断点;当重现错误时,站点就会执行到源代码中断点处停止,就如同调试本机程序一样简单。不仅是Web站点,对于任意已部署的程序,都可以使用这种方式将源代码挂载到目标执行进程

上调试。如果没有源代码,那么 Visual Studio就会显示程序错误时系统堆栈中的汇编代码,通过调试

和分析汇编代码也可以迅速定位程序中的错误。下

面就详细地对此过程进行介绍。

图 4-27 等待用户输入

还以上面的程序为例。直接执行工程目录

“bin\Debug”中的 debuginstance.exe。程序会停止在等待用户输入数据处,如图 4-27所示。 然后,在 Visual Studio中选择“调试”→“附

170

第 4章 编码及实现

加到进程”,显示如图 4-28 所示附加进程设置界面。在“传输”下拉框中,可以选择“默认值”或者“远程”模式,选择“默认值”模式,然后在“限定符”窗口中输入用户名和远程机器名即

可,格式是“用户名@远程机器名”,如果用户名有远程调试目标主机的权限,则可以连接成功,否则无法使用远程调试模式;如果是自己的机器,则不需要输入用户名,如图 4-28所示,只有目标主机名称“RAY”。

图 4-28 附加到进程

如果是在自己的机器上,限定符中输入本机名后就会在下面的“可用进程”窗口中显示本机

的所有正在运行的进程。如果是远程调试,则需要在远程主机上运行远程调试监视器,远程调试

监视器位于“Microsoft Visual Studio 2010”→“Visual Studio Tools”→“Visual Studio 2010 远程调试文件夹”中,打开文件夹。如果是 32位机器,进入“x86”子文件夹;如果是 64位机器,进入“x64”子文件夹。然后执行“msvsmon.exe”运行远程调试监视器(见图 4-29),调试监视器会提示建立的服务器名称,图 4-29中的“ShadowSong@RAY”,该名称需要填入“附加到进程”窗口(见图 4-28)中的限定符位置。一个机器上可以执行多个远程调试监视器,如果远程主机上没有安装 Visual Studio,那么只需要将文件夹内的所有文件复制到远程主机上即可(当然,远程主机必须安装对应的.NET Framework版本才能执行监视器程序)。

图 4-29 远程调试监视器

171

软件工程——理论与实践

在“可用进程”窗口中,选择“DebugInstance.exe”,单击“附加”按钮,即可将源代码工程挂载到“DebugInstance.exe”进程中。然后在代码中的第 20行设置断点,在程序运行窗口中输入数字,就会看到程序在执行到断点处停止了,如图 4-30所示。然后就可以使用调试本机程序的方法调试“DebugInstance.exe”进程。如果是远程站点,只需要在“附加到进程”的“限定符”框中输入远程主机,然后在“可用进程”窗口中选择目标站点进程,如 IIS 站点的执行进程是w3wp.exe,挂载成功后,就可以像调试本地站点一样调试远程站点。

图 4-30 程序在断点处停止

4.4 使用 Visual Studio 实现网上书店系统的

用户登录模块

在第 3 章,我们给出了网上书店系统的登录模块顺序图,在本节中,将学习如何使用 Visual Studio 2010作为集成开发环境,结合 C#编程语言实现该登录模块。

4.4.1 登录模块描述

登录模块描述见表 4-1。

表 4-1 登录模块

模块编号 名称 模块功能描述

SS1-2 会员登录

登录页面:Login.aspx

参数:type=?,指定登录之后跳转的页面

type=CustomerInfo 表明登录之后跳转到 CustomerInfo.aspx(?type=buy&CustomerId=?)页面,type=Orders表明登录之后跳转到MyOrders.aspx?CustomerId=?页面

调用背景:

(1)当“我的订单”项被单击时,跳转至此页面

172

第 4章 编码及实现

续表

模块编号 名称 模块功能描述

SS1-2 会员登录

(2)在MyShoppingCart.aspx页面中单击“结账”时,跳转至此页面

(3)如果用户是管理员,登录成功,跳转至 AdminPage.aspx 页面,否则,显示出错信息

页面组成:由一个登录框组成。登录框包含用户名和密码两个文本框、1个登录按钮、4个验证控件、1个消息条、1个注册超链接

调用描述:

(1)当前用户没有登录,在用户名和密码填入后,单击“登录”。在数据库中进行查询,若存在此记录,根据 type参数跳转到相应的页:若 type=CustomerInfo,则跳转到CustomerInfo. aspx(?type=buy&CustomerId=?)页进行用户信息的核对,以便书店的送货人员按照这些信息进行联系。若 type=Orders,则跳转到 MyOrders.aspx?CustomerId=?页面,浏览订单信息。若没有此记录,则在登录框中提示登录失败信息

(2)单击“注册”按钮,则页面跳转到 CustomerInfo.aspx(?type=Register)页面。游客进行注册。若注册成功,则弹出对话框提示成功,之后,页面跳转至

MyShoppingCart.aspx (?CustomerId=?)进行结账

(3)若为管理员,登录到 AdminPage.aspx页面中 登录模块使用的用户数据表描述见表 4-2。

表 4-2 Customer表

序 号 英文字段名 中文字段名 数 据 类 型 是否允许为空 主键/外键

1 Email 会员编号(用邮箱注册) varchar(50) 否 主键

2 CustomerName 会员姓名 varchar(20) 是

3 Password 密码 varchar(10) 否

4 IsAdmin 是否是管理员 Bool 否

5 NickName 会员别名 varchar(50) 是

6 Sex 性别 varchar(10) 否

7 Address 地址 varchar(200) 是

8 Phone 电话 varchar(20) 否

4.4.2 建立数据库和表

由于多数读者都安装了Microsoft Office系列产品,为方便学习,这里我们使用 Office Access 2010来建立数据库。如果读者自己实现的网上书店系统需要部署于实际的应用环境,考虑到性能问题,最好使用 MySql、SQLServer、Oracle 等更专业的数据库工具(也可以使用 Access 创建数据库之后,利用 Access提供的功能直接导出到支持的专业数据库中)。 运行 Office Access 2010,新建空数据库,创建表“Customer”,切换到设计视图,按照表 4-2

建立各字段,如图 4-31所示。 保存数据库为“DataBase.accdb”,放置在网上书店项目的“App_Data”目录下。然后在

Visual Studio中选择“项目”→“添加现有项”,将数据库添加到项目解决方案中,如图 4-32所示。

173

软件工程——理论与实践

图 4-31 Customer数据表

图 4-32 网上书店项目目录

4.4.3 编写数据库操作代码

使用 Visual Studio 编写 ASP.NET 网站时,集成开发环境工具箱中提供了丰富的拖曳式开发控件,合理利用可以极大地提高开发效率。但是,对于新手来说,非常不建议这样做,因为拖曳

控件可控性较差,写出来的代码也难以维护,而且这对于学习开发并不好。对于学习阶段的新手

以及希望开发出工程性很强的开发人员来说,要尽可能地手工编写代码。 数据库的操作代码要集中放置在一个文件中,以方便日后维护。数据库连接字符串很重要,

可以放在操作代码文件中,也可以放在“web.config”配置文件中。第 2种方式更为常见,也建议读者采用。 在“web.config”中配置数据库连接字符串的方法是在“web.config”中的“configuration/

connectionStrings”节点中添加连接字符串节点。代码如下:

174

第 4章 编码及实现

<configuration> <connectionStrings> <add name="DBConnStr" connectionString="Provider=Microsoft.ACE.OLEDB.12.0;Data

Source=|DataDirectory|/DataBase.accdb"/> </connectionStrings> </configuration>

其中的“name”属性为“DBConnStr”的连接字符串节点即是我们这里定义的连接字符串。日后维护时,如果需要修改,只需用文本编辑器改动该字符串,重启站点即可。而对于上面提到

的放在操作代码文件中的字符串,如需改动,则需重新编译整个站点文件,所以只有在开发中才

会使用此种方法。 此处需要注意的一个细节是,“connectionString”中的“|DataDirectory|”是.NET Framework

支持的应用程序域变量,在包含“App_Data”目录的Web站点中,该变量默认被解析到“App_Data”目录中(可以通过 AppDomain.CurrentDomain.SetData 方法设置该变量的默认值),这也是我们之所以将数据库文件放在这个目录下的原因,便于解析,同时避免文件地址的硬编码。 在项目的“App_Data”目录下添加“DBConnection.cs”类文件专用于数据库操作处理,代码

如下: using System; using System.Collections.Generic; using System.Web; using System.Data.OleDb; using System.Configuration; namespace BookShoponWeb { public class DBConnection {

#region Access数据库连接参数

//从配置文件 web.config中读取连接字符串

private string_DBConnStr = ConfigurationManager.ConnectionStrings["DBConnStr"]. ToString();

//在操作代码中直接声明连接字符串

/*private string_DBConnStr = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source= |DataDirectory|/DataBase.accdb;"; */

public string DBConnStr {

get { return _DBConnStr; }

set { _DBConnStr = value; } }

//数据库连接实例

public OleDbConnection DBConn{get;set;} #endregion /// <summary>

/// 连接数据库

/// </summary> public void connection() {

//修改 DataDirectory的默认解析地址 /*AppDomain.CurrentDomain.SetData("DataDirectory", HttpContext.Current.

Request.PhysicalApplicationPath+"App_Code");*/

175

软件工程——理论与实践

if(DBConn ==null) DBConn = new OleDbConnection(DBConnStr); if (DBConn.State != System.Data.ConnectionState.Closed) disconnection(); DBConn.Open(); } /// <summary>

/// 释放数据库连接

/// </summary> public void disconnection() { if (DBConn.State != System.Data.ConnectionState.Closed) DBConn.Close(); } } }

4.4.4 编写页面和逻辑代码

写好了数据库操作代码之后,就可以编写登录模块的页面和后台逻辑代码了。在工程中添加

“Login.aspx”页面,编写页面代码。建议此时使用拆分窗口,编写代码的同时可以即刻见到代码的设计效果。 登录表单的代码如下所示: <div>

<a href="CustomerInfo.aspx?type=Register">尚未注册</a>

<table style="width:400px"> <tr>

<td colspan="2" style=" text-align:center;"><span>用户登录</span></td>

</tr> <tr>

<td>用户名:</td>

<td>

<asp:TextBox ID="TextBox_UserName" runat="server"></asp:TextBox> <span style="color:Red">*</span> <asp:RequiredFieldValidator ID="RequiredFieldValidator_UserName" runat="server"

ErrorMessage="用户名不能为空" ControlToValidate="TextBox_UserName"> </asp:RequiredFieldValidator>

</td> </tr> <tr>

<td>密码:&nbsp; &nbsp;</td>

<td>

<asp:TextBox ID="TextBox_Password" runat="server" TextMode="Password"> </asp:TextBox>

<span style="color:Red">*</span> <asp:RequiredFieldValidator ID="RequiredFieldValidator_Password" runat=

"server"

ErrorMessage="密码不能为空" ControlToValidate="TextBox_Password"></asp: RequiredFieldValidator>

</td> </tr> <tr><td colspan="2" style="height:20px"></td></tr>

176

第 4章 编码及实现

<tr> <td>

<asp:Button ID="Button_Login" runat="server" Text="登录" />

</td> <td>

<asp:Label ID="Label_Message" runat="server" Text=""></asp:Label> </td> </tr> </table> </div>

登录表单的界面如图 4-33所示。

图 4-33 登录表单界面

展开登录模块后台代码文件“Login.aspx.cs”,编写后台代码如下: using System; using System.Collections.Generic; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Data.OleDb; namespace BookShoponWeb { public partial class Login : System.Web.UI.Page {

protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) return;

if (UserLogin(TextBox_UserName.Text.Trim(), TextBox_Password.Text.Trim())) //验证通过

{

if (Session["user_isAdmin"].ToString() == "True") Response.Redirect("/admin/AdminPage.aspx"); else { switch (Request.QueryString["type"]) { case "CustomerInfo": Response.Redirect("CustomerInfo.aspx?type=buy&CustomerId=

" + Session["user_name"]); break; case "Orders": Response.Redirect("MyOrders.aspx?CustomerId=" + Session

["user_name"]); break; default: Response.Redirect("Home.aspx");

177

软件工程——理论与实践

break; } }

}else//验证失败

Label_Message.Text = "用户名不存在或密码错误";

} public bool UserLogin(string userName,string password) { DBConnection DBConn = new DBConnection(); DBConn.connection(); string strSQL = "select * from Customers where (Email=@userName or

CustomerName= @userName) and Password=@password"; OleDbCommand dbComm = new OleDbCommand(strSQL, DBConn.DBConn); dbComm.Parameters.Add(new OleDbParameter("@userName",userName)); dbComm.Parameters.Add(new OleDbParameter("@password",password)); OleDbDataReader dataReader = dbComm.ExecuteReader();

if (dataReader.HasRows)//验证成功

{ dataReader.Read();

Session["user_name"] = dataReader[1].ToString();//用户名

Session["user_isAdmin"] = dataReader[3].ToString();//是否是管理员

DBConn.disconnection(); return true; } DBConn.disconnection(); return false; } } }

这样,用户登录模块就实现完毕了。网上书店是基于 ASP.NET WebForm 的,感兴趣的读者可以尝试使用 ASP.NET MVC 的架构方式实现。

小 结

本章主要讨论了与编码相关的问题。编码就是把软件设计的结果翻译成用某种编程语言书写

的程序。编写代码不是一项简单的工作,而是一个复杂的迭代过程,包括对设计成果的理解、编

写代码、代码检查、代码调试、软件集成及代码优化等。 编程语言是人与计算机进行交互的基本工具,它定义了一组计算机的语法规则,通过这些语

法规则可以把人的意图、思想等转化为计算机可以理解的指令,进而让计算机帮助人类完成某些

任务。编程语言的发展经历了机器语言、汇编语言、高级语言和超高级语言 4个阶段。机器语言是可以直接操纵计算机底层硬件的语言,它采用“0”和“1”为指令代码来编写程序,编写不方便,但是执行速度快。汇编语言也是“面向机器”的低级语言,它采用了一组助记符来代替机器

语言中晦涩、难懂的二进制代码,用地址符号或标号来代替地址码,使得代码比较直观,容易被

程序员理解。高级语言产生于 20世纪 50年代,它采用类似英文的语句来表示语义,脱离了计算机硬件,方便了软件开发人员的使用。高级语言分为面向过程的高级语言和面向对象的高级语言

178

第 4章 编码及实现

两类。超高级语言一般由特定的知识库和方法库支持,是对数据处理和过程描述的更高级的抽象。 选择编程语言时要综合考虑各方面的因素,并做出合理的平衡。通常需要考虑的因素有待开

发系统的应用领域、用户的要求、软件开发人员的喜好和能力、系统的可移植性要求、算法和数

据结构的复杂性以及平台依赖性等。 编程风格是指源程序的书写习惯。规范的编程风格会对后期的软件维护带来很多便利。规范

编程风格可从源程序文档化、数据说明、语句构造、输入输出和效率几个方面入手。 本章还介绍了 Visual Studio的使用方法以及使用 Visual Studio实现网上书店系统的用户登录

模块。

习 题

1.编程语言主要有哪几类?总结每类语言的优缺点。 2.在选择编程语言时通常要考虑哪些因素? 3.对标识符命名时要注意哪些原则? 4.为什么要对源程序进行注释? 5.假如你是一位软件开发项目的负责人,请综合考虑各方面的因素,制定一份该项目的软件

编码的规范书。

179

第5章 软件测试

本章目标 ● 了解软件测试的基本概念以及软件测试的必要性。 ● 掌握软件测试的原则。 ● 熟悉软件测试的常用模型以及每种模型的优缺点。 ● 了解软件测试的各种分类,掌握软件测试按照软件质量因素的类型划分。 ● 熟悉黑盒测试和白盒测试的特点。 ● 掌握等价类划分法。 ● 掌握逻辑覆盖法。 ● 掌握软件测试的一般步骤以及每个阶段性测试的关注点。 ● 掌握面向对象的软件测试与传统软件测试模型的不同以及面向对象测试的特点和方法。 ● 熟悉 Visual Studio 中单元测试工具的用法。 ● 了解其他单元测试工具。 ● 了解利用 Visual Studio 中的工具进行界面测试的方法。

5.1 软件测试的基本概念

软件测试是发现软件中错误和缺陷的主要手段。为了保证软件产品的质量,软件开发人员通

过软件测试发现产品中存在的问题,并对其进行及时的修改。可以说,软件测试的过程就是发现

并改正软件缺陷的过程。 软件缺陷是指软件产品中存在的问题,具体表现为用户所需的功能没有实现,无法满足用户

的需求。由于软件开发是以人为中心的活动,开发人员之间交流的不畅、开发人员对需求理解的

偏差、开发过程中的失误、所使用工具的误差、开发环境的限制等因素都可能造成软件缺陷,所

以缺陷的产生是不可避免的,软件测试的工作是必需的。 测试是开发软件系统中每项可靠的工作都不可避免的部分。

——William Howden 在软件开发过程的任何阶段都可能引入缺陷。缺陷被引入的阶段越早,在软件开发的后期修

复这些缺陷带来的成本损失就越大。尽早地揭示并修复软件缺陷有利于减小已有缺陷对后续软件

开发工作的影响,从而节约软件开发的时间和成本,提高软件开发的质量。

180

第 5章 软件测试

软件测试是软件开发过程中的一个重要阶段。在软件产品正式投入使用之前,软件开发人员

需要保证软件产品正确地实现了用户的需求,并满足稳定性、安全性、一致性、完全性等各个方

面的要求,通过软件测试对产品的质量加以保证。实际上,软件测试过程与整个软件开发过程是

同步的,也就是说,软件测试工作应该贯穿于整个开发过程。

5.1.1 软件测试的原则

软件测试是为了发现错误而执行程序的过程,它并不可能找出所有的错误,但是却可以减少

潜在的错误或缺陷。人们在长期进行软件测试实践的过程中,不断地总结出一些软件测试的经验

和原则,可供我们参考。 (1)完全测试是不可能的。测试并不能找出所有的错误。基于时间、人员、资金或设备等方

面的限制,不可能对软件产品进行完全的测试。在设计测试用例时,也不可能考虑到软件产品所

有的执行情况或路径。 普通程序员认为已经彻底测试过的软件其实只执行了 55%~60%的逻辑路径。采用覆盖分

析器等自动工具可以将上述比例提高到 85%~90%。但是测试软件中 100%的逻辑路径几乎是不

可能的。 ——Robert L. Glass

(2)测试中存在风险。每个软件测试人员都有自己独特的思维习惯或思考问题的方式,在设计

测试用例或者进行产品测试时,难免考虑问题不全面。此外,并不存在十全十美的测试方法,不论

是黑盒测试还是白盒测试,不论采用自动测试还是进行手工测试,被测试的软件产品中都会有被忽

略的环节。而且,测试人员所使用的测试工具本身也是一种软件产品,即测试工具本身也是存在缺

陷的,所以利用测试工具来查找软件缺陷时,也会出现异常情况。综合各种因素,软件测试中是存

在风险的,测试的结果不一定是准确无误的。例如,对一段判定变量 a是否大于 0的伪代码: if (a >= 0) print"a > 1" else print"a <= 0"

如果选用 a=5为测试用例,那么本段代码的错误就不能被发现。 (3) 软件测试只能表明缺陷的存在,而不能证明软件产品已经没有缺陷。软件测试只是查找

软件缺陷的过程,即使测试人员使用了大量的测试用例和不同的测试方法对软件产品进行测试,

测试成功以后也不能说明软件产品已经准确无误,完全符合用户的需求。 (4) 软件产品中潜在的错误数与已发现的错误数成正比。通常情况下,软件产品中发现的错

误越多,潜在的错误就越多。如果在一个阶段内,软件产品中发现的错误越多,就说明还有更多

的错误或缺陷有待于去发现和改正。 (5) 让不同的测试人员参与到测试工作中。在软件开发中存在着“杀虫剂现象 ”。农业中的“杀

虫剂现象”是指:如果长期使用某种药物,那么生物就会对该药物产生抗药性,从而降低了杀虫剂的威

力。同样,在软件开发中也存在着类似的“杀虫剂现象”。每个测试人员在进行软件测试时,都有自己

的思维习惯、喜欢的测试方法、擅长的测试工具。如果同一个软件产品总是由特定的测试人员去测试,

那么基于这个测试人员的思维习惯、测试方法和所使用的测试工具的局限,有些软件缺陷是很难被发现

的。因此,在软件的测试工作中,应该让多个测试人员参与到同一产品或同一模块的测试工作中。 (6)让开发小组和测试小组分立,开发工作和测试工作不能由同一部分人来完成。如果开发

181

软件工程——理论与实践

人员对程序的功能要求理解错了,就很容易按照错误的思路来设计测试用例。如果开发人员同时

完成测试工作,那么测试工作就很难取得成功。 (7)尽早并不断地进行测试,使测试工作贯穿于整个软件开发的过程中。软件开发的各个阶

段都可能出现软件错误。软件开发早期出现的小错误如果不能及时被改正,其影响力就会随着项

目的进行而不断地扩散,越到后期,纠正该错误所付出的代价就越大。因此,应该尽早地进行测

试工作。而且,测试工作应该贯穿在软件开发的各个阶段,这样才能提高软件开发的效率和质量。 正如医生所说,某些疾病在其初发阶段是易于治愈的,但是早期发现却很难……然而,如

果没有在早期被发现和治疗,随着时间的推移,这些疾病将变得很容易发现但却很难治愈。 ——Niccolo Machiavelli

(8)在设计测试用例时,应包括输入数据和预期的输出结果两个部分,并且,输入数据不仅

应该包括合法的情况,还应该包括非法的输入情况。测试用例必须由两部分组成:对程序输入数

据的描述和由这些输入数据产生的程序的正确结果的精确描述。这样在测试的过程中,测试人员就

可以通过对实际的测试结果与测试用例预期的输出结果进行对照,方便地检验程序运行的正确性。 此外,用户在使用软件产品时,不可避免地会输入一些非法的数据。为了检验软件产品是否

能对非法输入做出准确的响应,测试用例应当包括合理的输入条件和不合理的输入条件。测试人

员应该特别注意用非法输入的测试用例进行测试,因为人们总是习惯性地过多考虑合法和期望的

输入条件。实际上,用不合理的输入数据来进行测试,往往会发现较多的错误。 (9)要集中测试容易出错或错误较多的模块。在软件测试工作中存在着二八定律,即 80%的

错误会集中存在于 20%的代码中。为了提高测试的工作效率,应该对容易出错或错误较多的模块给予充分的注意,集中测试这些模块。 (10)应该长期保留所有的测试用例。测试的主体工作完成之后,还要进行回归测试。为了方

便回归测试,有时还可以用已经使用过的用例。保留所有的测试用例有助于后期的回归测试。

5.1.2 软件测试模型

软件测试模型是指软件测试全部过程、活动或任务的结构框架。通常情况下,一个软件测试

模型应该阐明的问题有: (1)测试的时间; (2)测试的步骤; (3)如何对测试进行计划; (4)不同阶段的测试中应该关注的测试对象; (5)测试过程中应该考虑哪些问题; (6)测试需要达到的目标等。 一个好的软件测试模型可以简化测试的工作,加速软件开发的进程。常用的软件测试模型有

V模型、W模型和 H模型。 可以说V模型是最具代表意义的测试模型,它是软件开发中瀑布模型的变种。V模型的重要意义

在于它非常明确地表明了测试过程中存在的不同级别,并且清楚地描述了这些测试阶段和开发过程的

各阶段的对应关系,即反映了测试活动与分析和设计活动的对应关系。V模型的示意图如图 5-1所示。 从 V模型的示意图可以看出,它从左到右描述了基本的开发过程和测试行为。左起从上往下

描述的是开发过程的各阶段,与此对应的是右侧依次上升的部分,即与开发过程各阶段对应的测

182

第 5章 软件测试

试过程的各个阶段。不难发现,在 V模型中,测试工作在编码之后才能进行,所以在软件开发早期各个阶段引入的错误不能及时被发现,尤其是需求阶段的错误只有等到最后的验收测试才能被

识别。对分析、设计阶段产生的错误不能及时发现并改正的缺点会对后期的修复工作带来诸多不

便,造成更多资源的浪费和时间的延迟。

图 5-1 V模型示意图

为了克服 V模型开发和测试不能同步的问题,Evolutif公司发明了W模型,它在 V模型的基础上增加了软件开发阶段中应同步进行的测试活动。如图 5-2所示为W模型的示意图,可以看出,W模型由两个分别代表开发过程和测试过程的 V模型组成。

图 5-2 W模型示意图

183

软件工程——理论与实践

W模型的最大优势在于测试活动可以与开发活动并行进行,这样有利于及早发现错误,但是W 模型也有一定的局限性。在 W 模型中,需求、设计、编码等活动依然是依次进行的,只有上

一阶段完全结束,才有可能开始下一阶段的工作。与迭代的开发模型相比,这种线性的开发模型

在灵活性和对环境的适应性上有很大差距。 H模型强调测试的独立性和灵活性。在 H模型中,软件测试活动完全独立,它贯穿于整个软

件产品的生命周期,与其他流程并行进行。当软件测试人员认为测试准备完成,即某个测试点准

备就绪时,就可以从测试准备阶段进入到测试执行阶段。H模型的示意图如图 5-3所示。

图 5-3 H模型示意图

5.2 软件测试的分类

软件测试可以从不同的角度划分为多种类型,如图 5-4所示。

图 5-4 软件测试的分类

下面介绍按照质量因素划分的软件测试分类。 (1)功能测试关注于软件产品的功能实现,以软件产品的需求规格说明书为依据,检验最终

的软件产品是否实现了需求规格说明书中的所有功能需求。 (2)可靠性测试关注于程序输出结果的准确性,它以需求规格说明书中对系统的可靠性要求

184

第 5章 软件测试

为依据,评测最终的软件产品提供准确输出结果的能力。 (3)可用性测试用来衡量处理服务请求时应用程序的可用频率。顾名思义,它以需求规格说

明书中对系统的可用性要求为依据。可用性和可靠性的区别在于,可用性衡量的是一个应用程序

处理服务请求并且在最短时间内从故障中恢复的能力,而可靠性衡量的是应用程序能够在多长时

间内一直运行并且给出期望的结果值。 (4)软件系统的性能包括多方面的因素,比如输入/输出数据的精度、系统的响应时间、更新

频率、数据的转换和传送时间、操作方式或运行环境变化时软件产品的适应能力、故障处理能力、

资源利用率等。性能测试主要针对软件产品各方面的性能因素,可以细分为负载测试、容量测试、

压力测试。 (5)安全性测试主要验证系统的安全性、保密性等措施是否能有效地发挥作用,包括用户管

理和访问控制、数据备份与恢复、入侵检测等。 除了图 5-4 给出的各种测试类型以外,软件测试还包括配置测试、兼容性测试、安装测试、

文档测试、软件国际化测试、软件本地化测试、α测试和β测试等。 (1)配置测试考察软件系统是否能在多种硬件平台上正常运行。 (2)兼容性测试是为了检测各软件之间是否能正确地交互和共享信息,它主要关注软件的运

行平台和应用系统的版本、标准和规范、数据的共享性。 (3)安装测试是为了发现软件在安装过程中存在的错误,验证其与安装手册的内容是否一致。

与安装测试相对应的还有卸载测试。 (4)文档测试是指检验软件产品的文档是否清晰、准确、一致。 (5)软件的国际化和本地化是相对应的。软件的国际化特性要求软件产品能够支持 Unicode,

支持不同时区的设定、显示和切换,消除一些不容易改变的设置等。显而易见,软件国际化测试

就是验证软件产品是否支持软件国际化所需满足的特性的过程。软件的本地化是将软件产品按特

定的国家、地区的市场需要进行加工、处理,使其满足特定市场用户对软件产品的要求的过程。

软件本地化测试的重点包括翻译问题、文化背景问题、数据格式问题等。 (6)α 测试和 β 测试都是属于验收测试的范畴,是在系统测试之后,产品发布之前进行的测

试过程的最后一个阶段。

5.3 软件测试的方法

在 5.2 节中已经介绍过,按照执行测试时是否需要运行程序,软件测试可以划分为静态测试和动态测试。静态测试以人工测试为主,通过测试人员认真阅读文档和代码,仔细分析其正确性、

一致性及逻辑结构的正确性,从而找出软件产品中的错误或缺陷。静态测试对自动化工具的依赖

性较小,通过人脑的思考和逻辑判断来查找错误,因而可以更好地发挥人的主观能动性。根据软

件开发实践的总结,静态测试的成效非常显著,一般静态测试检测出的错误数可以达到总错误数

的 80%以上。 审查和走查是静态测试的常用形式。审查是指通过阅读并讨论各种设计文档以及程序代码来

检查其是否有错。审查的工作可以独自进行,也可以通过会议的形式将相关的人员召集起来共同

发现并纠正错误。而走查的对象只是代码,不包括设计文档。代码走查以小组会议的形式进行,

相关测试人员提供所需的测试用例,参会人员模拟计算机,跟踪程序的执行过程,对其逻辑和功

185

软件工程——理论与实践

能提出各种疑问,并通过讨论发现问题。 不考虑审查所花费的时间,审查工作使程序员资源节省了 25%。

——Michael Fagan 总而言之,静态测试的效率比较高,而且要求测试人员具有丰富的经验。 与静态测试不同的是,动态测试需要通过实际运行被测程序来发现问题。测试人员可以输

入一系列的测试用例,通过观察测试用例的输出结果是否与预期相符来检验系统内潜在的问题

或缺陷。 动态测试中有两种非常流行的测试技术,即黑盒测试和白盒测试,下面重点介绍这两种技术。 在黑盒测试里,测试人员把被测试的软件系统看成是一个黑盒子,并不需要关心盒子的内部

结构和内部特性,而只关注软件产品的输入数据和输出结果,从而检查软件产品是否符合它的功

能说明。与黑盒测试不同,白盒测试关注软件产品的内部细节和逻辑结构,即把被测的程序看成

是一个透明的盒子。黑盒测试和白盒测试的示意图分别如图 5-5和图 5-6所示。

图 5-5 黑盒测试 图 5-6 白盒测试

不论是黑盒测试还是白盒测试,它们都可以发现被测系统的问题。但是由于它们侧重的角度

不同,所以发现的问题也不尽相同。一般在软件测试的过程中,既要用到黑盒测试,又要用到白

盒测试。大的功能模块采用黑盒测试,小的构件采用白盒测试。 可以说,黑盒测试和白盒测试都是基于用例的测试方法,因为它们都通过运行测试用例来发

现问题。 设计测试用例的唯一规则:覆盖所有特征,但并不创建太多测试用例。

——Tsuneo Yamaura 根据设计用例的方法的不同,黑盒测试包括等价类划分法、边界值分析法、错误推测法、因

果图法、流程图法等,而白盒测试包括逻辑覆盖测试方法和基本路径测试方法。下面将重点对黑

盒测试中的等价类划分法和白盒测试中的逻辑覆盖法进行详细的介绍。

5.3.1 等价类划分法

等价类划分法是把程序的输入域划分为若干子集,然后从每个子集中选取少数具有代表性的

数据用作测试用例,所选取的输入数据对于揭露程序中的错误都是等效的。对于测试来说,某个

等价类的代表值与该等价类的其他值是等价的,因此可以把所有的输入数据划分为若干等价类,

在每一个等价类中取少部分数据进行测试。等价类分为有效等价类和无效等价类。 (1)有效等价类是指对程序的规格说明是有意义的、合理的输入数据所构成的集合。

186

第 5章 软件测试

(2)无效等价类是指对程序的规格说明是无意义的、不合理的输入数据构成的集合。 在划分等价类时,有一些可供遵循的原则。 (1)如果输入条件规定了取值范围或个数,则可确定一个有效等价类和两个无效等价类。例

如,输入值是选课人数,在 0~100之间,那么有效等价类是“0≤学生人数≤100”,无效等价类是“学生人数<0”和“学生人数>100”。 (2)如果输入条件规定了输入值的集合或是规定了“必须如何”的条件,则可确定一个有效

等价类和一个无效等价类。例如,输入值是日期类型的数据,那么有效等价类是:日期类型的数

据;非日期类型的数据。 (3)如果输入条件是布尔表达式,则可以分为一个有效等价类和一个无效等价类。例如,要

求密码非空,则有效等价类为非空密码,无效等价类为空密码。 (4)如果输入条件是一组值,且程序对不同的值有不同的处理方式,则每个允许的输入值对应一个

有效等价类,所有不允许的输入值的集合为一个无效等价类。例如,输入条件“职称”的值是初级、中

级或高级,那么有效等价类应该有 3个,即初级、中级、高级,无效等价类有一个,即其他任何职称。 (5)如果规定了输入数据必须遵循的规则,则可以划分出一个有效的等价类(符合规则)和

若干个无效的等价类(从不同的角度违反规则)。 划分好等价类后,就可以设计测试用例了。设计测试用例的步骤可以归结为以下 3步。 (1)对每个输入和外部条件进行等价类划分,画出等价类表,并为每个等价类进行编号。 (2)设计一个测试用例,使其尽可能多地覆盖有效等价类,重复这一步,直到所有的有效等

价类被覆盖。 (3)为每一个无效等价类设计一个测试用例。 下面将以一个测试 NextDate函数的具体实例为出发点,讲解使用等价类划分法的细节。输入

3个变量(年、月、日),函数返回输入日期后面一天的日期:1≤月份≤12,1≤日期≤31,1812 ≤年≤2012。给出等价类划分表并设计测试用例。 (1)划分等价类,得到等价类划分表,见表 5-1。

表 5-1 等价类划分表

输入及外部条件 有效等价类 等价类编号 无效等价类 等价类编号

日期的类型 数字字符 1 非数字字符 8

小于 1812 9 年 在 1812与 2012之间 2

大于 2012 10

小于 1 11 月 在 1与 12之间 3

大于 12 12

日小于 1 13 非闰年的 2月 日在 1与 28之间 4

日大于 28 14

日小于 1 15 闰年的 2月 日在 1与 29之间 5

日大于 29 16

日小于 1 17 月份为 1月、3月、5月、7月、8月、10月、12月

日在 1与 31之间 6 日大于 31 18

日小于 1 19 月份为 4月、6月、9月、11月 日在 1与 30之间 7

日大于 30 20

187

软件工程——理论与实践

(2)为有效等价类设计测试用例,见表 5-2。

表 5-2 有效等价类设计测试用例

输入数据 预期输出 序号

年 月 日 年 月 日 覆盖范围(等价类编号)

1 2003 3 15 2003 3 16 1,2,3,6

2 2004 2 13 2004 2 14 1,2,3,5

3 1999 2 3 1999 2 4 1,2,3,4

4 1970 9 29 1970 9 30 1,2,3,7 (3)为无效等价类设计测试用例,见表 5-3。

表 5-3 无效等价类设计测试用例

输入数据 序号

年 月 日 预期结果 覆盖范围(等价类编号)

1 xy 5 9 输入无效 8

2 1700 4 8 输入无效 9

3 2300 11 1 输入无效 10

4 2005 0 11 输入无效 11

5 2009 14 25 输入无效 12

6 1989 2 −1 输入无效 13

7 1977 2 30 输入无效 14

8 2000 2 −2 输入无效 15

9 2008 2 34 输入无效 16

10 1956 10 0 输入无效 17

11 1974 8 78 输入无效 18

12 2007 9 −3 输入无效 19

13 1866 12 35 输入无效 20

5.3.2 逻辑覆盖法

逻辑覆盖法以程序内在的逻辑结构为基础,根据程序的流程

图设计测试用例。根据覆盖的目标不同又可分为语句覆盖、分支

覆盖、条件覆盖、分支-条件覆盖、条件组合覆盖和路径覆盖。

图 5-7 程序流程图

下面以一段代码为例,用各种不同的覆盖方法对其进行逻

辑覆盖测试。 Dim x, y As Integer Dim z As Double IF(x>0 AND y>0) THEN z = z/x END IF IF(x>1 OR z>1) THEN z = z + 1 END IF z = y + z

对其进行逻辑覆盖测试的第一步就是要先绘制出它的程

序流程图,如图 5-7所示。

188

第 5章 软件测试

这时就该设计测试用例了。 语句覆盖的基本思想是,设计若干个测试用例,运行被测试的程序,使程序中的每个可执行

语句至少执行一次。该程序段的语句覆盖用例可以是: 输入:{x = 2,y = 3,z = 4} 执行路径:abd 可见,根据用例,执行语句 1、2、3都执行了一次。 分支覆盖的思想是使每个判断的取真分支和取假分支至少执行一次。其用例为:

输入:{x = 3,y = 4,z = 5}执行路径:abd 输入:{x = −1,y = 2,z = 0}执行路径:ace 条件覆盖的思想是使每个判断的所有逻辑条件的每种可能取值至少执行一次。下面给出其用

例设计的过程。

对于判断语句 x>0 AND y>0: 条件 x>0 取真为 T1,取假为−T1 条件 y>0 取真为 T2,取假为−T2 对于判断语句 x>1 OR z>1: 条件 x>1 取真为 T3,取假为−T3 条件 z>1 取真为 T4,取假为−T4 测试用例见表 5-4。

表 5-4 条件覆盖的测试用例

输 入 通 过 路 径 条 件 取 值 覆 盖 分 支

x = 7,y = 1,z = 3 abd T1,T2,T3,T4 bd

x = −1,y = −3,z = 0 ace −T1,−T2,−T3,−T4 ce 分支-条件覆盖就是要同时满足分支覆盖和条件覆盖的要求。其用例取分支覆盖的用例和条件

覆盖的用例的并集即可。 条件组合覆盖的思想是使每个判断语句的所有逻辑条件的可能取值组合至少执行一次。下面

给出其用例设计的过程。 对各判断语句的逻辑条件的取值组合标记如下:

(1)x>0,y>0,记作 T1,T2,条件组合取值 M (2)x>0,y<=0,记作 T1,−T2,条件组合取值−M (3)x<=0,y>0,记作−T1,T2,条件组合取值−M (4)x<=0,y<=0,记作−T1,−T2,条件组合取值−M (5)x>1,z>1,记作 T3,T4,条件组合取值 N (6)x>1,z<=1,记作 T3,−T4,条件组合取值 N (7)x<=1,z>1,记作−T3,T4,条件组合取值 N (8)x<=1,z<=1,记作−T3,−T4,条件组合取值−N 测试用例见表 5-5。

表 5-5 条件组合覆盖的测试用例

输 入 通过路径 条件取值 覆盖组合号

x = 1,y = 3,z = 2 abd T1,T2,−T3,T4 1,7

x = 2,y = 0,z =8 acd T1,−T2,T3,T4 2,5

189

软件工程——理论与实践

续表

输 入 通过路径 条件取值 覆盖组合号

x = −1,y =1,z = 1 ace −T1,T2,−T3,−T4 3,8

x = −2,y = −3,z = 0 ace −T1,−T2,−T3,−T4 4,8

x = 5,y = 9,z = 0 abd T1,T2,T3,−T4 1,6 路径覆盖的思想是覆盖被测试程序中的所有可能的路径,其用例见表 5-6。

表 5-6 路径覆盖的测试用例

输 入 通 过 路 径 覆 盖 条 件

x = 2,y = 4,z = 3 abd T1,T2,T3,T4

x = 1,y = 3,z = 0 abe T1,T2,−T3,−T4

x = −1,y = −1,z = 3 acd −T1,−T2,−T3,T4

x = −2,y = −3,z = 1 ace −T1,−T2,−T3,−T4 一般情况下,这 6种覆盖法的覆盖率是不一样的,其中路径覆盖的覆盖率最高,语句覆盖的

覆盖率最低。

5.4 软件测试的一般步骤

在软件测试的过程中,测试工作可以分为单元测试、集成测试、系统测试、验收测试等多个

阶段。每个阶段完成特定的测试任务。 单元测试是指对软件中最小的可测试单元进行检查和验证。基本单元一般来说是一个函数、

一个过程或者一个类。通常情况下,测试人员采用白盒测试的方法进行单元测试。 集成测试是指在单元测试的基础上,对通过测试的单元模块组装成系统或子系统进行测试。

由于测试的对象是经过单元测试的代码,所以集成测试并不关注各个模块的内部细节,而是关注

模块之间的接口是否运行正常。 系统测试是指将整个软件系统看作一个整体进行测试,包括对功能和性能以及软件所运行的

软硬件环境进行测试。 不为系统测试安排足够的时间简直就是一场灾难。因为延迟发生在项目快完成的时候,所

以直到接近项目的发布日期才有人发现进度上的问题。因此,坏消息没有任何预兆,很晚才会

出现在客户和项目经理面前。 ——《人月神话》

验收测试以用户测试为主,分为α测试和β测试。α测试指的是由用户、测试人员、开发人员

等共同参与的内部测试,而β测试指的是完全交给最终用户的测试。 综上所述,软件测试的一般步骤如图 5-8所示。

图 5-8 软件测试的一般步骤

190

第 5章 软件测试

5.5 单 元 测 试

单元测试(Unit Testing)是对软件基本组成单元进行的测试,其中,基本单元不局限于一个具体的函数或类方法。“单元”具有一些基本的属性,如明确的功能、规格定义、与其他部分明确

的接口定义等,可以清晰地与同一程序的其他单元划分开来。在具体实现中,也可能对应多个程

序文件中的一组函数。单元测试常常由开发人员进行,有些甚至极端地采取“谁编码谁测试”的

方式,但如果人手充足,笔者更推荐采用敏捷开发中强调的结对编程方式,即两人结对,互相给

对方做单元测试。 传统的结构化编程语言(如 C)中,进行测试的单元一般是具体的函数或子过程;在类似 C++

的面向对象编程语言中,测试的单元一般是类或类的函数;对 Ada语言来说,开发人员可以选择独立的过程和函数,或者在 Ada包级别上进行单元测试;单元测试的原则也被扩展到第四代编程语言的开发中,此时的一个单元被典型地划分为一个菜单或显示界面。

5.5.1 单元测试的目的

通俗地讲,可以说测试的目的就是发现软件中的错误。从现代的软件工程的角度看,软件的开发质量是从过程上进行保证的。如果在编码前已经保证详细设计的质量,那么做单元测试时就

不仅仅要检查代码的错误,而需要测试代码是否严格按照详细设计中规定的方式来实现。因此,

单元测试的主要目的有: (1)验证代码是符合设计的; (2)跟踪需求和设计的实现; (3)发现需求和设计中存在的错误; (4)发现编码中存在的错误。

5.5.2 单元测试和集成测试、系统测试的区别

单元测试和集成测试相比,集成测试的对象一般是在概要设计中划分的模块以及这些模块之间的组合,单元测试的对象一般是这些模块下实现具体功能的单元,这些单元常常在详细设计中

精确描述。从现代的测试来看,两者之间的界限正在变得模糊。单元测试中也常常引入集成概念,

比如为了减少桩模块的设计,单元测试常常采用自下而上的测试方法。其目的是为了发现开发中

的错误,提高产品的质量,而不是舍本逐末地去追究两者的区别。 单元测试和系统测试相比,一般来说单元测试由开发人员来做,系统测试由专业的测试人员

来做(尤其是如 GUI 类的系统测试)。单元测试关注单元的具体实现、内部逻辑、数据流向等,以便及早发现问题,属于早期测试,各单元测试之间常常并行。系统测试属于黑盒测试,是从用

户的角度上看待系统,验证系统是否满足用户的需求,其测试基于需求规格说明书,属于后期测

试,是测试环节的一个独立过程。

5.5.3 单元测试的几个误区

由于单元测试需要编写测试工程,而且要针对每个函数编写测试方法,工作量几乎多出一倍,这也导致很多开发人员感性上比较厌恶做单元测试,所以常常有以下错误认识。

191

软件工程——理论与实践

(1)单元测试浪费了太多时间。一旦编码完成,开发人员常常希望能够立即集成,马上看到软件系统的执行。实际上,这种表面上的进度效率常常是掩盖严格单元测试带来的真实意义

上的进度效率。因为过早的集成更多的情况是系统中充满了各种各样的错误,系统甚至无法正

常运行,进一步的结果就是开发人员花费大量的时间追踪错误,并最终导致在软件集成时需要

额外的工期,而且还无法保证系统在投入使用时能够可靠地运行。在实践工作中,进行完整计

划的单元测试和编写实际代码所花费的精力大致相同。一旦完成单元测试,很多错误将被纠正。

在保证代码可靠的前提下,集成将会非常高效,这才是真正意义上的进步。所以完整计划下的

单元测试其实是对时间的更高效利用,而调试人员的不受控和散漫工作方式只会花费更多的时

间,带来较少的成果。 (2)单元测试仅仅证明了这些代码做了什么。这显然是那些没有为每个单元做详细设计规

格说明的开发人员的抱怨,因为没有详细的规格说明,所以当他们进行单元测试的时候,就找

到源代码,分析实现了什么功能,然后为其设计测试代码。结果是为了证明代码确实按照他们

写的方式执行了,换句话说,就是编译器工作正常。所以他们常常做吃力不讨好的事,花费了

大量时间写测试代码,却没有起到真正的测试作用。正常的测试应该是基于详细设计规格说明

的,而不是基于他们的代码实际实现的功能。测试要告诉的是这段代码应该做什么以及实际

做了什么,而不是证明它们功能正常。显然,高质量的测试需要高质量的设计规格说明,这

也就明白了为什么那些开发人员会这样抱怨—没有规格说明,单元测试确实只能证明代码

做了什么! (3)我很棒,不需要进行单元测试。笔者承认确实有一批神级般存在的程序员,他们非常擅

长编程,常常能在很短的时间内写出高效的代码且能在第一次就运行成功。但毕竟多数人不是如

此,而且即便是他们,也会有犯错的时候,我们不能将软件的质量寄托于他们状态良好的时候,

而必须靠严格的过程体系来保证代码的可靠性。Humphry在其 PSP的研究中发现,一般的软件工程师平均缺陷引入率在 100个/千行代码。所以编码不是一个一次性就能成功的过程,严格可重复验证的单元测试能够避免那些让人恼火的代码堆调试。 (4)集成测试和系统测试足以保证软件质量。这个论点的问题在于规模越大的代码复杂性也

越高。在考虑软件全局复杂性的前提下对每个单元进行全面的测试是一件极其困难的事,因为表

面上的正常掩盖了底层大量的隐藏错误。而“时机”一到,这些错误就会集中“爆发”,然后就能

“如愿”听到用户歇斯底里的抱怨了。一个类比的例子就是,电脑能够正常使用,必然是各个软硬

件都在正常运行,而不正常则可能是由各种各样的错误导致,排查错误的原因常常让人变得疯狂,

即便我们拥有强大的搜索引擎。

5.5.4 单元测试的策略

单元测试的策略常有以下几种。 (1)自下而上的测试。先对最下层的模块进行测试,然后依次向上测试,直到所有模块测试

完毕。优点是测试用例可以直接从功能设计中获取,而不必从结构设计中获取,在缺乏结构细节

时非常有用。缺点是随着测试的进行,过程将越来越复杂,越到顶层,结构覆盖率就越难达到。

对任意单元的修改都会导致所有上层单元重新测试。 (2)自上而下的测试。先对最上层模块进行测试,然后逐步向下,直到完成所有测试。这也

符合详细设计的过程,能够和详细设计和编码重叠进行。缺点是随着测试的进行,测试过程越来

越复杂,开发维护成本将增加;而且任何一个单元的修改都将导致下层所有单元被重新测试,下

192

第 5章 软件测试

层单元测试必须等待上层完成,并行性不好。 (3)孤立测试。由于各模块之间的测试没有关联,所以并行性很好。缺点是没有提供一

种集成角度的测试途径。但无疑,相比于前两者,孤立测试优异很多,缺点也可以在集成测

试中弥补。

5.5.5 单元测试的原则

单元测试需要遵守一定的规范,下面是一些基本的原则,读者可以根据自己的具体项目增删

细节。 (1)对全新代码或修改过的代码进行单元测试。 (2)被测对象为实现一组相关功能的代码(一个或一组函数)。 (3)单元测试必须有详细的测试计划,避免随意性。 (4)项目管理者必须保证所有测试用例经过审核。 (5)当测试用例的结果和预期结果不一致时,测试人员必须如实记录实际的测试结果。 (6)当测试计划中的结束标准达到时,单元测试结束。 (7)测试需要达到一定的代码覆盖率。 (8)当程序被修改时,必须进行回归测试以保证没有引入新的错误。

5.6 集 成 测 试

集成测试是在单元测试的基础上,将所有模块按照概要设计要求组装为子系统或系统进行集

成测试。集成测试时,单元测试已经完成,被集成的模块和单元都是经过可靠性验证的;如果不

经过单元测试,那么集成测试的效果将受到影响。

5.6.1 集成测试和系统测试的区别

集成测试所测试的对象是模块间的接口,目的是找出模块接口以及体系结构上的问题。集成

测试依赖于系统的上层架构设计。 系统测试所测试的对象是整个系统以及与系统交互的硬件和软件平台,是站在最终用户的角

度对系统做的功能性测试,还包括一些非功能性的测试,如性能、压力、容量、安全性、恢复性

等。系统测试依赖于用户需求规格说明书和行业的已成文的或事实上的标准和规范。

5.6.2 集成测试考虑的问题

模块集成中常常出现单个模块工作良好,但组合在一起之后不能正常工作的情形。一些问题

只能在全局的层次上才会暴露出来,比如接口定义等,所以集成测试时,应当考虑以下问题: (1)在把各个模块集成在一起时,跨越模块接口的数据是否会丢失。 (2)各个子功能组合起来,是否能达到预期要求的父功能。 (3)一个模块的功能是否会对另一个模块的功能产生负面影响。 (4)全局数据结构是否有问题,会不会被异常修改。 (5)模块集成后,累积误差会不会放大到不可接受的程度。 因此,在进行单元测试之后,集成测试是非常必要的,也是必需的,以便排查模块连接中存

193

软件工程——理论与实践

在的诸多问题,最终构成符合要求的软件子系统或系统。

5.6.3 集成测试的层次和策略

一个产品的开发常常要经历从产品、子系统、子模块、子程序单元的分层设计过程和细化过

程。集成测试主要测试子模块和子系统两个中间层,各层的测试粒度也不同,重点也有所偏重,

一般可以把集成测试分为 3个级别: (1)模块内集成测试; (2)子系统内集成测试; (3)子系统间集成测试。 不同级别测试常使用不同的集成策略,每种都有自己的优缺点和适用项目。所以需要根据自

己的项目选择合适的测试类型,而大型复杂的项目常常综合使用不同的测试策略。以下介绍几种

常见的集成策略: (1)一次性集成 该集成方式一次性将所有组件集成到一起,不考虑组件之间的相互依赖性或者可能存在的风

险;应用一个系统范围内的测试包来证明系统最低限度的可操作性。 优点:在底层单元可靠的情况下,能够迅速地完成集成测试,并且需要相对少的驱动测试模

块;由于省去了逐层测试,需要的测试用例较少;方法执行起来比较简单;并行性很好,人力可

以充分利用。 缺点:由于模块间不可避免地存在模块间接口、全局数据结构冲突的问题,一次性运行成功

的可能性并不大;在出现错误时,定位错误比较困难,因为全局的复杂性常常掩盖局部的细节问

题;即使是系统一次性集成成功,也会有一些接口错误轻易地躲过测试而进入到系统测试环节中。 综合其优点和缺点,一次性集成主要使用在以下几种类型项目中: ● 维护型项目,这类项目由于其产品已经比较稳定,新增的只有少数组件和功能,这时采

用一次性集成会比较合适。 ● 被测系统比较小,而且每个组件都经过充分的单元测试。 ● 产品使用了严格的静室软件工程过程,并且每个开发阶段的质量和单元测试质量都相当高。 (2)自上向下集成 该集成方式和系统的设计顺序一致,可以在第一时间对系统的控制接口进行验证。如果项目

使用迭代式或增量式方法开发,则系统的控制结构模型与树是一致的,其中最上层的组件具有控

制的责任,采用自上向下的集成测试首先集中于最上层组件,然后逐步向下。有广度优先和深度

优先两种策略。 优点:自上向下的测试过程能较早地从全局视角验证控制,如果核心控制有问题,就能尽早

发现而减少返工;如果按照深度优先方式组装测试,就能首先实现和验证一个完整的软件功能,

为后续的集成提供可靠的基础保证;功能可行性较早地验证,能给开发者和用户带来信心;只需

编写最上层模块的驱动模块,然后每个测试过的上层模块都可以充当底层的驱动模块,减少了驱

动模块的开发;由于和设计顺序一致,所以可以和设计并行进行,如果目标环境可能存在改变,

该方法也能灵活适应;支持故障隔离,比如如果 A模块正确,和 B集成后出错,那么就可以将故障锁定在 B模块或 A与 B的接口处。 缺点:底层组件行为验证被推迟了,同时为了能够有效测试,需要控制模块具有较高可测试

性;随着底层模块的不断增加,系统越来越复杂,导致底层测试不充分,同时需要开发越来越多

194

第 5章 软件测试

的底层支持模块来保证上层的测试。 综合其优缺点,该集成方法比较适用于结构化编程方法的软件,这类产品的结构相对比较简

单。自上向下集成策略的产品特点有: ● 产品控制结构比较清晰和稳定; ● 产品上层接口变化比较小; ● 产品底层接口未定义或经常需要修改; ● 产品控制模块具有技术风险,希望及早地验证; ● 希望及早地看到系统的功能行为; ● 在极限编程中使用探索性开发思路时,可以采用该集成策略。 (3)自下向上集成 该方式从具有最小依赖的底层组件开始,按照依赖关系树,逐层向上集成。每个模块测试之

后都可以成为上层模块的支持模块,避免了支持模块的开发。 优点:允许对下层模块行为进行早期验证,之后的每一次集成都会有一个可靠的下层模块作

为支持;在工作的早期,各下层模块没有依赖关系,可以并行进行,效率要比自上向下集成高效

一些;也支持故障隔离。 缺点:上层驱动模块的开发工作量比较大;对高层的验证被推迟到最后,设计上的错误发

现比较晚,出现问题时,修改设计代价极大;越到上层,系统越复杂,对于底层的异常将很难

覆盖。 综合其优缺点,该集成方式比较适合具有以下特征的软件系统: ● 采用契约式开发的产品。这类产品的代码规格使用一种用于描述代码隐含契约的形式化

语言明确的表达,代码的实现必须严格依据契约规则。 ● 底层接口比较稳定。 ● 高层接口变化比较频繁。 ● 底层模块较早被完成的产品。有些公司开发软件产品时,会有专门的支持团队负责开发

各种组件,提供给开发团队用于产品开发。 (4)混合集成 由于自上向下和自下向上都有自己的优缺点,因此,若将两种方法结合起来,通过合理的方

案实现优劣互补,将会有益于集成的顺利进行。混合集成正是采用了这种方式,通过把系统分层,

中间一层为目标层,然后对上层使用自上向下集成策略,对下层使用自下向上集成策略,两种方

式在目标层实现会合。 这种集成方式好处是两种集成方式优劣互补,但坏处是导致中间层在被集成前不能被充分测

试。但相对来讲,该方式综合效益较好,多数集成采用这种方式。 除了上面提到的几种集成策略,还有很多其他策略,比如基干集成、分层集成、高频集成、

基于功能集成、基于进度集成、基于风险集成、基于事件集成、基于使用集成、分布式集成等。

在实际项目中,最终要的是根据自己的项目特点选择合适的集成策略,毕竟上面介绍的每种策略

都有优劣和应用局限,灵活运用才是解决问题的关键。

5.6.4 集成测试的过程

根据 IEEE 的过程标准 IEEE Std 1012-1998,集成测试分为 4个阶段:计划阶段、设计阶段、实现阶段和执行阶段。

195

软件工程——理论与实践

(1)计划阶段 ● 时间安排 常常在概要设计完成评审后大约一星期开始。

● 输入 需求规格说明书 概要设计文档 产品开发计划路标

● 入口条件 概要设计文档已经通过评审。

● 活动步骤 确定被测试对象和测试范围 评估测试对象的数量和难度,即工作量 确定角色分工和任务划分 标识出各阶段时间、任务、约束等条件 考虑一定的风险分析及应急计划 考虑和准备集成测试需要的测试工具、测试仪器、环境资源等 考虑技术需求等相关支持 定义测试完成标准

● 输出 集成测试计划。

● 出口条件 集成测试计划通过概要设计阶段基线评审。

(2)设计阶段 ● 时间安排 常常和详细设计同步进行。

● 输入 需求规格说明书 概要设计 集成测试计划

● 入口条件 概要设计阶段基线通过评审。

● 活动步骤 被测对象结构分析 集成测试模块分析 集成测试接口分析 集成测试策略分析 集成测试工具分析 集成测试环境分析 集成测试工作量估计和安排

● 输出

196

第 5章 软件测试

集成测试设计(方案)。 ● 出口条件 集成测试设计通过详细设计基线评审。

(3)实现阶段 ● 时间安排 编码阶段开始后进行。

● 输入 需求规格说明书 概要设计 集成测试计划 集成测试设计

● 入口条件 详细设计阶段基线通过评审。

● 活动步骤 集成测试用例设计 集成测试规程设计 集成测试代码设计 测试测试脚本 集成测试工具

● 输出 集成测试用例 集成测试规程 集成测试代码 集成测试脚本 集成测试工具

● 出口条件 测试用例和测试规程通过编码阶段基线评审。

(4)执行阶段 ● 时间安排 单元测试已经完成。

● 输入 需求规格说明书 概要设计 集成测试计划 集成测试设计 集成测试用例 集成测试规程 集成测试代码 集成测试脚本 集成测试工具

197

软件工程——理论与实践

详细设计 代码 单元测试报告

● 入口条件 单元测试阶段已经通过基线化评审。

● 活动步骤 执行集成测试用例 回归集成测试用例 撰写集成测试报告

● 输出 集成测试报告。 ● 出口条件 集成测试报告通过集成测试阶段基线评审。

5.6.5 集成测试的原则

集成测试是单元测试到系统测试的过渡测试,位置极其重要,而又因为其不容易做好,常常

投入力度不够。以下总结了一些做好集成测试比较通用的原则,可以在进行集成测试的时候作为

参考。 (1)公共接口必须实现全部测试。 (2)关键模块必须进行充分测试。 (3)集成测试应当按一定层次进行。 (4)集成策略选择应当综合考虑质量、成本和进度三者关系。 (5)集成测试应当尽早开始,并以概要设计为基础。 (6)在模块和接口的划分上,测试人员应当和开发人员充分沟通。 (7)当接口发生更改时,所有被影响接口必须进行回归测试。 (8)应当严格根据计划或方案进行,避免随意性。 (9)项目管理者必须保证测试用例都经过审核。 (10)测试执行结果应当如实详细记录。

5.7 系 统 测 试

系统测试是将已经集成好的软件系统,作为整个计算机系统的一个元素,与计算机硬件、外设、支持软件、数据和人员等其他系统元素结合在一起,在实际运行环境中对计算机系统进行一

系列的组装测试和确认测试。 系统测试的目的在于通过与系统的需求定义作比较,发现软件与系统定义不符合的地方,以

验证软件系统的功能和性能等特性满足其规约所指定的要求。系统测试的测试用例应根据需求规

格说明书,并在实际的使用环境中进行测试。 在传统的 V型开发模型中,系统测试是产品提交给用户前进行的最后阶段测试,是软件的最

后一道防线,一旦有漏洞或错误从测试中逃脱,将会直接进入到用户使用的最终软件系统中。不

198

第 5章 软件测试

仅损害开发公司的信誉,重者可能对客户的应用系统产生灾难影响,比如银行使用的系统。因此,

软件的质量如何,软件测试工作是否严谨规范与能否顺利完成系统测试关系极大。 系统测试涉及的内容非常广泛,涉及实际运行中的方方面面,而不仅仅是单元和集成测试中

对系统本身代码和功能的测试。主要类型有: ● 功能测试 ● 性能测试 ● 容量测试 ● 压力测试 ● 安全测试 ● GUI测试 ● 故障测试 ● 兼容性测试 ● 可靠性测试 ● 可用性测试 ● 可安装性测试 ● 文档测试 ● 在线帮助测试 ● 恢复备份测试 ● 协议一致性测试 ● 安装测试 除此之外,还有一些专项性测试,如: ● 验收测试 ● Alpha测试 ● Beta测试 ● 指标测试 ● 配置测试 ● 外场测试 ● 数据库测试 ● 回归测试 以下部分结合功能、性能、安全和 GUI测试进行介绍,以让读者建立系统测试的基础知识。

由于系统测试涉及面太广,更多的测试类型及详细内容建议大家阅读一些专门讲解系统测试的

书籍。

5.7.1 功能测试

功能测试是系统测试中最基本的测试,它不管软件内部是如何实现的,而只是根据需求规格说明书和测试需求列表,验证产品的功能是否符合需求规格,主要检验以下几个方面: (1)功能是否全部实现,有没有遗漏; (2)功能是否满足用户需求和系统设计的隐藏需求; (3)能否正确地接受输入,并给出正确结果。 功能测试要求测试设计者对产品规格说明、需求文档、产品业务功能都非常熟悉,同时要求

199

软件工程——理论与实践

掌握测试用例的设计方法,才能设计出好的测试方案和测试用例,高效地完成测试。 在进行功能测试时,作为功能测试的基本输入,首先需要对需求规格说明书进行分析,分析

步骤如下: (1)对每一个明确的功能需求进行标号。 (2)对每一个可能隐含的功能需求进行标号。 (3)对于可能出现的功能异常进行分类分析并标号。 (4)对前 3个步骤获得的功能需求进行分级,以便为每个功能点计划投入的人力等;由于对

每个功能点都进行充分测试需要极大的代价,所以常常需要将需求功能划分为关键需求功能和非

关键需求功能,关键需求功能是指产品核心功能,如果关键功能失败,则可能导致用户直接拒绝

使用产品。 (5)对每个功能进行测试分析,以决定是否可测,如何测,如何输入,可能输出等。 (6)为测试制订脚本化和自动化支持。 功能测试常用的用例设计方法有: ● 规范导出法 ● 等价类划分 ● 边界值分析 ● 因果图 ● 判定表 ● 正交实验设计 ● 基于风险的测试 ● 错误猜测法

5.7.2 性能测试

性能测试是用来测试软件系统在实际的集成系统中运行性能的。因为无论是在单元测试,还

是在集成测试中,都没有将系统作为一个整体放入实际环境中运行,因此,只有在性能测试阶段

才能够真正看到系统的实际性能。 对于实时系统和嵌入式系统,提供符合功能需求但不符合性能需求的软件是不能接受的。性

能测试的目的是度量系统相对于预定义目标的差距。需要的性能级别针对于实际的性能级别进行

比较,并把其中的差距文档化。 例如,压力测试通过远超过平均数量的用户和请求来获取系统的抗压能力,用于试图耗尽如

缓冲区、CPU 时间片、I/O 资源等方面的资源。这种形式的测试在评价针对拒绝服务方面的危险非常有帮助。 性能测试一般要有专门的工具支持,必要情况下还要自己开发专门的接口工具。有一些成熟

的商业性能测试可以用于 GUI和Web等方面的测试,诸如内存分析工具、指令分析工具等。 下面是一些性能测试中可能要考虑的方面: ● CPU时间片使用情况 ● 缓存使用情况 ● 内存使用情况 ● I/O使用情况 ● 每个指令的 I/O数量

200

第 5章 软件测试

● 信道使用情况 ● 每个模块执行时间百分比 ● 一个模块等待 I/O完工的百分比时间 ● 指令随时间的跟踪路径 ● 控制从一个模块到另一个模块的次数 ● 遇到每一组指令等待的次数 ● 每一组指令页换入和换出的次数 ● 系统反应时间 ● 系统吞吐量 ● 系统负载能力,额定负载、最高负载等 收集系统执行时间和资源使用情况可以采用两种方式:一是在运行环境中使用性能监视器的

方法,在固定时间间隔内收集系统状态信息;二是采用探针的方法,即在系统代码中插入许多程

序指令,通过这些指令记录系统状态,并最终将收集的数据整理成外部格式报告。

5.7.3 安全测试

安全测试的目的是验证系统的保护机制是否能够在实际的环境中抵御非法入侵、恶意攻击等

非法行为。任何包含敏感信息或能够对个人造成不正当伤害的计算机系统都会成为被攻击的目标。

入侵的内容非常广泛,包括仅仅为了练习技术而试图入侵的黑客,为了报复而试图破坏系统的内

部雇员,以及为了获取非法利益而试图入侵系统的非法个人甚至组织。 在安全测试中,测试人员常常扮演系统攻击者的角色,然后尝试各种方案入侵系统,如企图

获取系统超级密码;使用任何能够瓦解系统防护机制的软件;劫持系统,使别人无法使用;有目

的地引发系统错误,使系统崩溃,并从错误的信息以及恢复过程中侵入系统等。 理论上,只要有足够的时间和资源,就一定能设计出一个方法侵入一个系统。所以系统设计

者的目的不是设计出一套方案,从理论上杜绝一切可能的攻击,因为这是不现实的,除非系统不

被使用。设计者的目的是要把系统设计为想要攻破系统而付出的代价大于攻破系统之后得到的信

息价值。 下面是一些安全测试中常常要考虑的问题: ● 控制特性是否工作正确 ● 无效或不可能的参数或指令是否被有效检测并被适当处理,比如针对注入攻击等 ● 错误和文件访问是否被适当地记录 ● 不正常的登录以及权限高的登录是否被详细记录,常用来追踪入侵者 ● 影响比较严重的操作是否被有效记录,比如系统权限调整,增删文件等 ● 是否有变更安全性表格的过程 ● 系统配置数据是否正确保存,系统故障发生后是否可以恢复 ● 系统配置能否正常导入和导出到备份设备上 ● 系统关键数据是否被加密存储 ● 系统口令是否能够有效抵抗攻击,如字典攻击等 ● 有效的口令是否被无误接受,失效口令是否被及时拒绝 ● 多次无效口令后,系统是否有适当反应,这对于抵抗暴力攻击非常有效 ● 系统的各用户组是否维持了最小权限

201

软件工程——理论与实践

● 权限划分是否合理,各种权限是否正常 ● 用户的生命期是否有限制,被限制后用户能够恶意突破限制 ● 低级别用户是否可以使用高级别用户的命令 ● 用户是否会自动超时退出,以及退出之后用户数据是否被及时保存 ● 防火墙安全策略是否有效,端口设置是否合理 安全测试机制的性能和安全机制本身一样重要,例如: (1)有效性。安全性控制一般要求比系统的其他部分具有更高的有效性。 (2)生存性。抵御错误和严重灾难的能力,包括对错误期间紧急操作模式的支持、之后的备

份操作和恢复到正常操作的能力。 (3)精确性。安全性控制精度如何,精确性围绕错误的数量、频率和严重性。 (4)反应时间。反应时间过慢将会导致用户绕过安全机制,或者给用户的使用带来不便。 (5)吞吐量。安全性控制是否支持必需的使用吞吐量,吞吐量包含用户和服务请求的峰值和

平均值。 安全性测试的用例设计方法有: ● 规范导出法 ● 边界值分析 ● 错误猜测法 ● 基于风险的测试 ● 故障插入技术

5.7.4 GUI 测试

图形化用户接口(Graphic User Interface,GUI)已经越来越成为人们最喜欢的人机交互界面。虽然命令行界面具有非常高的效率和便捷性,但相对于命令行界面,GUI界面降低了使用难度以及用户的知识储备要求,因此,GUI的好坏直接影响到用户使用软件时的效率和心情以及对系统的印象。通过严格的 GUI测试,软件可以更好地服务于使用者。

GUI测试包含两方面内容,一是界面实现与界面设计是否吻合;二是界面功能是否正确。GUI测试相对功能测试来说要困难一些,主要有以下原因。 (1)GUI的可能接口空间非常巨大。比如,不同的 GUI活动序列可能导致系统处于不同的状

态,这样测试的结果会依赖于活动序列。有时单看某个测试顺序下,功能是正常的;但换个顺序,

功能就出现了异常。而完全覆盖系统的状态集有时非常困难。 (2)GUI的事件驱动特性。由于用户可能点击屏幕上的任何一个位置,于是产生非常多的用

户输入,模拟这类输入比较困难。 (3)GUI测试的覆盖率理论上不如传统的结构化覆盖率成熟,难以设计出功能强大的自动化

工具。 (4)界面美学具有很大的主观性。比如界面元素大小、位置、颜色等,不同的人常常有不同

的结果,因此难以定出一个标准。 (5)糟糕的界面设计使得界面与功能混杂在一起,这使得界面的修改会导致更多的错误,同

时也增加了测试的难度和工作量。 为了更好地进行 GUI测试,一般将界面与功能分离设计,比如分成界面层、界面与功能接口

层、功能层。这样 GUI的测试重点就可以放在前两层上。

202

第 5章 软件测试

GUI测试常采用越早测试越好的原则,通常在原型出来之后就开始着手进行 GUI测试。由测试人员扮演场景中的角色,模拟各种可能的操作和操作序列。由于测试工作相对枯燥,可以使用

一些自动化测试工具,一些很不错的工具有 WinRunner、Visual Studio UnitTest 等。自动化 GUI测试的基本原理是录制和回放脚本。 设计 GUI测试用例时,常常沿用以下步骤进行思考。 (1)划分界面元素,并根据界面复杂性进行分层。 一般将界面元素分成 3个层:第 1层为界面原子,即界面上不可再分割的单元,如按钮、图

标等;第 2层为界面元素的组合,如工具栏、表格等;第 3层为完整窗口。 (2)在不同的界面层次确定不同的测试策略。 对界面原子层,主要考虑该界面原子的显示属性、出发机制、功能行为、可能状态集等内容。 对界面元素组合层,主要考虑界面原子的组合顺序、排列组合、整体外观、组合后的功能行

为等。 对完整窗口,主要考虑窗口的整体外观、窗口元素排列组合、窗口属性值、窗口的可能操作

路径等。 (3)进行测试数据分析,提取测试用例。 对于元素外观,可以从以下角度获取测试数据 : ● 界面元素大小 ● 界面元素形状 ● 界面元素色彩、对比度、明亮度 ● 界面元素包含的文字属性(如字体、排序方式、大小等) 对于界面元素的布局,可以从以下角度获取测试数据: ● 元素位置 ● 元素对齐方式 ● 元素间间隔 ● Tab顺序 ● 元素间色彩搭配 对于界面元素的行为,可以从以下角度获取测试数据: ● 回显功能 ● 输入限制和输入检查 ● 输入提醒 ● 联机帮助 ● 默认值 ● 激活或取消激活 ● 焦点状态 ● 功能键或快捷键 ● 操作路径 ● 撤销操作 (4)使用自动化测试工具进行脚本化工作。 GUI测试的用例设计方法有: ● 规范导出

203

软件工程——理论与实践

● 等价类划分 ● 边界值分析 ● 因果图 ● 判定表 ● 错误猜测法

5.8 面向对象的软件测试

在基于面向对象思想的软件开发中,由于面向对象的软件工程方法与传统的软件工程方法有

诸多不同,传统的软件测试模型对面向对象的软件系统已经不再适用。 在传统的软件工程中,测试是按照单元测试、集成测试、系统测试到验收测试的顺序进行

的。单元测试一般针对一个过程或者函数。当单元测试通过后,就把相应的单元按照一定的策

略集成起来,然后再测试集成之后模块之间的接口及交互是否正常。最后再进行系统测试和验

收测试。 然而,在面向对象的软件开发中,程序的基本单元是类或对象,而不再是函数或者过程。所

以,单元测试通常以类或对象为单位。类的本质和特征会对单元测试造成很多影响。比如,类具

有多态性,不论与特定对象确切相关的类是什么,测试者都要保证代码能够正常工作。类还支持

信息隐藏的特性,这个特性会使测试复杂化,有时需要向类的接口中添加一些操作才能完成特定

的测试工作。 与死亡和税收一样,测试既是令人不愉快的,也是不可避免的。

——Ed Yourdon 此外,传统的软件工程中的集成测试所要求的逐步将开发模块搭建在一起进行测试的方法对

面向对象的软件开发已经不再适用。面向对象的系统中,程序结构已经不再是传统的功能模块结

构,所以不再适宜将模块按照自顶向下或者自底向上的策略进行集成。因为类的组件之间存在着

交互,一次集成一个操作或属性到类中不太可行。系统集成策略的改变必然会使集成测试时策略

发生相应的变化。通常,面向对象的集成测试会采用基于线程或者基于使用的测试方法。在基于

线程的测试中,首先把响应系统的某个事件所需要的一组类集成起来,然后分别集成并测试每个

线程。在基于使用的测试中,首先测试系统中不与服务器相关联的类,然后再逐层往下测试,直

到测试完整个系统。 实际上,在面向对象的软件开发中,人们已经抛弃了传统的测试模型。针对面向对象的开发

模型中面向对象分析(OOA)、面向对象设计(OOD)和面向对象实现(OOP)3 个阶段,同时结合传统的测试步骤的划分,面向对象的软件测试可以分为: (1)面向对象分析的测试; (2)面向对象设计的测试; (3)面向对象实现的测试; (4)面向对象的单元测试; (5)面向对象的集成测试; (6)面向对象的系统测试及验收测试。

204

第 5章 软件测试

测试目标就是在现实的时间范围内利用可控的工作量尽可能多地找到错误。对于面向对象

软件,尽管这个基本目标是不变的,但面向对象软件的本质特征改变了测试策略和测试战术。 ——Roger S. Pressman

1.面向对象分析的测试

结构化需求分析把目标系统看成是一个由若干功能模块组成的集合,而面向对象需求分析以

现实世界中的概念为模型结构。前者关注系统的行为,即功能结构,而后者更关注于系统的逻辑

结构。对面向对象需求分析的测试要考虑: (1)对认定的对象或类的测试; (2)对定义的属性和操作的测试; (3)对类之间层次关系的测试; (4)对对象之间交互行为的测试; (5)对系统逻辑模型的测试等。 2.面向对象设计的测试

与传统的软件工程方法不同的是,面向对象分析和面向对象设计之间并没有严格的界限。实

际上,面向对象设计是对面向对象分析结果的进一步细化、纠正和完善。对面向对象设计的测试

涉及面向对象分析的测试内容,但是会更加关注对类及其类之间关系的测试和对类库支持情况的

测试。 3.面向对象实现的测试

面向对象的程序具有封装、继承和多态的特性。测试多态的特性时要尤为注意,因为它使得

同一段代码的行为复杂化,测试时需要考虑不同的执行情况和行为。由于系统功能的实现分布在

类中,所以本阶段的测试中还要重点评判类是否实现了要求的功能。 4.面向对象的单元测试

面向对象的单元测试以类或对象为单位。由于类包含一组不同的操作,并且某些特殊的操作

可能被多个类共享,因此单元测试不能孤立地测试某个操作,而是将操作作为类的一部分。 传统的测试用例是通过软件的输入—处理—输出视图或单个模块的算法细节来设计的。面

向对象测试侧重于设计适当的操作序列以检查类的状态。 ——Roger S. Pressman

5.面向对象的集成测试

面向对象的集成测试采用基于线程或者基于使用的测试方法。基于线程的测试是指把回应系

统外界输入的一组相关的类集成起来,对线程进行集成并测试。基于使用的测试方法按照类对服

务器的依赖以及对其他类的依赖程度,把类划分为独立类和依赖类。 (1)独立类是指那些几乎不使用服务器的类。在进行基于使用的测试的时候,先对独立类进

行测试。 (2)依赖类是使用独立类的类,即它们对独立类存在着某种程度的依赖。 在测试完独立类后,就可以对依赖类进行测试了。依赖类中可能还划分为多个层次,测试时

按照逐层向下的顺序,直到测试完整个系统。 6.面向对象的系统测试及验收测试

在系统测试的过程中,软件开发人员要尽量搭建与用户的实际使用环境相同的平台,对目标

205

软件工程——理论与实践

系统是否能作为一个整体,满足用户在性能、功能、安全性、可靠性等各个方面对系统的要求做

出检测和评估。面向对象的系统测试要以面向对象需求分析的结果为依据,对需求分析中描述的

对象模型、交互模型等各种分析模型进行检验。 验收测试是以用户为主的测试,是将软件产品正式交付给用户或市场发布之前的最后一个测

试阶段。

5.9 利用 Visual Studio 中的工具进行单元测试

5.9.1 UnitTest 使用初步

Visual Studio 2010 中包含有单元测试工具,它基于黑盒测试的概念,可以对运行在 Visual Studio平台上的代码进行单元测试。若要使用该测试工具,需首先确认在安装 Visual Studio 2010的过程中安装了单元测试组件。下面以一个简单的Windows控制台应用程序为例,具体演示Visual Studio 2010中单元测试工具的使用方法。 启动 Visual Studio 2010后新建一个Windows Console Application,然后在该项目下完成两个

类,分别是 Arithmetic.cs和 Program.cs。其中,Arithmetic.cs里含有对两个整数进行加、减、乘、除四则运算的函数,如图 5-9所示;而 Program.cs里包含Main函数,它调用 Arithmetic中的成员函数,完成相关的计算,如图 5-10所示。

图 5-9 Arithmetic类

由图 5-9和图 5-10可以看出,Arithmetic类中包含 4个静态成员函数,分别计算两个整数的和、差、积与商。其中,在求商的函数中,还考虑了除数为 0的异常情况。在 Program类的Main

206

第 5章 软件测试

函数中,程序从控制台接收用户输入的两个整数,然后调用 Arithmetic 类中的静态成员函数,并将计算结果输出到控制台上。

图 5-10 Program类

在进行单元测试的过程中,可以把一个类看成是一个单元模块,也可以把一个函数看成是一

个单元模块。不过,在面向对象的软件开发过程中,更习惯于把类当作单元模块的基本单位。下

面,我们来对 Arithmetic.cs进行单元测试。在当前解决方案下新建一个专用于测试的工程,选择“添加”→“新建项目”,在弹出的窗口中,将工程的类型设为基于 Visual C#语言的 Test Project,如图 5-11所示。

图 5-11 新建测试工程

207

软件工程——理论与实践

创建完毕,可以在解决方案 UnitTestInstance 中看到新的测试工程 TestProject1。为UnitTestInstance工程创建测试有两种方法,可以直接在 Unit Test Tool自动产生的 UnitTest1.cs中自定义完成(此时需要先添加 UnitTestInstance工程的引用),也可以利用 Unit Test Tool自动产生测试函数的框架。这里采用第二种方法。打开 Arithmetic.cs文件,将鼠标置于代码编辑窗口中右击,然后选择“创建单元测试”,如图 5-12所示。

图 5-12 创建单元测试

在弹出的对话框(见图 5-13)中可以设置有关测试的各种信息,如被测试的对象、依赖的测试工程。在这里,我们选择对 Arithmetic.cs中的 4个静态成员函数进行测试,将测试工程的输出项目选择为先前新建的测试工程。 有关测试文件的更多信息可以在如图 5-13 所示的对话框中选择“设置”,然后在弹出的窗口

(见图 5-14)中进行设置,例如,测试文件和测试函数的命名规则。

图 5-13 设置测试信息 图 5-14 设置测试信息

208

第 5章 软件测试

建立单元测试之后,在 TestProject1工程中,在“引用”文件夹下可以看到自动添加的对工程UnitTestInstance 的引用,如果是手动创建测试,则需要手动添加该引用。然后观察生成的ArithmeticTest.cs,它包含一个私有的 TestContext类型的成员变量以及对应的属性,该变量存储了与测试运行有关的上下文信息。此外,ArithmeticTest.cs中还包含 4个测试函数,它们分别对应于 Arithmetic.cs 中被测试的 4 个函数。仔细观察可以发现,测试工具已经帮我们完成了每个测试函数的算法,我们只需要根据“TODO”提示,对函数进行完善即可。下面以 SumTest()函数(见图 5-15)为例进行介绍。

图 5-15 SumTest()函数

可以发现,SumTest()函数没有参数,且没有返回值。实际上,所有的测试函数都没有参数,也没有返回值。在函数的算法上,它首先定义两个整数,然后比较实际求和的结果与利用 Sum()函数求和的结果,如果两者相等,则测试成功,否则测试失败。不难理解,这是一种黑盒测试的

思想,因为我们并不需要研究 Sum()函数的内部逻辑,而是将 Sum()函数看成是一个黑盒子,只关心它的输入和输出。如果输出符合我们的预期,那么该函数的测试就是成功的。所以所有进行黑

盒测试的函数必须有返回值,否则就不能使用这种方法进行测试。 在 SumTest()里,用到 Assert 类,中文翻译为“断言”。这个类在测试中非常重要。使用

MicroSoft.VisualStudio.TestTools.UnitTesting命名空间(包含在 UnitTestFramework.dll中)的 Assert类可对特定功能进行验证。当然,有各种各样的测试工具,每种测试工具的测试方法不同,在

下一节中我们将会介绍其他的测试工具。如果安装了其他与 Visual Studio集成的测试工具,那么所使用的命名空间取决于所选择的测试工具。单元测试方法执行开发代码中的方法代码,但

只有包含 Assert 语句时才能报告代码行为方面的内容。Assert 类包含计算布尔值条件的一组静态方法。如果被验证的条件计算为 true,则断言通过,否则断言将失败,并抛出 AssertFailed- Exception异常。

Assert.AreEqual(Object, Object)用来验证指定的两个对象是否相等。通常,第一个参数为单元测试要求的对象,而第二个参数为单元测试实际生成的对象。使用这一方法时要注意,被比较的

两个对象如果逻辑值相等,但是数值类型不一样,那么这两个对象也会被认为是相等的,比如 20L不等于 20,但逻辑值相等,断言为真。此外,对于复杂的数据类型,在使用这一方法之前,需要在数据类型的定义中重写 Equals()函数,因为 Assert.AreEqual()在执行的过程中会调用参数所属数据类型的 Equals()函数。

Assert.Inconclusive()指示断言不能被验证为真还是为假。它在不检查任何条件的情况下指示断言无结论。创建单元测试时 Visual Studio生成的代码包括一条 Inconclusive语句作为占位符。在

209

软件工程——理论与实践

运行测试之前,可以把 Assert.Inconclusive()语句注释掉。 SumTest()函数修改后如图 5-16所示。

图 5-16 修改后的 SumTest()函数

UnitTest测试工具包含很多的断言函数,即使是 Assert.AreEqual函数也有 18个重载版本。其他的一些常用断言函数包括 Assert.AreNotEqual、Assert.AreNotSame、Assert.AreSame、Assert.Fail、Assert.IsFalse 等。表 5-7 列出了微软官方 UnitTest 使用文档中的一些常用断言函数的具体信息。

表 5-7 部分 Assert函数

函数名称 说明

AreEqual(object,object) 验证指定的两个对象是否相等。如果两个对象不相等,则断言失败

AreEqual(Double,ouble, Double)

验证指定的两个双精度型值是否相等或者是否在对方的指定精度内。如果它们不

位于对方的指定精度内,则断言失败

AreEqual < T > (T, T) 验证指定的两个泛型类型数据是否相等。如果它们不相等,则断言失败

AreNotEqual(Object, Object) 验证指定的两个对象是否不相等。如果两个对象相等,则断言失败

AreSame(Object, Object) 验证指定的两个对象变量是否引用同一个对象。如果它们引用不同的对象,则断

言失败

AreNotSame(Object, Object)验证指定的两个对象变量是否引用不同的对象。如果它们引用同一个对象,则断

言失败

Fail(String) 在不检查任何条件的情况下使断言失败。显示消息

Inconclusive(String) 指示无法验证断言。显示消息

IsFalse(Boolean) 验证指定的条件是否为 false。如果该条件为 true,则断言失败

IsInstanceOfType(Object, Type) 验证指定的对象是否为指定类型的实例。如果在该对象的继承层次结构中找不到

该类型,则断言失败

IsNull(Object) 验证指定的对象是否为 null。如果该对象不为 null,则断言失败

IsTrue(Boolean) 验证指定的条件是否为 true。如果该条件为 false,则断言失败

ReplaceNullChars(String) 在字符串中,用 "\\0" 替换空字符 ('\0')

我们可以在完成所有的测试函数后统一运行测试,也可以单个运行测试函数。现在,我们首

先来运行 SumTest()函数。先把光标定位在 SumTest()函数体内,在菜单栏里选择“测试”→“运

行”→“当前上下文中的测试”。也可以直接在右键菜单中选择“运行测试”,如图 5-17所示。还可以打开“测试”→“窗口”→“测试视图”,在其中选择需要执行的测试。

210

第 5章 软件测试

图 5-17 选择运行测试

测试完成后,测试结果窗口中会出现测试的结果信息,如图 5-18所示。

图 5-18 测试结果

也可以对所有函数进行测试,方法是选择“测试”→“运行”→“解决方案中的所有测试”,

就会对整个解决方案中的所有测试工程中的所有测试方法进行测试。测试结果如图 5-19所示。

图 5-19 全部测试结果

从测试结果中,我们可以看到 Divide函数没有通过测试。双击测试结果中的未通过的结果,显示未通过的详细信息,如图 5-20所示。

图 5-20 未通过测试的详细信息

从详细信息中了解到,测试方法执行过程中遇到了异常。下面通过调试测试方法来查看具体

的异常信息。在测试方法 DivideTest()中插入断点,如图 5-21所示。

211

软件工程——理论与实践

图 5-21 插入断点

选择“测试”→“调试”→“当前上下文中的测试”,然后逐步执行(默认情况下按快捷键

F10即可),如图 5-22所示。

图 5-22 逐步调试测试方法

当执行到如图 5-22中所示的代码行时,选择“调试”→“逐语句”(或者直接按快捷键 F11),进入到 Arithmetic.Divide函数中。继续按键 F11,跟踪函数的具体执行过程,发现函数在参数 b为 0时抛出异常,如图 5-23所示。分析得知,参数 b为 0,即函数 Divide没有通过测试的原因是测试方法中使用了 0作为除数。将测试方法中的 b改为其他非零值,即可看到测试全部通过,如图 5-24 所示。由此可以看出,测试是否通过,不仅与被测试函数本身有关,也与

选择的测试参数有关。在设计测试参数时,最

重要的一点就是全面性,比如如果 Divide 函数本身没有对参数 b是否为 0做出校验,而测试人员设计测试参数时又没有测试 0作为除数的例子,就不能发现 Divide函数中的这个逻辑漏洞。等到工程部署到实际应用时,就会在某一时刻出现致命的逻辑错误,严重的可能导致整个服务程序的崩溃。由此可以看出,测试人员在设

计测试用例时,是否能考虑周全关系到整个系统的最终质量。因为测试是系统交付给用户前的

最后一道防线(尤其是交付测试或β测试等最后环节),如果不能测试出来,那就会将有漏洞的

系统交付给最终用户。试想如果某银行使用的系统中存在这样一个错误,那么当错误被触发时,

造成的后果可能是灾难性的。虽然在软件系统中要求测出所有的漏洞是非常困难的,但必须尽

可能地测试出软件中所包含的漏洞,这也是评估测试设计人员水平高低的重要因素之一。关于

如何设计有效的用例,5.3节中已经给出了初步的介绍,更深入的学习测试技术请查阅专门讲解测试的书籍。

图 5-23 抛出异常

212

第 5章 软件测试

图 5-24 测试全部通过

5.9.2 使用 UnitTest 的自动化数据驱动测试

在 5.9.1小节中,初步介绍了 UnitTest做单元测试的方法:声明变量,调用被测试的函数,将返回值与期望值比较,断言是否符合特定关系(如相等);如果符合,则通过测试,否则测试失败。 测试方法每运行一次,需要一个测试用例。在实际工程中,通过一个测试用例来测试函数功能

显然是不充分的。比如,如果测试除法函数,至少就要两类测试用例,除数为 0和除数不为 0;更复杂一点,比如图书价格在 0~100元(不含)时打 9折,超过 100元打 8折,那么测试用例就必须覆盖 3个数域及 2个边界,可行的测试用例为−1、0、99、100、200,至少需要 5个测试用例。而执行每个测试用例都需要修改测试方法中的用例数据。如果依靠手工修改,效率就太低了。现代化

的测试工具可以根据自定义流程选择不同的用例,执行测试方法,并记录整个过程的测试结果。自定

义流程可以是从指定的数据库中按序或随机地读取事先录入的测试用例,然后在测试方法中运行。 自动化数据驱动测试就是通过程序自动地从测试用例库中读取用例并自动执行测试方法和记

录测试结果。在一些敏捷开发中(如极限编程)常常采用测试驱动开发的方法,即在正式编码之

前,先建立测试用例数据库和编写测试工程,然后再按照测试方法中定义的函数接口实现函数功

能,这样,在编码过程中,每完成一个函数,立即就能通过运行测试发现一些潜在的错误。通过

高质量的用例数据库,采用测试驱动开发,能够以较短的时间代价产生高质量的代码,这也正是

测试驱动开发近年来大行其道的原因。而测试驱动开发(test-driven development,TDD)所带来的好处远非这些,笔者强烈推荐大家去读一些专门介绍 TDD 的书籍,更建议在以后的开发过程中,无论工程大小,尽可能采用 TDD的方式,它带来的好处之多或许会让你惊讶。 对于用例数据库,有一些是许多项目都会使用的,比如登录的用户名和密码,是否符合长度、

中英文等规范。许多公司都有自己的测试用例数据库,甚至有一些设计良好的商业测试用例数据

库。采用这些成熟的数据库,不仅省去了一些编写测试用例数据库的时间,而且数据库的质量有

一定的保证。毕竟设计一个良好的测试用例数据库对公司来说也是一笔很大的人力资源开销,而

其质量常常还比不上久经实践验证的成熟数据库。 对于测试用例数据库的选择,如果用例量非常庞大,则采用速度快的数据库比较合适,如 SQL

Server、Oracle 等;如果对速度要求不高,而对通用性要求比较高(比如参与编写测试用例的工程师可能对数据库了解并不多),则采用 Excel格式比较合适(使用门槛低,而且大部分机器上都会安装)。 下面结合 SQL Server介绍 UnitTest的自动化数据驱动测试。 仍然采用前一小节中使用的工程,对 Sum函数进行自动化测试。首先打开 SQL Server建立

UnitTestDB数据库,并建立 SumTest表,表中数据如图 5-25所示。 然后,打开 TestProject1工程,打开“测试”→“窗口”→“测试视图”,在视图中选择 SumTest,

单击右键,打开属性,如图 5-26所示。

213

软件工程——理论与实践

图 5-25 Sum函数的测试用例数据表 图 5-26 测试方法属性

在属性视图中找到“数据连接字符串”,单击右侧的“…”按钮,打开“新建测试数据源向导”。选择“数据库”,单击“下一步”按钮,单击新建连接,显示“连接属性”视图。此时可以单击“更

改”按钮,在出现的“更改数据源”视图中选择各种数据类型,如图 5-27所示。选择“Microsoft SQL Server”类型。在服务器名处填写测试数据库服务器的机器名,然后选择登录方式和数据库,如图 5-28所示。也可以在“高级”中设置更详细的配置信息。然后单击“测试连接”按钮,如果数据库可用,则显示“测试连接成功”对话框。确定数据源设置,选择“下一步”→“完成”,即

可将数据库附加到测试工程的 SumTest中,如图 5-29所示。

图 5-27 更改数据源视图 图 5-28 连接属性视图

214

第 5章 软件测试

修改 SumTest方法,使其中的参数 a和参数 b以及期望值 expected为从数据库中自动读取得到的数据,如图 5-29 所示。其中的 TestContext 用于获取测试上下文的信息,包含从数据库中读取到的测试用例数据。由于 DataSource属性中 DataAccessMethod选择的是 Sequential,测试方法会自动从数据库中顺序地读取数据行,然后执行测试。

图 5-29 修改后的 SumTest函数

对 SumTest方法运行测试,结果及其详细信息如图 5-30所示。

图 5-30 测试结果

用例全部通过,如果有未通过的用例,只需双击即可查看未通过的原因。可以用相同方法对

其他函数进行测试。自动化数据驱动测试大大节约了测试人员的时间,如果测试工程设计得当,

完全可以实现无人值守的方式进行测试。测试工程师只需分析最终的运行结果,将由系统错误导

致的未通过测试反馈给开发者即可。数据驱动测试已经是现在工程项目开发中不可或缺的一部分。

随着软件工程理论和实践方法越来越成熟,出现了数十万甚至百万行代码级别的解决方案,它们

所含的工程代码量非常庞大,依靠测试人员手工填写测试用例几乎是不现实的,这时就更能体会

到自动化测试所带来的优势。

215

软件工程——理论与实践

在上面的测试中,我们使用了直接将数据库的连接通过属性的方式放在测试方法的方式。事实上,更通用的方式是使用以下 4个特性指定的函数。 (1)ClassInitialize。该特性指定的函数在运行类中第一个测试前先运行代码。比如可以将数

据库的配置信息放在 app.config中,将连接代码放在此处,将使测试工程更加灵活。 (2)ClassCleanup。该特性指定的函数在运行类中的所有测试后再运行代码。比如可以将释放

数据库连接资源的代码放在此处。 (3)MyTestInitialize。该特性指定的函数在运行类中每个测试前运行代码。比如可以在此处

添加测试方法执行日志代码,用于记录哪个测试方法以及执行的频率。 (4)MyTestCleanup。该特性指定的函数在运行完类中每个测试后运行代码。

5.10 其他单元测试工具

除了 Visual Studio 中集成的 UnitTest,还有许多应用于各种语言和平台的单元测试工具,例如 LoadRunner、GTest 等。最初的知名单元测试工具是 Kent Beck 在 SmallTalk 上实现的一个叫SUnit的单元测试框架。后来,这个框架被扩展到各个语言平台,例如(面向 Java语言的)JUnit、(面向 C++语言的)CPPUnit等。所有这些参考 SUnit和 JUnit设计实现的单元测试框架被统称为xUnit。如今 xUnit已经有针对 C#、C++、C、PHP、Perl、Ruby、Python、LISP、Lua、Objective-C、Javascript等语言的移植版本,形成了一个完善的测试体系。基于.NET平台的移植版本是 NUnit。由于 xUnit 的各类版本设计都很相似,本节只对 Nunit 作简单的介绍,大家可以从与上一节Microsoft UnitTest的对比中了解诸多测试框架的共性功能,以便以后能够更快速地学习使用其他测试工具。

NUnit目前的最新版本是 2.6,可以从 NUnit的官网下载(http://www.nunit.org),而且可以下载源代码,读者可以根据自己项目需要修改和重新编译 NUnit。由于 NUnit 界面设计非常简洁,我们采用官方英文原版进行介绍。 第一步,建立 NUnit 的测试工程,依然使用 5.9 节中建立的工程。打开解决方案,添加新项

目。经过 VS UnitTest的使用,我们已了解到单元测试工程不需要可执行的Main函数,那是否应该建立“类库”型项目呢?事实确实如此。选择“类库”型项目,命名为“NUnitTest”。

第二步,在新建的 NUnitTest 工程中,添加对项目 UnitTestInstance 的引用和对 NUnit的类库“nunit.framework.dll”的引用,后者可以在 NUnit的安装目录中的“bin\framework”文件夹下找到(如果使用官方的 NUnit 安装版,也可以在.NET 组件库中找到。如图 5-31所示。

图 5-31 添加引用

216

第 5章 软件测试

第三步,添加“NArithmeticTest”类。打开类文件,输入如图 5-32所示的代码。 第四步,编译 NUnitTest 工程,方法是选择“生

成”→“生成 NUnitTest”。打开“NUnit.exe”,添加新工程,命名为“NUProject.nunit”。然后,选择“Project”→

“Assembly”,将 NunitTest 工程“Debug”目录中的“NUnitTest.dll”添加进来。单击“Run”运行测试,结果如图 5-33所示。

NUnit 的基本使用演示完毕。读者可以发现,这和 Visual Studio 的 UnitTest使用一样方便,事实确实如此。但仔细分析图 5-32中的代码,发现 NUnit的一些特性关键字和 UnitTest 是不同的。不过,UnitTest中所含有的特性功能,基本都能在 NUnit中找到对应特性功能。表 5-8列出了部分 NUnit和 UnitTest 的对应特性关键字以及一些断言函数,更详细的区别请参考 NUnit的官方文档。

图 5-32 NArithmeticTest的代码

图 5-33 NUProject的运行结果

表 5-8 NUnit和 UnitTest的部分属性和断言函数对比

功 能 NUnit属性 UnitTest属性

标识测试类 TestFixture TestClass

标识测试方法 Test TestMethod

标识测试类初始化函数 TestFixtureSetup ClassInitialize

标识测试类释放资源函数 TestFixtureTearDown ClassCleanup

标识测试方法初始化函数 Setup TestInitialize

标识测试方法释放资源函数 TearDown TestCleanup

标识忽略该测试方法 Ignore Ignore

断言相等 Assert.AreEqual(object,object) Assert.AreEqual(object,object)

断言相同 Assert.AreSame(object,object) Assert.AreSame(object,object)

217

软件工程——理论与实践

5.11 利用Visual Studio中的工具进行界面测试

Visual Studio 2010 功能极其强大,在 5.9节中,我们学习了使用 UnitTest进行单元测试的过程。在测试工程的“添加新测试”模板窗口中,我们可以看到 Visual Studio 2010 还集成了很多其他类型的测试工具,比如编码的 UI测试(CodedUITest)、Web性能测试、负载测试、顺序测试等。 由于单元测试和界面测试是最基本的两种测试,本节介绍使用 Visual Studio 2010 中的

CodedUITest(编码的 UI 测试)进行界面测试。界面测试的工具还有很多,读者也可以课后练习使用其他的界面测试工具,如WinRunner、Visual Test、QARun等,本书不再作详细介绍。

5.11.1 CodedUITest 使用初步

界面测试属于系统测试,是黑盒测试的一种,是基于完全状态的软件系统进行的测试。在这

个过程中,测试工程师充当用户,完全模拟用户的操作,查看软件系统的功能是否正常。界面测

试的难度在于,如果需要完整测试软件系统,就需要设计一系列能够完全覆盖软件系统功能的测

试用例,然后测试人员逐一验证用例的运行,这个过程非常耗时,而且存在大量的重复工作。例

如,验证一个计算器程序的除法,就至少要设计和运行除数为 0和不为 0两种测试,而这两种测试,仅仅是输入不一样而已,其他的完全是重复动作。 界面测试技术就是为了解决这个耗时重复的过程,将测试人员从重复的动作中解脱出来,专

注于设计优良的测试用例。一般来说,自动化界面测试就是通过录制界面测试人员的操作,制成

脚本。然后通过自动回放记录脚本,就能完成一次自动测试,而无需测试人员再重复一次。尤其

是如果有多个测试用例,只需将测试脚本回放多次,在每次中自动使用不同用例,就能达到全部

测试,这是自动化数据驱动界面测试的内容,我们将在下一小节讲述。 由此可见,自动化界面测试不仅解放了界面测试人员,而且(由于使用了同一脚本)保证了

每次测试流程完全相同,避免了出现随意测试导致的测试结果不同。随意测试导致测试过程失去

价值,因为没有记录具体操作过程,一旦出现错误,开发人员无法回放测试人员的测试过程,也

就无法追踪错误。 笔者在公司做项目期间,就曾遇到过这个问题。起初,测试人员没有采用严格的自动化测试流程,

而是采用随意测试,结果导致出现错误后,有将近一半的错误竟然无法重现,导致反复测试,试

图重现当时的错误。而有一些错误,直至项目结束时,也没有再次重现,只好作为不可重现错误

提交到BUG库中,这直接导致了软件质量的下降。所以,笔者建议,无论是否使用自动化界面测

试工具,最基本的要写一个测试流程,然后严格按照流程执行;或者使用录屏工具,或记录鼠标

键盘动作的脚本工具,详细记录测试的过程。一旦出现错误,将能够根据脚本回放整个过程,这

样才能让开发人员轻易地还原到错误场景。 由于界面测试是针对有 UI界面的程序进行的,所以无法使用 5.9节中创建的工程。下面我们

首先创建一个简单的计算两个数和的界面程序。 打开 Visual Studio 2010,创建一个新的名为“Calculator”的“Windows 窗体应用程序”类型

项目,单击“确定”按钮。 将“Form1.cs”重命名为“Calculator.cs”。在“Calculator.cs”的设计视图中,右键单击“Form1”

218

第 5章 软件测试

窗体,打开属性对话框,将“Form1” 窗体的“Name”和“Text”属性重命名为“Calculator”。 然后在工具箱中拖出 3个“TextBox”控件,依次将“Name”属性重命名为“textBoxNum1”、

“textBoxNum2”、“textBoxSum”。再拖出一个“Button”控件,将名称重命名为“ButtonSum”,将“Text”属性重命名为“AddTwoNumbers”。最终界面如图 5-34 所示,其中最上面的两个 Textbox为“textBoxNum1”和“textBoxNum2”,下面的为“textBoxSum”。

图 5-34 Calculator项目界面设计

双击“AddTwoNumbers”按钮,在后台事件函数中输入如图 5-35所示代码。 选择击“生成”→“生成解决方案”。在 Calculator 项目的 “bin/Debug”目录下找到并运行

“Calculator.exe”应用程序,并输入数字 4、5进行加法测试,如图 5-36所示。

图 5-35 加法按钮的后台处理代码 图 5-36 程序执行界面

然后在解决方案中选择“添加”→“新建项目”,选择“测试”类型,命名为“CodedUITest”。在 CodedUITest项目中选择“添加”→“新建测试”→“编码的 UI测试”,命名为“CalculatorUITest”。在弹出的“为编码的 UI测试生成代码”中选择“录制操作、编辑 UI映射或添加断言”,单击“确定”按钮,显示 UI测试生成器,如图 5-37所示。 单击 UI 测试生成器中最左侧的红色“开始录制”按钮,开始录

制脚本。然后在计算器程序的 textBoxNum1 中输入数字 5,textBoxNum2 中输入数字 6,并单击“AddTwoNumbers”按钮。再单击最左侧的“暂停录制”按钮结束录制。再单击最右侧的“生成代码”按钮,在弹出的方法名窗口中填写名称

“AddTwoNumbers”,单击“添加并生成”完成自动生成测试代码。

图 5-37 UI测试生成器

注意,上述步骤必须在录制前打开计算器程序,否则,打开过程也将被录进脚本中。如果不

小心将多余步骤录进脚本,可以打开“UIMap.Designer.cs”文件,找到“AddTwoNumbers”方法,删除其中的多余步骤。最终的“AddTwoNumbers”方法应该如图 5-38所示。

219

软件工程——理论与实践

图 5-38 自动生成的测试脚本

在“CalculatorUITest.cs”中找到方法“CodedUITestMethod1”,其代码应该如图 5-39所示。

图 5-39 CodedUITestMethod 1方法

在“测试”→“窗口”→“测试视图”中右键单击“CodedUITestMethod1”,单击“运行选定内容”,运行测试脚本,如图 5-40所示。

图 5-40 运行测试脚本

220

第 5章 软件测试

然后就可以看到自动回放刚才录制的使用计算器过程。注意,运行测试前必须保证计算器程

序是打开的,因为我们录制的脚本中没有打开计算器程序的脚本语句。还可以在测试结果窗口中

看到测试的结果,如图 5-41所示。

图 5-41 测试脚本运行结果

以上就是界面测试录制和回放脚本的基本过程。由于上面的程序中没有 Assert(断言),所以,测试结果永远是成功的,除非发生应用程序异常,例如没有事先打开计算器程序。所以一个完整

的测试常常包含断言,例如验证计算器程序的 textBoxSum 中结果是否正确。由于添加断言需要添加的控件映射,我们将此内容放在下一小节“自动化数据驱动界面测试”中讲述。 录制和回放脚本的测试过程可以应用于任何具有用户界面(UI)的应用程序,比如浏览器,

录制脚本过程可以完整记录使用浏览器的过程,包括打开哪些页面,单击哪些超链接等,这常用

于 Web 项目的界面测试。 一个项目中可以添加多个测试类,一个测试类中可以添加多个测试方法,一个测试方法

中可以添加多个测试用例代码,但所有这些都只会生成一个 UIMap。如果一个项目包含过多的测试,会导致 UIMap 极度庞大,笔者建议如果项目中包含多个测试,可以放在多个测试项目中。

5.11.2 使用 CodedUITest 的自动化数据驱动界面测试

在上一小节中,我们学习了使用 CodedUITest 进行界面测试的方法,本节我们将学习从已经定义好的测试用例库中逐个读取用例进行自动化数据驱动界面测试的方法。 首先使用Microsoft Office 2010 Excel建立一个 csv格式的数据文档,命名为“testCase.csv”,

也可以使用数据库或 XML文档等,如果使用数据库,请参照 5.9.2节中的方法。csv数据文档的内容如图 5-42所示。

图 5-42 测试用例

测试数据一共 5条,其中第 1条是错误的测试用例。界面测试的最终结果取决于所有的用例测试结果。如果有用例测试失败,

则整个界面测试就失败。所以在最终的测试结果中,我们应该看

到 6条测试结果(5条独立用例测试结果和 1条界面测试结果),其中 4条成功,2条失败。 首先,在测试视图中,右键打开 CodedUITestMethod1 的属性,单击“数据连接字符串”右

侧按钮,在“新建测试数据源向导”中选择“CSV 文件”,单击“下一步”按钮。选择刚才新建的 testCase.csv 文件,如图 5-43 所示,单击“完成”按钮,在“将数据库文件复制到当前项目并作为部署项添加”中选择“是”。

刷新数据视图(每次修改后,都需要刷新)。现在的 CodedUITestMethod1 方法如图 5-44所示。

下面添加控件映射。在 CodedUITestMethod1 方法中右键选择“为编码的 UI 测试生成代码”→“使用编码的 UI测试生成器”,打开 UI测试生成器,如图 5-37所示。

221

软件工程——理论与实践

图 5-43 选择数据源

图 5-44 添加数据源后的测试方法

打开计算器程序,单击其中的 textBoxSum数据框,使其成为当前屏幕的激活输入区,同时按键“Win”(Win键就是键盘上靠近左侧 Ctrl键的带有Windows图标的键)和“I”,将计算器程序的 textBoxSum 控件添加到测试映射中。也可以将 UI测试生成器中的十字准星拖动到 textBoxSum 控件上来添加映射。也可用同样的方法添加 textboxNum1、textboxNum2和 buttonSum的控件映射,但由于上一节中我们使用这 3个控件录制过脚本,它们的控件映射已经生成了,此处不必重复生成。在添加 textBoxSum控件映射时,选择控件的“Text”属性(可以通过“添加断言”右侧的 4个箭头调整控件层次,直至找到 Text属性所在层次;可以通过这 4个箭头逐层遍历计算器程序的所有控件),单击“添加断言”,即可为 textBoxSum的 Text属性添加断言,如图 5-45所示。 在“添加断言”窗口中,选择“AreEqual”比较运算符,单击“确定”按钮,如图 5-46所示。 单击UI测试生成器中的生成代码(或通过快捷键“Alt+G”),将方法命名为“AssertAddTwoNumbers”,

单击“添加并生成”。刷新测试视图。 改写 CodedUITestMethod1方法的代码,使计算器程序中的输入数据取自数据源 testCase.csv。

修改后的代码如图 5-47所示。

222

第 5章 软件测试

图 5-45 为 textBoxSum添加断言 图 5-46 选择断言比较运算符

图 5-47 修改后的 CodedUITest Method1方法

其中第 29~32行代码将数据源中读取的 num1和 num2值绑定到计算器程序的两个输入控件值上。第 34行执行录制的测试脚本。第 36行将数据源中读取的 expected值绑定到计算器程序的结果控件值上,然后在 39行的断言中做实际值与期望值的比较断言。 在测试视图中运行该测试方法,测试结果如图 5-48所示。总共 6个测试,4个通过,和我们

预期的一致。

图 5-48 界面测试结果

双击测试结果,可以看到结果的详细信息,如图 5-49所示。 根据测试结果,很容易通过分析测试用例查看测试失败的原因。读者可以用类似的方法创建

更多的更复杂的界面测试,本书不再一一演示。 至此,自动化数据驱动的界面测试过程介绍完毕。界面测试的知识远不止这些,例如,界面

测试和单元测试一样,也支持附加测试特性,以便实现更复杂的测试过程等。更多和更深入的界

面测试知识,读者可以参考测试工具的官方文档。对于 Visual Studio 2010,微软的 MSDN 无疑是所有能找到的文档中最权威最全面的了,这是所有使用 Visual Studio 2010的工程师们最宝贵的资料,一定要深入学习。

223

软件工程——理论与实践

图 5-49 测试结果的详细信息

5.12 利用 Visual Studio 对网上书店系统的

用户登录模块进行单元测试

在前面小节中,我们学习了单元测试、界面测试的基本方法,本小节将介绍如何使用 Visual Studio 对网上书店系统的用户登录模块进行单元测试。其他模块的单元测试以及界面测试等,读者可以依据本小节介绍的内容方法做对应练习。 在 Visual Studio 2010中打开网上书店项目,选择“测试”→“新建测试”。在“添加新测试”

窗口中选择创建“单元测试”,并选择“创建新的 Visual C#测试项目”,单击“确定”按钮。新建的测试项目命名为“TestProject_Login”,如图 5-50所示。

图 5-50 创建登录模块单元测试项目

224

第 5章 软件测试

创建完毕,定位到“Login.aspx.cs”中的“UserLogin”函数,右键选择“创建单元测试”。在“创建单元测试”窗口中,展开网上书店项目“BookShoponWeb”,展开“BookShoponWeb.Login”,可以看到“Login.aspx”后台的函数列表,如图 5-51所示。

图 5-51 创建登录模块单元测试类

“Login”后台包含 3 个函数,其中“Login”为构造函数,“Page_Load”为页面载入函数,“UserLogin”为用户验证函数。在学习 UnitTest 基础知识时我们知道,由于单元测试是封装了的函数级黑盒测试,需要函数具

有返回值,所以只有“UserLogin”函数需要进行单元测试。勾选“UserLogin”的复选框,单击“确定”按钮。“TestProject_Login”工程如图 5-52所示。 创建成功后,打开“TestProject_Login”测试工程中的

“LoginTest.cs”测试类。定位到测试类中包含的用户登录测试“UserLoginTest”方法。由于测试“Login.aspx”页面,需要修改方法特性“[UrlToTest]”地址为“Login.aspx”页面的 Url。如果不在 ASP.NET Development Server中进行测试,还要删除特性“[AspNetDevelopmentServerHost]”。在 IIS等其他 Web 服务器中进行单元测试需要先附加到Web服务器进程中,具体的 Web 服务器进程名称因生产厂商和版本而不同。 此处使用ASP.NET Development Server进行单元测试,因此

只需修改特性“[UrlToTest]”即可。给“userName”和“password”赋予测试账号和测试密码(例如“admin”),注释掉最后的“Assert.Inconclusive”语句。

图 5-52 TestProject_Login工程

最终的修改代码如下: [TestMethod()] [HostType("ASP.NET")] [AspNetDevelopmentServerHost("D:\\VSProjects\\BookShoponWeb\\BookShoponWeb", "/")] [UrlToTest("http://localhost:7337/Login.aspx")] public void UserLoginTest() {

Login target = new Login(); // TODO: 初始化为适当的值

string userName = "admin"; // TODO: 初始化为适当的值

225

软件工程——理论与实践

string password = "admin"; // TODO: 初始化为适当的值

bool expected = true; // TODO: 初始化为适当的值

bool actual; actual = target.UserLogin(userName, password); Assert.AreEqual(expected, actual);

//Assert.Inconclusive("验证此测试方法的正确性。");

}

启动 ASP.NET Development Server,在“UserLoginTest”函数处右键选择“运行测试”,在测试结果窗口中查看测试运行结果,如图 5-53所示。

图 5-53 用户登录模块测试结果

登录模块用户验证函数的单元测试完成。读者可以用类似的方法对其他模块和其他函数进行

单元测试以及界面测试等。

5.13 测试分析报告编写指南

下面的测试分析报告模板(可裁剪)可作为参考。 1 概述 1.1 项目简介

在本章节中简要介绍项目的基本情况。 1.2 术语定义

列出本文件中用到的专业术语的定义和外文首字母编写词的原词组。 1.3 参考资料

列出要用到的参考资料,如: 本项目的经核准的计划任务书或合同、上级机关的批文; 属于本项目的其他已发表的文件; 本文件中各处引用的文件、资料,包括所要用到的软件开发标准。

列出这些文件的标题、文件编号、发表日期和出版单位,说明能够得到这些文件资料的来源。 1.4 版本更新信息

版本更新记录格式见表 1。

表 1 版本更新记录

版 本 号 创 建 者 创 建 日 期 维 护 者 维 护 日 期 维 护 纪 要

V1.0 王林 2009/02/18 — — —

V1.0.1 — — 张浩 2009/02/26 不符合项测试

226

第 5章 软件测试

227

2 目标系统功能需求

需求规格说明书中对功能需求的描述。 3 目标系统性能需求

需求规格说明书中对性能需求的描述。 4 目标系统接口需求

需求规格说明书中对接口需求的描述。 5 功能测试报告

搭建功能测试平台,使测试平台与运行平台一致。按照功能需求内容设计测试用例(输

入/输出内容),进行现场测试,记录测试数据,评定测试结果。测试活动的记录格式可参

考表 2。

表 2 功能测试记录

编号 功能名称 功能描述 用例输入内容 用例输出内容 发现问题 测试结果 测试时间 测试人

1 √

2 √

3 √

4 ×

6 性能测试报告

搭建性能测试平台,使测试平台与运行平台一致。按照性能需求内容设计测试用例(输入/输出内容),进行现场测试,记录测试数据,评定测试结果。测试活动的记录见表 3。

表 3 性能测试记录

编号 性能名称 性能描述 用例输入内容 用例输出内容 发现问题 测试结果 测试时间 测试人

1 √

2 √

3 ×

4 √

7 接口测试报告 搭建接口测试平台,使测试平台与运行平台一致。按照接口列表内容,设计测试用例(输

入/输出内容),进行现场测试,记录测试数据,评定测试结果。测试活动的记录见表 4。

表 4 接口测试记录

编号 接口名称 入口参数 出口参数 传输频率 发现问题 测试结果 测试时间 测试人

1 ×

2 √

3 √

8 不符合项列表 将测试中的所有不符合项,整理后分别记录到表 5、表 6 和表 7 的表格中。

软件工程——理论与实践

表 5 功能测试不符合项列表

编号 功能名称 功能描述 用例输入内容 用例输出内容 发现问题 测试结果 测试时间 测试人

1 ×

2 ×

3 ×

4 ×

表 6 性能测试不符合项列表

编号 性能名称 性能描述 用例输入内容 用例输出内容 发现问题 测试结果 测试时间 测试人

1 ×

2 ×

3 ×

4 ×

表 7 接口测试不符合项列表

编号 接口名称 入口参数 出口参数 传输频率 发现问题 测试结果 测试时间 测试人

1 ×

2 ×

3 × 以上不符合项,限期××天内改正。改正完毕后重新进行回归测试。

9 测试结论 测试完成之后,测试小组应对本次测试做出结论,格式如下。 测试日期: 测试地点: 测试环境: 参与测试的人员: 列出系统的强项: 列出系统的弱项: 列出不符合项的统计结果: 测试组组长签字: 测试组组员签字:

5.14 网上书店系统的测试分析报告

1 概述 1.1 项目简介

通过网上书店系统实现图书销售的电子商务模式并满足经销商和用户进行电子交易的需

求,保证充分发挥网上交易的优势。 1.2 术语定义

无。

228

第 5章 软件测试

1.3 参考资料

测试分析报告编写参考指南。 1.4 版本更新信息

版本更新信息见表 1。

表 1 版本更新信息

版本号 创建者 创建日期 维护者 维护日期 维护纪要

V1.0 陈捷 2008-10-17 陈捷

2 目标系统功能需求

参见网上书店系统的需求规格说明书。 3 目标系统性能需求

参见网上书店系统的需求规格说明书。 4 目标系统接口需求

参见网上书店系统的需求规格说明书。 5 功能测试报告

功能测试报告见表 2。

表 2 功能测试记录

编号 功能 名称

功能描述 输入

内容

输出 内容

发现

问题

测试 结果

测试 时间

测试

101 用户 注册

用例编号:101 用例名称:用户注册 前置条件:游客申请注册 后置条件:游客注册成功成为会员

活动步骤: (1)游客选择注册。 (2)系统返回一个注册页面。 (3)游客根据提示输入相应的注册信息。

(4)系统验证游客输入成功。 (5)游客提交注册信息。 (6)系统提示注册成功并返回首页。(默认已登录。)

扩展点:无 异常处理: (1)游客输入信息和系统验证不一致(如字段长度超过系统设置等),系统给出相

应的提示信息并返回注册页面。 (2)游客输入用户名是已注册用户名,系统给出提示并返回注册页面。

(3)系统异常,无法注册,并给出相应信息(如网站维护等)。

用户

注册

信息

(1)用户注册成功 (2)该账号是 已 注 册

账号 (3)验证码不一致 (4)网站维护,无法注

无 √ 2008-12-20 陈捷

229

软件工程——理论与实践

续表

编号 功能 名称

功能描述 输入

内容

输出 内容

发现

问题

测试 结果

测试 时间

测试

102 会员 登录

用例编号:102

用例名称:会员登录

前置条件:该会员必须是本网站已注

册的成员

后置条件:该会员登录成功

活动步骤:

(1)该会员选择登录。

(2)系统返回一个登录页面。

(3)会员输入用户名、密码和验证码并提交。

(4)系统进行系统验证,验证成功,记录该用户为登录用户并返回主页

面。(表明该会员已登录。)

扩展点:无

异常处理:

(1)用户忘记密码,选择“找回密码”功能,进入找回密码用例。

(2)系统验证用户登录信息有错,提示用户重新登录。

(3)系统处理异常,系统给出相应的提示信息。

用户

登录

信息

(1)会员登录成功

(2)登录信息有误

无 √ 2008-12-20 陈捷

103 找回

密码 用例编号:103

用例名称:找回密码

前置条件:用户必须是本系统的成功

注册用户

后置条件:系统返回设置密码的页面

让用户重新设置密码

活动步骤:

(1)会员选择“找回密码”。

(2)系统返回一个密码找回页面。(要求用户输入注册时的邮箱号,系统自

动发送邮件到用户的邮箱中,用户再

根据邮箱中设置的链接重新设置密

码。)

(3)用户输入新的密码并提交。

(4)系统进行验证,验证成功,提示修改成功并自动跳转至登录页面。

扩展点:

(1)与活动步骤中的步骤 1相同。

(2)系统返回一个密码找回页面。(要求用户输入用户名,并根据密码提示

问题让用户输入密码提示答案。)

密码

提示

答案

(1)密码重新设置页面

(2)验证错误

无 √ 2008-12-20 陈捷

230

第 5章 软件测试

续表

编号 功能 名称

功能描述 输入

内容

输出 内容

发现

问题

测试 结果

测试 时间

测试

103 找回 密码

(3)用户输入用户名和密码提示问题并提交。

(4)系统进行验证,验证成功,并返回密码重新设置页面。

(5)用户输入新的密码并提交。

(6)与活动步骤中的(4)相同。

异常处理:

(1)在扩展点中,若用户输入错误的用户名或密码提示答案,则系统提示

验证错误并返回登录页面。

(2)系统处理异常,系统给出相应的提示信息。

密码

提示

答案

无 √ 2008-12-20 陈捷

104 修改

个人

信息

用例编号:104

用例名称:修改个人信息

前置条件:该用户必须是该系统成功注

册并且已成功登录的用户

后置条件:该用户修改个人信息成功

活动步骤:

(1)会员选择“修改信息”。

(2)系统返回一个信息修改页面。

(3)会员修改相关信息并提交。

(4)系统进行系统验证,验证成功,提示修改成功。

扩展点:无

异常处理:

(1)系统验证会员输入有误,提示重新输入并返回“修改信息”页面。

(2)系统处理异常,系统给出相应的提示信息。

修改

过的

个人

信息

(1)修改成功

(2)会员输入有误

无 √ 2008-12-21 陈捷

105 用户 注销

用例编号:105

用例名称:用户注销

前置条件:该用户必须是该系统成功

注册并且已成功登录的用户

后置条件:用户成功注销

活动步骤:

(1)会员选择“注销”。

(2)系统提示用户成功注销并返回网站首页。

扩展点:无

异常处理:系统异常,并给出相应的

提示信息

确认

注销

注销成功 无 √ 2008-12-21 陈捷

231

软件工程——理论与实践

续表

编号 功能 名称

功能描述 输入

内容

输出 内容

发现

问题

测试 结果

测试 时间

测试

201 浏览

图书

目录

用例编号:201

用例名称:浏览图书目录

前置条件:用户在本系统中选择了

“浏览图书目录”项

后置条件:用户成功浏览图书目录

活动步骤:

(1)用户选择浏览图书目录或者输入查看的图书信息。

(2)系统处理用户请求成功并返回用户查看的相应的图书目录页面。

扩展点:无

异常处理:系统在数据库中没有找到

与用户输入相关的信息,系统返回提

示信息

查看

的图

书信

(1)相应的图书目录页面

(2)没有找到相关信息

无 √ 2008-12-21 陈捷

202 浏览

图书 用例编号:202

用例名称:浏览图书

前置条件:用户必须在浏览商品目录

时查看某个商品的详细信息

后置条件:用户查看图书

活动步骤:

(1)用户选择查看图书的详细信息。

(2)系统返回图书的详细信息。

扩展点:无

异常处理:该书暂时无详细信息,系

统给出相应的提示

点击

查看

详细

信息

(1)图书详细信息

(2)提示暂无详细信息

无 √ 2008-12-21 陈捷

301 添加 图书

用例编号:301

用例名称:添加图书

前置条件:用户必须是已注册并已登

录的会员

后置条件:用户添加图书成功

活动步骤:

(1)用户在看中的图书中选择添加图书。

(2)系统返回添加成功,并弹出结账还是继续购物的提示窗口。

(3)用户选择结账。

(4)系统返回购物车页面。

选择

加图

(1)添加成功,返回购物车页

(2)用户未登录,返 回登录页面

无 √ 2008-12-21 陈捷

232

第 5章 软件测试

续表

编号 功能 名称

功能描述 输入

内容

输出 内容

发现

问题

测试 结果

测试 时间

测试

扩展点:用户选择继续购物,系统

返回购买图书的页面。 异常处理: (1)用户未登录,返回登录页面。(2)系统异常,系统给出相应的提示信息。

302 查看购

物车 用例编号:302 用例名称:查看购物车 前置条件: (1)用户选择“查看购物车”项。(2)系统返回购物车页面。 后置条件:用户打开购物车页面 活动步骤: (1)用户选择“查看购物车”。 (2)系统返回购物车页面。 扩展点:无 异常处理: (1)该用户不是会员,系统给出提示,要求此用户先登录,并返回登

录页面。 (2)系统给出一个提示:该购物车内没有图书。 (3)系统异常,系统给出相应的提示信息。

选择

查看

购物

(1)返回购物车页面 (2)该购物车内没有图书 (3)该用户不是会员,返回

登录页面

无 √ 2008-12-21 陈捷

303 删除 图书

用例编号:303 用例名称:删除图书 前置条件: (1)该用户是已登录的会员。 (2)购物车中含有图书。 (3)在购物车管理页面中选择删除图书。 后置条件:相应的图书被删除 活动步骤: (1)会员选择购物车管理,选中相应的图书,点击删除图书。 (2)系统提示会员删除成功并返回购物车页面。 扩展点:无 异常处理:系统异常,系统给出相

应的提示信息

选择

删除

图书

删除成功 无 √ 2008-12-21 陈捷

304 修改图

书数量 用例编号:304 用例名称:修改图书数量 前置条件:

修改

后的

数量

修改成功 无 √ 2008-12-21 陈捷

233

软件工程——理论与实践

续表

编号 功能

名称 功能描述

输入

内容

输出 内容

发现

问题

测试 结果

测试 时间

测试

(1)用户是已登录的会员。 (2)购物车内不能为空。 后置条件:购物车内相应图书的数量

被成功修改 活动步骤: (1)用户选择购物车并对相关图书的数量做出修改。 (2)系统返回确认修改信息。 (3)用户选择确认。 (4)系统提示修改成功并返回购物车。扩展点:无 异常处理: (1)用户修改的图书数量没有改变,提示无更改并返回购物车页面。 (2)用户取消修改。 (3)系统异常,系统给出相应的提示信息。

305 清空购

物车 用例编号:305 用例名称:清空购物车 前置条件: (1)该用户为已登录的用户。 (2)购物车内不能为空。 后置条件:购物车被成功清空 活动步骤: (1)用户选择购物车管理并点击清空购物车。 (2)系统提示购物车已清空并返回购物车页面。 扩展点:无 异常处理: (1)购物车为空,系统给出相应的提示信息。 (2)系统异常,系统给出相应的提示信息。

点击

清空

购物

清空成功 无 √ 2008-12-23 陈捷

401 提交 订单

用例编号:401 用例名称:提交订单 前置条件: (1)该用户为已成功登录的会员。(2)会员购物车内不能为空。 后置条件:会员提交订单成功 活动步骤: (1)会员确认购买并提交。

确认

购买

提交

(1)返回确认信息页面 (2)购物车为空,不能支付

(3)确认信息填写失败

无 √ 2008-12-23 陈捷

234

第 5章 软件测试

续表

编号 功能 名称

功能描述 输入

内容

输出 内容

发现

问题

测试

结果

测试 时间

测试 人

(2)系统返回确认信息页面(如收货人信息、送货方式、信用卡号、密码

是否开发票和备注说明等)。

(3)会员填写并提交。

(4)系统处理支付并提示结账成功然后给出购买信息。

扩展点:无

异常处理:

(1)购物车为空,系统给出相应的提示。

(2)信用系统处理支付失败,系统给出相应的提示。

(3)系统处理异常,系统给出相应的提示。

402 查看所

有订单 用例编号:402

用例名称:查看所有订单

前置条件:

(1)该用户为已成功登录的会员。

(2)该会员在该系统中下过订单。

后置条件:会员查看所有订单成功

活动步骤:

(1)会员单击“查看订单”项。

(2)系统返回订单目录页面。

扩展点:无

异常处理:

(1)系统提示无订单。

(2)系统处理异常,系统给出相应的提示。

点击

查看

订单

返回订单目

录页面 无 √ 2008-12-23 陈捷

403 查看单

个订单

信息

用例编号:403

用例名称:查看单个订单信息

前置条件:

(1)该用户为已成功登录的会员。

(2)会员拥有该订单。

后置条件:会员查看该订单成功

活动步骤:

(1)会员点击相应的订单。

(2)系统返回该订单的详细信息。

扩展点:无

异常处理:系统处理异常,系统给出

相应的提示

点击

相应

订单

返回相应的

详细信息 无 √ 2008-12-23 陈捷

235

软件工程——理论与实践

续表

编号 功能 名称

功能描述 输入

内容

输出 内容

发现

问题

测试 结果

测试 时间

测试

404 取消 订单

用例编号:404

用例名称:取消订单

前置条件:

(1)该用户为已成功登录的会员。

(2)会员拥有该订单。

后置条件:会员取消该订单成功

活动步骤:

(1)会员点击取消订单。

(2)系统返回确认取消提示。

(3)会员确认取消。

(4)系统提示已经取消该订单并返回订单目录页面。

扩展点:无

异常处理:

(1)该订单取消的时间已过,会员不能够取消该订单。

(2)系统处理异常,系统给出相应提示。

点击

取消

订单

(1)取消

成功

(2)取消时间已过,不

能取消

无 √ 2008-12-23 陈捷

501 查询 图书

用例编号:501

用例名称:查询图书

前置条件:该用户必须是已登录的管

理员且拥有此权限

后置条件:管理员查询图书信息成功

活动步骤:

(1)管理员选择“查看图书”选项。

(2)系统处理,返回相应图书页面(如图书名称、图书作者、图书价格、图

书出版社、入库时间和图书库存等数

据库中具有的相应信息)。

扩展点:无

异常处理:

(1)系统提示暂无此图书。

(2)系统提示查询异常,并给出相应的信息。

点击

查询

图书

返回相应的

图书页面 无 √ 2008-12-24 张航

502 添加 图书

用例编号:502

用例名称:添加图书

前置条件:

(1)该用户必须是已登录的管理员且拥有此权限。

图书

信息

(1)添加 成功

(2)已存在该图书信息

无 √ 2008-12-24 张航

236

第 5章 软件测试

续表

编号 功能 名称

功能描述 输入

内容

输出 内容

发现

问题

测试

结果

测试 时间

测试

(2)数据库中无此图书信息。

后置条件:管理员添加此图书信息

成功

活动步骤:

(1)管理员提交添加图书信息(如图书名称、图书作者、图书价格、图书

出版社、入库时间和图书库存等数据

库中具有的相应信息)。

(2)系统处理并提示添加图书信息成功。

扩展点:无

异常处理:

(1)添加失败,数据库中已存在该图书信息。

(2)系统处理异常,系统给出相应的提示信息。

503 删除 图书

用例编号:503

用例名称:删除图书

前置条件:

(1)该用户必须是已登录的管理员且拥有此权限。

(2)数据库中有此图书的相应信息。

后置条件:管理员删除相应图书信息

成功

活动步骤:

(1)管理员提交要删除的图书名称或ISBN等有关图书的关键信息。

(2)系统处理请求并提示删除成功。

扩展点:

(1)管理员选中要删除的图书并单击“删除”按钮。

(2)系统处理请求并提示删除成功。

异常处理:

(1)系统返回删除失败,数据库中已无此图书信息。

(2)系统处理异常,系统给出相应的提示信息。

相关

图书

信息

删除 成功

无 √ 2008-12-24 张航

504 修改 图书

用例编号:504

用例名称:修改图书

前置条件:

修改

过的

图书

信息

修改成功 无 √ 2008-12-24 张航

237

软件工程——理论与实践

续表

编号 功能 名称

功能描述 输入

内容

输出 内容

发现

问题

测试 结果

测试 时间

测试

(1)该用户必须是已登录的管理员且拥有此权限。

(2)数据库中有此图书的相应信息。

后置条件:管理员修改相应图书信

息成功

活动步骤:

(1)管理员提交修改图书信息(图书信息包括图书名称、图书作者、

图书价格、图书出版社、入库时间

和图书库存等数据库中具有的相应

信息)。

(2)系统处理请求并提示修改成功。

扩展点:无

异常处理:系统返回修改失败,相

应的图书信息没有修改

505 会员 查询

用例编号:505

用例名称:会员查询

前置条件:

(1)该用户必须是已登录的管理员且拥有此权限。

(2)数据库中已注册有该会员信息。

后置条件:管理员查询到该会员

信息

活动步骤:

(1)管理员选择“查询会员”项,并输入相关会员的关键信息(如会

员用户名、系统内部编号)。

(2)系统处理请求,返回查询结果页面(查询结果包括会员用户名和

会员名称等)。

扩展点:无

异常处理:

(1)数据库中无相应的会员信息,系统提示查询失败。

(2)系统处理异常,系统给出相应的提示信息。

会员

相关

信息

(1)查询 成功

(2)查询失败,没有此

会员

无 √ 2008-12-24 张航

506 订单 查询

用例编号:506

用例名称:订单查询

前置条件:

(1)该用户必须是已登录的管理员且拥有此权限。

(2)数据库中有相应的订单信息。

相应

订单

信息

(1)相应的订单页面

(2)没有相应的订单

无 √ 2008-12-24 张航

238

第 5章 软件测试

续表

编号 功能 名称

功能描述 输入

内容

输出 内容

发现

问题

测试

结果

测试 时间

测试

后置条件:相应的订单查询成功

活动步骤:

(1)管理员选择“订单查询”项,并输入相关订单的关键信息(如订单

号),根据某会员信息查询其订单。

(2)系统处理,返回相应的查询订单结果页面。

扩展点:无

异常处理:

(1)没有相应的订单。

(2)系统处理异常,系统给出相应的提示信息。

507 订单

删除 用例编号:507

用例名称:订单删除

前置条件:

(1)该用户必须是已登录的管理员且拥有此权限。

(2)数据库中有相应的订单信息。

后置条件:相应的订单删除成功

活动步骤:

(1)管理员选择“订单删除”项,并输入相关订单的关键信息(如订单

号),根据某会员信息查询其订单。

(2)系统处理,提示订单删除成功。

扩展点:无

异常处理:

(1)系统提示没有相应的订单或相应的订单已经被删除。

(2)系统处理异常,系统给出相应的提示信息。

点击

删除

订单

删除成功 无 √ 2008-12-24 张航

508 添加

新折

用例编号:508

用例名称:添加新折扣

前置条件:

(1)该用户必须是已登录的管理员且拥有此权限。

(2)数据库中有相应的图书信息。

后置条件:相应的图书添加新折扣成

活动步骤:

(1)管理员选择“添加折扣”项。

新折

扣信

(1)添加成功

(2)信息错误,添加失

无 √ 2008-12-24 张航

239

软件工程——理论与实践

续表

编号 功能 名称

功能描述 输入

内容

输出 内容

发现

问题

测试 结果

测试 时间

测试 人

(2)系统显示添加折扣页面。

(3)管理员填写并提交折扣信息(包括折扣类别名、打折原因、折扣价

格以及对应图书等关键信息)。

(4)系统处理,提示添加成功。

扩展点:无

异常处理:

(1)添加新折扣信息失败,系统给出相应的提示。

(2)信息填写失败,系统返回错误页面。

(3)系统处理异常,系统给出相应的提示信息。

6 性能测试报告

多个用户可以并发访问网站,不会造成冲突。 7 接口测试报告

无。 8 不符合项列表

无。 9 测试结论

测试完成日期:2008-12-24 测试地点:图书馆 测试环境:普通家用环境 参与测试的人员:陈捷,张航 系统的强项:可靠性强 系统的弱项:功能划分不是很清晰 不符合项的统计结果:无 测试组组长签字:陈捷 测试组组员签字:张航

小 结

本章主要讨论与软件测试相关的内容。软件测试的目的是发现软件产品中存在的软件缺陷,

进而保证软件产品的质量。可以说,目前保证软件产品质量,提高软件产品的可靠性的最主要方

法仍然是软件测试。

240

第 5章 软件测试

通过本章的学习,读者应该熟悉软件测试的原则:完全测试是不可能的;测试中存在着风险;

软件测试只能表明缺陷的存在,而不能证明产品已经没有缺陷;软件产品中潜在的错误数与已发

现的错误数成正比;让不同的测试人员参与到测试工作中;让开发小组和测试小组分立,开发工

作和测试工作不能由同一部分人来完成;尽早并不断地进行测试,使测试工作贯穿于整个软件开

发的过程中;在设计测试用例时,应包括输入数据和预期的输出结果两个部分,并且,输入数据

不仅应该包括合法的情况,还应该包括非法的输入情况;要集中测试容易出错或错误较多的模块;

应该长期保留所有的测试用例。 此外,读者还应该了解软件测试的模型。常用的软件测试模型有 V模型、W模型和 H模型。

每种模型都有各自的优缺点。V模型的价值在于非常明确地标明了测试过程中存在的不同级别,并且清楚地描述了这些测试阶段和开发过程各阶段的对应关系。在 V模型的基础上,增加开发阶段的同步测试,就是 W 模型。在 H 模型中,软件测试过程的活动完全独立,贯穿于整个软件产品的生命周期,与其他流程并行进行。 软件测试可以从不同的角度划分为多种类型。按照时间阶段,软件测试可以划分为单元测试、

集成测试、系统测试和验收测试。按照执行测试时是否需要运行程序,软件测试可以划分为静态

测试和动态测试。按照测试时是否查看源代码,软件测试还可以分为黑盒测试和白盒测试。按照

软件的质量因素,软件测试可以分为功能测试、可靠性测试、可用性测试、性能测试和安全性测

试,实际上,为了保证软件产品的质量,软件的方方面面都应该被测试到,但是由于穷尽测试是

无法实现的,在实际的软件项目中,测试工作应该有所取舍。 软件测试有多种方法。从用例设计的角度可以把软件测试分为黑盒测试和白盒测试。黑盒测

试指的是把被测试的软件系统看作是一个黑盒子,不需要关心盒子的内部结构,只关注软件产品

的输入数据和输出结果。白盒测试关注软件产品的内部细节和逻辑结构,研究源代码和程序结构。

等价类划分是一种重要的黑盒测试技术,逻辑覆盖是一种重要的白盒测试技术。这两种方法分别

适用于不同的场合。 本章详细介绍了单元测试、集成测试和系统测试的内容以及一些可行的操作方法和操作策略,

并针对系统测试,介绍了 4种比较基础的测试类型。 本章还介绍了利用 Visual Studio 中的工具进行单元测试、其他单元测试工具、利用 Visual

Studio中的工具进行界面测试、利用 Visual Studio对网上书店系统的用户登录模块进行单元测试、测试分析报告编写指南以及网上书店系统的测试分析报告。

习 题

1.简述静态测试和动态测试的区别。 2.现有一段判定三角形类型的程序,可以根据输入的三角形的三边长来判定可构成的三角形

是否为等腰三角形。请用等价类划分法来为此段代码设计测试用例。 3.为什么软件开发人员不能同时完成测试工作? 4.软件测试的常用模型有哪些?请简述它们的优缺点。 5.已知有如下一段代码: int a, b, c; if (a < 1 and b > 0)

241

软件工程——理论与实践

c = 5; else if ( b < -3) c = 4; else c = 3;

请画出这段代码的程序流程图,并分别采用语句覆盖、分支覆盖、条件覆盖、分支—条件覆盖、

条件组合覆盖和路径覆盖的方法设计测试用例。

242

第6章 软件工程的其他相关内容 本章目标 ● 熟悉软件维护的基本概念。 ● 掌握软件维护的工作过程。 ● 了解软件维护的分类。 ● 了解软件的可维护性以及提高软件可维护性的措施。 ● 了解软件维护的副作用以及避免软件维护副作用的措施。 ● 掌握 ISO Standard 9126 定义的软件质量的 6 个特性。 ● 熟悉 McCall 的软件质量特性模型。 ● 掌握软件质量保证的措施。 ● 了解软件配置管理的相关概念。 ● 了解软件估算的相关内容。 ● 熟悉软件过程能力成熟度模型。 ● 了解软件过程能力成熟度模型的 5个成熟度等级。 ● 了解软件项目管理的相关内容。 ● 熟悉软件工程文档的分类。 ● 了解合格的软件工程文档的特性。 ● 熟悉Microsoft Project的使用方法。 ● 熟悉利用Microsoft Project管理开发过程。

6.1 软 件 维 护

软件维护是软件产品生命周期的最后一个阶段。在产品交付并且投入使用之后,为了解决在

使用过程中不断发现的各种问题,保证系统正常运行,同时使系统功能随着用户需求的更新而不

断升级,软件维护的工作是非常必要的。概括地说,软件维护就是指在软件产品交付给用户之后,

为了改正软件测试阶段未发现的缺陷,改进软件产品的性能,补充软件产品的新功能等所进行的

修改软件的过程。 进行软件维护通常需要软件维护人员与用户建立一种工作关系,使软件维护人员能够充分了

解用户的需要,及时解决系统中存在的问题。通常,软件维护是软件生命周期中延续时间最长、

工作量最大的阶段。据统计,软件开发机构 60%以上的精力都用在维护已有的软件产品上了。对

243

软件工程——理论与实践

于大型的软件系统,一般开发周期是 1~3 年,而维护周期会高达 5~10 年,维护费用甚至会高达开发费用的 4~5倍。

维护开支通常占软件成本的 40%~80%(平均为 60%)。因此,维护可能是软件生命周期中

最重要的阶段。 ——Robert L. Glass

软件维护不仅工作量大、任务重,而且如果维护得不恰当,还会产生副作用,引入新的软件

缺陷。因此,进行维护工作要相当谨慎。

6.1.1 软件维护的过程

可以把软件维护过程看成是一个简化或修改了的软件开发过程。为了提高软件维护工作的效

率和质量,降低维护成本,同时使软件维护过程工程化、标准化、科学化,在软件维护的过程中

需要采用软件工程的原理、方法和技术。 典型的软件维护的过程可以概括为:建立维护机构,用户提出维护申请并提交维护申请报告,

维护人员确认维护类型并实施相应的维护工作,整理维护记录并对维护工作进行评审,对维护工

作进行评价。 1.建立维护机构

对于大型的软件开发公司,建立独立的维护机构是非常必要的。维护机构中要有维护管理员、

系统监督员、配置管理员和具体的维护人员。对于一般的软件开发公司,虽然不需要专门建立一

个维护机构,但是设立一个产品维护小组是必需的。 2.用户提出维护申请并提交维护申请报告

当用户发现问题并需要解决时,首先应该向维护机构提交一份维护申请报告。申请报告中需

要详细记录软件产品在使用过程中出现的问题,比如数据输入、系统反应、错误描述等。维护申

请报告是维护人员研究问题和解决问题的基础,因此它的正确性、完整性是后续维护工作的关键。 3.维护人员确认维护类型并实施相应的维护工作

软件维护有多种类型,对不同类型的维护工作所采取的具体措施也有所不同。维护人员根据

用户提交的申请报告,对维护工作进行类型划分,并确定每项维护工作的优先级,从而确定多项

维护工作的顺序。 在实施维护的过程中,需要完成多项技术性的工作,比如: (1)对软件开发过程中相关文档进行更新; (2)对源代码进行检查和修改; (3)单元测试; (4)集成测试; (5)软件配置评审等。 4.整理维护记录并对维护工作进行评审

为了方便后续的维护评价工作以及对软件产品运行状况的评估,需要对维护工作进行简单的

记录。与维护工作相关的数据量非常庞大,需要记录的数据一般有: (1)程序标识; (2)使用的程序设计语言以及源程序中语句的数目; (3)机器指令的条数;

244

第 6章 软件工程的其他相关内容

(4)程序交付的日期和程序安装的日期; (5)程序安装后的运行次数; (6)程序安装后运行时发生故障导致运行失败的次数; (7)进行程序修改的次数、修改内容及日期; (8)修改程序而增加的源代码数目; (9)修改程序而删除的源代码数目; (10)每次进行修改所消耗的人力和时间; (11)程序修改的日期; (12)软件维护人员的姓名; (13)维护申请表的标识; (14)维护类型; (15)维护的开始和结束日期; (16)维护工作累计花费的人力和时间; (17)与维护工作相关的纯收益。 维护的实施工作完成后,最好对维护工作进行评审。维护评审可以为软件开发机构的有效管

理提供反馈信息,对以后的维护工作产生重要的影响。维护评审时,评审人员应该对以下问题进

行总结: (1)在当前的环境下,设计、编码或测试的工作中是否还有改进的余地和必要? (2)缺乏哪些维护资源? (3)维护工作遇到的障碍有哪些? (4)从维护申请的类型来看,是否还需要有预防性维护? 5.对维护工作进行评价

当维护工作完成时,需要对维护工作完成的好坏进行评价。维护记录中的各种数据是维护评

价的重要参考。如果维护记录完成得全面、具体、准确,会在很大程度上方便维护的评价工作。 对维护工作进行评价时,可以参考的评价标准有: (1)程序运行时的平均出错次数; (2)各类维护申请的比例; (3)处理不同类型的维护,分别消耗的人力、物力、财力、时间等资源; (4)维护申请报告的平均处理时间; (5)维护不同语言的源程序所花费的人力和时间; (6)维护过程中,增加、删除或修改一条源语句所花费的平均时间和人力。

6.1.2 软件维护的分类

前面多次提到维护的类型。本节将对维护的分类做具体介绍。 根据维护工作的特征以及维护目的的不同,软件维护可以分为纠错性维护、适应性维护、完

善性维护和预防性维护 4种类型,如图 6-1所示。 纠错性维护是为了识别并纠正软件产品中所潜藏的错误,改正软件性能上的缺陷所进行的维

护。在软件的开发和测试阶段,必定有一些缺陷是没有被发现的。这些潜藏的缺陷会在软件系统

投入使用之后逐渐地暴露出来。用户在使用软件产品的过程中,如果发现了这类错误,可以报告

给维护人员,要求对软件产品进行维护。根据资料统计,在软件产品投入使用的前期,纠错性维

245

软件工程——理论与实践

护的工作量比较大,随着潜藏的错误不断地被发现并处理,纠错性维护的工作量会日趋减少。 适应性维护是为了使软件产品适应软硬件环境的变更而进行的维护。随着计算机的飞速发展,

软件的运行环境也在不断地升级或更新,比如,软硬件配置的改变、输入数据格式的变化、数据

存储介质的变化、软件产品与其他系统接口的变化等。如果原有的软件产品不能够适应新的运行

环境,维护人员就需要对软件产品做出修改。适应性维护是不可避免的。 完善性维护是软件维护的主要部分,它是针对用户对软件产品所提出的新需求所进行的维护。

随着市场的变化,用户可能要求软件产品能够增加一些新的功能,或者对某方面的功能能够有所

改进,这时维护人员就应该对原有的软件产品进行功能上的修改和扩充。完善性维护的过程一般

会比较复杂,可以看成是对原有软件产品的“再开发”。在所有类型的维护工作中,完善性维护所

占的比重最大。此外,进行完善性维护的工作一般都需要更改软件开发过程中形成的相应文档。 预防性维护主要是采用先进的软件工程方法对已经过时的、很可能需要维护的软件系统的某

一部分进行重新设计、编码、测试,以达到结构上的更新,它为以后进一步维护软件打下了良好

的基础。实际上,预防性维护是为了提高软件的可维护性和可靠性。形象地讲,预防性维护就是

“把今天的方法用于昨天的系统以满足明天的需要”。在所有类型的维护工作中,预防性维护的工

作量最小。 据统计,一般情况下,在软件维护过程中,各种类型的维护的工作量分配如图 6-2所示。

各种维护的工作量比例

适应性维护 25%

完善性维护50% 纠错性维

护 20%

预防性维护 5%

图 6-1 软件维护的分类 图 6-2 各种维护的工作量比例

6.1.3 软件的可维护性

软件的可维护性是衡量对软件产品进行维护的难易程度的标准,它是软件质量的主要特征之

一。软件产品的可维护性越高,纠正并修改其错误或缺陷,对其功能进行扩充或完善时消耗的资

源越少,工作越容易。开发可维护性高的软件产品是软件开发的一个重要目标。 影响软件可维护性的因素有很多,如可理解性、可测试性、可修改性等。可理解性是指人们

通过阅读软件产品的源代码和文档来了解软件的系统结构、功能、接口和内部过程的难易程度。

可理解性高的软件产品应该具备一致的编程风格,准确、完整的文档,有意义的变量名称和模块

名称,清晰的源程序语句等特点。 理解是维护中最重要的因素。

——Ned Chapin 可测试性是指诊断和测试软件缺陷的难易程度。程序的逻辑复杂度越低,就越容易测试。透

彻地理解源程序有益于测试人员设计出合理的测试用例,从而有效地对程序进行检测。

246

第 6章 软件工程的其他相关内容

可修改性是指在定位了软件缺陷以后,对程序进行修改的难易程度。一般来说,具有较好的

结构且编码风格好的代码比较容易修改。 实际上,可理解性、可测试性和可修改性这三者是密切相关的。可理解性较好的软件产品有

利于测试人员设计合理的测试用例,从而提高了产品的可测试性和可修改性。显然,可理解性、

可测试性和可修改性越高的软件产品,它的可维护性就一定越好。 要想提高软件产品的可维护性,软件开发人员需要在开发过程和维护过程中都对其非常重视。

提高可维护性的措施有以下几种。 (1)建立完整的文档。完整、准确的文档有利于提高软件产品的可理解性。文档包括系统文

档和用户文档,它是对软件开发过程的详细说明,是用户及开发人员了解系统的重要依据。完整

的文档有助于用户及开发人员对系统进行全面的了解。 不同用户需要不同级别的文档。有些用户只是偶尔使用文档,有些用户必须依赖程序,还

有一些用户必须根据环境和目的的变动对程序进行修改。 ——《人月神话》

(2)采用先进的维护工具和技术。先进的维护工具和技术可以直接提高软件产品的可维护性。

例如,采用面向对象的软件开发方法、高级程序设计语言以及自动化的软件维护工具等。 (3)注重可维护性的评审环节。在软件开发过程中,每一阶段的工作完成前都必须通过严格

的评审。由于软件开发过程中的每一个阶段都与产品的可维护性相关,因此对软件可维护性的评

审应该贯穿于每个阶段完成前的评审活动中。 在需求分析阶段的评审中,应该重点标识将来有可能更改或扩充的部分。在软件设计阶段的

评审中,应该注重逻辑结构的清晰性,并且尽量使模块之间的功能独立。在编码阶段的评审中,

要考查代码是否遵循了统一的编写标准,是否逻辑清晰、容易理解。严格的评审工作,可以从很

大程度上对软件产品的质量进行控制,提高其可维护性。

6.1.4 软件维护的副作用

软件维护是存在风险的。对原有软件产品的一个微小的改动都有可能引入新的错误,造成意

想不到的后果。软件维护的副作用主要有 3类,包括修改代码的副作用、修改数据的副作用和修改文档的副作用。

程序维护中的一个基本的问题是—缺陷修复总会以固定的几率(20%~50%)引入新

的 Bug。 ——《人月神话》

人类通过编程语言与计算机进行交流,每种编程语言都有严格的语义和语法结构。编程语言

的微小错误,哪怕是一个标点符号的错误,都会造成软件系统无法正常运行。因此,每次对代码

的修改都有可能产生新的错误。虽然每次对代码的修改都可能导致新的错误产生,但是相对而言,

以下修改更具危险性: (1)删除或修改一个子程序; (2)删除或修改一个语句标号; (3)删除或修改一个标识符; (4)为改进性能所做的修改;

247

软件工程——理论与实践

(5)修改文件的打开或关闭模式; (6)修改运算符,尤其是逻辑运算符; (7)把对设计的修改转换成对代码的修改; (8)修改边界条件的逻辑测试。 修改数据的副作用是指数据结构被改动时有新的错误产生的现象。当数据结构发生变化时,

可能新的数据结构不适应原有的软件设计,从而导致错误的产生。例如,为了优化程序的结构将

某个全局变量修改为局部变量,如果该变量所存在的模块已经有一个同名的局部变量,那么就会

引入命名冲突的错误。会产生副作用的数据修改经常发生在以下一些情况中: (1)重新定义局部变量或全局变量; (2)重新定义记录格式或文件格式; (3)更改一个高级数据结构的规模; (4)修改全局数据; (5)重新初始化控制标志或指针; (6)重新排列输入/输出或子程序的自变量。 修改文档的副作用是指在软件产品的内容更改之后没有对文档进行相应的更新而为以后

的工作带来不便的情况。文档是软件产品的一个重要组成部分,它不仅会对用户的使用过程

提供便利,还会为维护人员的工作带来方便。如果对源程序的修改没有反映到文档中,或对

文档的修改没有反映到源程序中,造成文档与源程序不一致,对后续的使用和维护工作都会

带来极大的不便。 对文档资料的及时更新以及有效的回归测试有助于减少软件维护的副作用。

6.2 软件质量保证

6.2.1 软件质量的基本概念

质量是产品的生命线,保证软件产品的质量是软件产品生产过程的关键。ANSI/IEEE729-183把软件质量定义为“与软件产品满足规定的和隐含的需要的能力有关的特征或特性的组合”。也就

是说,软件产品包含一系列的特征或特性,这些特征或特性可以对产品在性能、功能、开发标准

化等各方面的绩效进行度量。软件产品的质量越高,其相关特征或特性就越能满足用户的需求。

实际上,可以通俗地说,软件质量是指软件系统满足用户需要或期望的程度。高质量的软件产品

意味着较高的用户满意度及较低的缺陷等级,它较好地满足了用户需求,具有高水平的可维护性

和可靠性。 质量不是被束之高阁的观赏品,也不是像圣诞树上的闪亮金箔那样的装饰品。

——Robert Pirsig 不难理解,软件的质量是由多种因素决定的,它等价于软件产品的一系列的质量特性。根据

ISO Standard 9126的定义,软件质量的特性包括功能性、可靠性、可用性、效率、可维护性和可移植性。软件质量的每项特性的定义如下。

功能性:符合一组功能及特定性质的属性的组合。

248

第 6章 软件工程的其他相关内容

可靠性:在规定的时间和条件下,软件维持其性能水平能力的属性的组合。 可用性:衡量软件产品在运行中使用灵活、方便的程度。 效率:完成预期功能所需的时间、人力、计算机资源等指标。 可维护性:当系统的使用环境发生变化、用户提出新的需求或者系统在运行中产生了错误时,

对潜在的错误或缺陷进行定位并修改或对原系统的结构进行变更的难易程度。 可移植性:反映了把软件系统从一种计算机环境移植到另一种计算机环境所需要的工作量的

多少。 有关软件质量特性的定义还有很多种,除 ISO Standard 9126的定义外,McCall软件质量特性

模型也很受人们欢迎。McCall软件质量特性模型把与软件质量相关的多种特性划分为运行、维护和移植 3个方面,如图 6-3所示。

McCall软件质量特性模型中的每种特性的定义如下。 正确性:系统在预定的环境下,正确完成系统预期功能的程度。 效率:完成预期功能所需的时间、人力、计算机资源等指标。 可靠性:在规定的时间和条件下,软件维持其性能水平能力的属性的组合。 可用性:衡量软件产品在运行中使用灵活、方便的程度。 完整性:保存必要的数据,使之免受偶然或有意的破坏、改动或遗失的能力。 可维护性:当系统的使用环境发生变化、用户提出新的需求或者系统在运行中产生了错误时,

对潜在的错误或缺陷进行定位并修改或对原系统的结构进行变更的难易程度。 可测试性:测试软件系统,使之能够完成预期功能的难易程度。 灵活性:对一个已投入运行使用的软件系统进行修改时所需工作量多少的度量。 可移植性:反映了把软件系统从一种计算机环境移植到另一种计算机环境所需要的工作量的多少。 互连性:将一个软件系统与其他软件系统相连接的难易程度。 可复用性:软件系统在其他场合下被再次使用的程度。

McCall 软件质量特性模型

正确性、效率、可靠

性、可用性、完整性 可维护性、可测

试性、灵活性

运行 维护

移植

可移植性、互连

性、可复用性

图 6-3 McCall软件质量特性模型

6.2.2 软件质量保证的措施

在软件开发实践中,可以采取多种方法保证软件产品的质量。下面介绍几种常用的方法。 1.基于非执行的测试

非执行的测试是指不具体执行程序的测试工作,也称为软件评审。非执行的测试需要贯穿于

249

软件工程——理论与实践

整个软件开发过程。在项目开发前期,软件开发人员需要制定详细的开发计划以及评审计划,标

识各阶段的检查重点以及阶段工作的预期输出,为以后的阶段评审做准备。 在项目的阶段评审工作中,要保证评审工作的严格性和规范性。首先,评审人员要具备相应

的资格和能力,评审团队的规模及任务分配要合理。每次评审都需要做详细的评审记录,并做出

明确的评审结果。对于不合规范的工作成果还要给出修改意见。 软件评审的具体实施手段包括设计评审、审查、走查、个人评审等。 虽然严格审查有很多优点,但是不能也不应该代替测试。

——Robert L. Glass 2.基于执行的测试

基于执行的测试是指通过具体地执行程序,观察实际输出和预期输出的差异,从而发现软件

产品错误的方法。软件开发人员通常使用一种或几种自动测试工具对系统进行测试。但是,由于

手工测试灵活性高的特点,手工测试也是必需的。 自动测试很少,也就是说有些测试可以也应该自动化,但是有许多测试任务不能自动

完成。 ——Robert L. Glass

测试人员可以使用黑盒测试或白盒测试的方法设计测试用例进行测试。软件测试有利于及早

揭示软件缺陷,其相关内容在第 5章中已有详细介绍。 3.程序的正确性证明

软件测试有一条重要原则是:测试可以发现程序中的错误,但是不能证明程序中没有错误。

可见,软件测试并不能完全证明程序的正确性和可靠性。如果能采用某种方法对软件系统运行的

正确性进行证明,那么软件产品的质量将更有保证。目前,人们已经研究出证明 Pascal 和 LISP程序正确性的软件系统,正在对其进行完善和功能扩充。但是,这些系统还只适用于小型的软件

系统,并不适合大规模的软件系统。

6.3 软件配置管理概述

软件的开发过程中,常常产生大量的文档和程序版本,比如立项报告、需求规格说明书、概

要设计文档、详细设计文档、编码设计说明、源代码、可执行程序、用户手册、测试计划、测试

用例、测试结果、在线文档等,此外还可能有合同、会议记录、报告、审核等管理文档。在软件

开发中,还常常存在对这些文档的大量变更。在人员方面,随着软件规模越来越大,很多项目有

成千的开发人员,而且可能分布于世界各地,有不同的文化和社会背景。如何有效地组织和管理

这些内容,对于项目的成败和效率影响非常重大。 最早的配置管理标准是 1962 年美国空军为了解决喷气飞机设计中的控制和通信问题而制定

和发布的 AFSCM375-1 标准。美国军用标准 MIL_S和国防部标准 DOD_STD 等许多标准都是遵循这一标准而制定的。后来随着计算机的普及和软件开发规模的增长,美国国防部、IEEE、ANSI和 ISO 等组织开始着手制订软件开发过程的配置管理标准。其中最为普遍使用的是 ANSI/IEEE 标准。现在大多数的软件组织在开发的过程中都遵循使用这些标准。而且还有很多依据这些标准设

250

第 6章 软件工程的其他相关内容

计的自动化软件配置管理过程工具,极大地降低管理的难度。

6.3.1 软件配置管理术语

软件配置是软件产品在生命周期的各个阶段中产生的文档、程序和数据的各个配置项的合理

组合。软件从建立到维护的过程中,产生变更是不可避免的。软件配置管理就是一种标识、组织

和控制变更的技术,目的是使由变更而引起的错误降至最少,从而有效地保证产品的完整性和生

产过程的可视性。 改进的艺术是在变更中保持有序,同时在有序中保持变更。

——Alfred North Whitehead 由于软件配置管理涉及很多概念,为了便于深入理解,下面给出一些软件配置管理的相关术

语,这些术语主要基于 GB/T 12505—90规范。 (1)项目委托单位。项目委托单位(Project Entrust Organization)是指为产品开发提供资金,

通常也是(但有时未必)确定产品需求的单位或个人。 (2)项目承办单位。项目承办单位(Project Undertaking Organization)是指为项目委托单位

开发、购置或选用软件产品的单位或个人。 (3)软件开发单位。项目开发单位(Software Development Organization)是指直接或间接受

项目委托单位而直接负责开发软件的单位或个人。 (4)用户。用户(User)是指实际只用软件来完成某项计算、控制或数据处理等任务的单位

或个人(即软件的最终使用者)。 (5)软件。软件(Software)是指计算机程序以及有关的数据和文档,也包括固化到硬件中

的程序。 IEEE 给出的定义是:计算机程序、方法、规则、相关的文档资料以及在计算机上运行时所

必需的数据。 (6)配置。配置(Configuration)是指在配置管理中,软件或硬件所具有的(即在技术文档

中所陈述的或产品所实现的)那些功能特性和物理特性。 (7)软件对象。软件对象(Software Object)是在项目进展过程中产生的、可由软件配置管

理加以控制的任何实体。每个软件对象都具有唯一的一个标识符、一个包含实体信息的对象实体、

一组用于描述其自身特性的属性与关系以及用于与其他对象进行关系操作与消息传递的机制。 软件对象按其生成方式可分为源对象(Source Object)与派生对象(Derived Object),按其内

部结构可分为原子对象(Atomic Object)与复合对象(Composite Object),按照软件开发的不同阶段可分为可变对象(Mutable Object)与不可变对象(Immutable Object)。 (8)软件生存周期。软件生存周期(Software Life Cycle)是指从对软件系统提出应用需求开

始,经过开发,产生出一个满足需求的计算机软件系统,然后投入实际运行,直至软件系统退出

使用的整个过程。这一过程划分为 3个主要阶段,系统分析与软件定义、软件开发、系统运行与维护。其中软件开发阶段又分为需求分析、概要设计、详细设计、编码与单元测试、组装与集成

测试、系统测试、安装与验收等 7个阶段。 (9)软件开发库。软件开发库(Software Development Library)是指在软件生存周期的某一阶

段中,存放与该阶段软件开发工作有关的计算机可读信息和人工可读信息的库。 (10)配置项。GB/T 11457—1995《软件工程术语》中对配置项(Configuration Item)的定义

251

软件工程——理论与实践

为:为了配置管理目的而作为一个单位来看待的硬件和/或软件成分,满足最终应用功能并被指明用于配置管理的硬件/软件或它们的集合。 软件配置管理的对象是软件配置项,它们是在软件工程过程中产生的信息项。在 ISO 9000-3

中的,配置项可以是 与合同、过程、计划和产品有关的文档和数据; 源代码、目标代码和可执行代码; 相关产品,包括软件工具、库内的可复用软件/组件、外购软件及用户提供的软件。 上述信息的集合构成软件配置,其中每一项称为一个软件配置项,这是配置管理的基本单位。

软件配置项基本可划分为两种类别: 软件基准。经过正式评审和认可的一组软件配置项(文档和其他软件产品),它们作为下

一步的软件开发工作基础。只有通过正式的变更控制规程才能更改基准。比如详细设计是编码的

工作基础,详细设计文档是软件基准的配置项之一。 非基准配置项。没有正式评审或认可的一组软件配置项。 配置标识的命名必须唯一,以便用于追踪和报告配置管理项的状态。通常情况下,配置项标

识常常采用层次命名的方式,以便能够快速地识别配置项,比如某一即时通信软件的登录配置项

可以命名为 IM_Log_001、IM_Log_002等。

图 6-4 软件配置管理项的 4种状态

根据软件的生命周期,一般把配置管理项分

为 4 种状态,如图 6-4 所示。4 种状态之间的联系具有方向性,实线箭头所指方向的状态变化是

允许的,虚线表示为了验证或检测某些功能或性

能而重新执行相应的测试,正常情况下不沿虚线

方向变化。 (11)配置标识。配置标识(Configuration Identification)由系统所选的配置项及记录它们功

能和物理特性的技术文档组成;经核准的配置项的技术文档由说明书、图、表等组成。为了方便

对配置项进行控制和管理,需要对它们进行唯一的命名。 配置标识的主要目的是对变更配置项的软件行为及变更结果提供一个可跟踪的手段,避免软

件开发行为在不受控或混乱的情况下进行,也有利于软件开发工作以基线渐进的方式完成。 (12)配置管理。配置管理(Configuration Management)是指对配置管理过程中的各个对象

进行监视和管理。如对配置项的功能特性和物理特性进行标识并写成文档;对这些特性的更改进

行控制;对更改处理过程和实施状态进行记录和报告;对是否符合规定需求进行验证等。 (13)版本。版本(Version)是某一配置项的已标识的实例;或者定义为:不可变的源对象

经质量检验合格后所形成的新的相对稳定的状态(配置)称为软件版本。 (14)基线。基线(Baseline)指一个配置项在其生存周期的某一特定时间,被正式标明、固

定并经正式批准的版本。也可以说,基线是软件生存期中各开发阶段末尾的特定点,也常称为里

程碑。所有成为基线的软件配置项协议和软件配置的正式文本必须经过正式的技术审核。通过基

线,各阶段的任务划分更加清晰,本来连续的工作在这些点上断开,作为阶段性的成果。基线的

作用就是进行质量控制,是开发进度表上的一个参考点与度量点,是后续开发的稳定基础。基线

的形成实际上就是对某些配置项进行冻结。一般情况下,不允许跨越基线修改另一阶段的文档。

比如,一旦完成系统设计,经过正式审核之后,设计规格说明就成为基线,在之后的编码和测试

等阶段,一般不允许修改设计文档;如果存在重大的设计变更,则必须通过正式的流程由系统设

252

第 6章 软件工程的其他相关内容

计人员对系统设计进行修正,并重新生成基线。 基线又分为功能基线、分配基线、产品基线、过程能力基线等。 (15)版本控制。版本控制(Version Control)就是管理在整个软件生存周期中建立起来的某

一配置项的不同版本。

6.3.2 配置管理的过程

配置管理的工作范围一般包括 4个方面:标识配置项,进行配置控制,记录配置状态和执行配置审计。 (1)标识配置项。所谓配置项是配置管理中的基本单元,每个配置项应该包含相应的基本配

置管理的信息。标识配置项就是要给配置项取一个合适的名字。所有的软件产品都要进行配置项

的标识,该标识符应该具有唯一性,并且要遵循特定的版本命名规律,以便于管理和追踪。例如,

V2005.0.1,V2008.1.2。 (2)进行配置控制。进行配置控制是配置管理的关键,包括访问控制、版本控制、变更控制

和产品发布控制等。 访问控制通过配置管理中的“软件开发库”、“软件基线库”、“软件产品库”来实现,每个

库对应着不同级别的操作权限,为团队成员授予不同的访问权利。 版本控制是指用户能够对适当的版本进行选择从而获得需要的系统配置,它往往使用自动

的版本控制工具来实现,例如 SVN。 变更控制是应对软件开发过程中各种变化的机制,可以通过建立控制点和报告与审查制度

来实现。 产品发布控制面向最终发布版本的软件产品,旨在保证提交给用户的软件产品版本是完

整、正确和一致的。 (3)记录配置状态 记录配置状态的目的是使配置管理的过程具有可追踪性。配置状态报告记录了软件开发过程

中每一次配置变更的详细信息,包括改动的配置项、改动内容、改动时间和改动人等。配置状态

报告是开发人员之间进行交流的重要工具,对项目的成功非常重要。 (4)执行配置审计 配置审计是为了保证软件工作产品的一致性和完整性,从而保证最终软件版本产品发布的正确性。 软件的配置管理贯穿于整个软件开发过程,可以建立和维护在整个软件生命周期内软件产品

的完整性。目前市场上流行的配置管理工具有很多,比如微软公司的 Visual Source Safe(VSS)和 Rational公司的 Clear Case等。

6.3.3 配置管理的角色划分

比较合理的基于软件配置管理的团队成员一般会包含如下的角色: (1)负责软件小组的项目经理; (2)负责软件配置管理规程和方针的配置管理者; (3)负责软件产品开发与产品维护的软件工程师; (4)负责验证产品正确性的测试者; (5)负责确保产品质量的质量保证经理; (6)使用产品的用户。

253

软件工程——理论与实践

不同的角色可以根据团队自身情况由相同的人担任,不过,配置管理建议这些角色由不同的

人担任,以保证每个成员能够专注于自身的角色。 项目经理的目标是确保产品在一定的时间框架里开发,其任务是监视开发过程并发现问题,

及时解决出现的问题。而这些问题又必须通过分析软件系统的现状报告以及评审系统才能完成。 配置管理者的目标是确保代码的创建、变更和测试等活动都执行相应的程序和方针,并使有

关工程的信息都是可访问的。为了实施控制代码变更,管理者需要制订变更请求、变更评估、变

更允许的策略和方法。管理者需要为每个成员和相关工程创建和分配任务表。同时,管理者还要

收集统计软件系统各部件的信息。 软件工程师的目标是实现产品。由于工程师彼此之间需要协作和沟通,而又不能影响到彼此

的工作,所以通常每个工程师都有自己独立的工作区域用于创建、变更、测试和集成代码。而软

件配置管理可以将工程师的工作成果以代码基线渐进的方式保存,便于延续以后的开发工作和对

不同目标的并行开发。 测试者的目标是保证产品的所有内容都是经过充分测试并符合要求的。这包括对产品的某个

版本进行的测试以及将测试结果与该版本一起保存。需要回归测试时,可以相对容易地追踪到错

误的发生版本以及原因,并将其反馈给开发人员。 质量保证经理的目标是确保产品的高质量。制订的程序和方针必须以适当的方法完全贯彻执

行。错误和漏洞必须得到修改和重新测试。客户对产品的意见也必须得到跟踪和响应。 不同的客户使用的产品版本有时是不同的,客户需要遵循制订的程序来做变更请求和参与改

进产品。

6.4 软 件 估 算

6.4.1 软件估算的概念

软件估算(Software Estimation)是指以准确的调查资料和项目信息(如人员和设备信息)为依据,从估算对象的历史、现状及其规律性出发,运用科学的方法,对估算对象的规模、所需工

作量和成本进行的测定。 软件估算需要的文档有需求说明书、系统设计、对象设计和变更请求,估算的内容包括软件

规模、工作量和进度。对于估算来说,有些可以做得很仔细,而大多数只是凭主观经验判断。所

以多数估算难以做到 10%以内的精确度,有的甚至误差达几倍,尤其是估算人员经验不足或估算项目没有可参考凭借之时。 软件项目估算是项目计划的依据,但是多数的软件开发组织没有意识到软件估算的重要性。

调查结果显示: (1)35%的组织没有对软件开发的成本和时间做估算; (2)50%的组织没有记录任何正在进行的项目的相关数据; (3)57%的组织没有使用成本会计; (4)80%的项目在成本或时间上超出预算; (5)超出成本和时间的项目里仅有 50%是有意义的超出; (6)进行成本估算的组织里,62%的组织是基于主观经验,仅仅 16%的组织使用了正式的估

254

第 6章 软件工程的其他相关内容

算方法,如成本估算模型。

Case Study ——凭直觉的项目估算 Carl 负责 Gaga-safe 公司库存控制系统 1.0 版本的开发(ICS),在参加项目监督委员会第

一次会议的时候,他对期望的功能已经有了总体设想。Bill 是监督委员会的领导,他问:“Carl,ICS1.0 需要多长时间?”。

Carl 回答:“大概要 9 个月,不过这只是粗略的估算。” “不行,”Bill 说,“我真希望你说 3 或 4 个月,我们一定要在 6 个月内拿出系统,能完成吗?” “我不能肯定,”Carl 坦白地说,“我还得仔细研究一下,不过我相信可以找到办法在 6

个月内完成。” “那么把 6 个月当成项目完成的目标,”Bill 说,“无论如何我们都必须这样做。”委员会

的其他人也一致同意了这个决定。 经过第一周的计划,第二、三周跟客户进行的需求沟通,第四周的技术筹备,到了第五

周时,又增加了一些产品概要设计工作,这使 Carl 更确信项目的时间更接近 9 个月而非 6 个

月。然而他还是认为运气好的话还是可能在 6 个月内完成的。他不想被看做惹麻烦的人,所

以决定等等再说。 Carl 的团队努力地工作着,进展稳定,但需求分析的时间比期望的要长。预定 6 个月要

完成的项目已经过去了 4 个月。“2 个月无论如何也做不完剩下的工作。”他只好告诉 Bill,项

目需要延长 2 个月,总共需要 8 个月时间。 几个星期后,Carl 意识到进度也不像期望的那么快,“先做容易部分,”他告诉项目组成

员,“其余部分遇到时再考虑。” Carl 再次向监督委员会报告:“8 个月的项目已经过去了 7 个月,详细设计基本完成,工

作卓有成效,但 8 个月内无法完成。”Carl 通报了第二次进度拖延,并将完成时间延期为 10个月。Bill 对进度的拖延产生了抱怨,并要求 Carl 想办法把进度仍安排在 8 个月左右。

第 9 个月,项目完成了详细设计,但部分模块的编码还没有开始。Carl 第三次要求延

期—12 个月。Bill…… 编码进行顺利,但一些地方需要重新设计和实现,而这些地方项目组没有把详细设计

调整好,一些实现过程互相冲突。在第 11 个月的项目监督委员会上,Carl 宣布了第 4 次延

期—13 个月。Bill…… 最后,Carl 的项目组在第 15 个月完成了最后的工作。Bill……

一些组织希望在需求定义投入前就把成本估算的误差控制在 10%以内。尽管项目的精确估计

越早达到越好,但理论上是不可能实现的。软件开发是一个逐渐改进的过程,在每个阶段,都可

能出现影响项目最终成本和进度的决策或困难。不考虑这些问题,将会导致最终估算结果产生很

大偏差。对于经验不成熟的估算人员来说,尤其如此。有的项目误差可能达到 300%,最终结果却是在投入大量人力物力和财力之后被迫放弃。 不同的软件开发阶段,估算的对象和使用的方法都会有所不同,估算的精确度也不一样。一

般来说,随着项目进展,对项目内容了解越多,估算也会越来越精确。 估算既不要过高也不要过低,应该与实际费用尽可能接近。估算的目标是寻找估算与实际的

交汇点。在软件企业中,有时估算人员会迫于领导的压力凭直觉压缩估算,往往导致估算误差增

255

软件工程——理论与实践

大,也给项目组成员造成更大压力。正确估算很重要,应该根据具体情况,制定不同的估算计划,

计划内容可以包括估算的对象说明、估算人员的角色和职责、估算的方法、估算的风险识别、工

作量估算、估算活动进度安排。大的估算活动还需要取得参与估算人员对估算计划的承诺,交给

机构高级管理者审阅后执行估算活动,确保估算活动顺利进行。

6.4.2 软件估算的方法

估算的方法有很多,大致分为基于分解技术的估算方法和基于经验模型的估算方法两大类。

基于分解技术的方法包括功能点估算法、特征点估算法、对象点估算法、代码行(LOC)估算法、MARK Ⅱ等;基于经验模型的方法包括 IBM模型、普特南模型、COCOMO模型等。

1.功能点估算法

功能点(FP)估算法是一种在需求分析阶段基于系统功能的一种规模估算方法,也叫做 IBM方法。这种方法适用于面向数据库应用的项目早期的规模估算,基于初始应用需求(即需求规格

说明书)来确定各种输入、输出、计算和数据库需求的数量和特性获得功能点。功能点方法包括

3个逻辑部分:未调整的功能点、加权因子和功能点。 2.LOC估算法

代码行估算往往是依据经验和组织的历史数据进行估算,多采用 PERT、Delphi、WBS、类比估算等方法。优点是计算方便,监控容易,能反映程序员的思维能力;缺点是代码行数不能正确反

映一项工作的难易程度以及代码的效率,而且编码一般只占系统开发工作量的 10%左右。高水平的程序员常常能以短小精悍的代码解决问题。对于相同规模的软件,如果只用代码行方法估算,程序

员水平的改变将使估算结果失真。所以实际中,代码行估算只是作为一个辅助的估算方法。 3.COCOMO估算法

COCOMO(Constructive Cost Model,构造性成本模型)是 Boehm在对 TRW公司的大量软件工程数据进行详细研究后,在《软件工程经济学》(Software Engineering Economics)一书中提出的软件估算综合经验模型。

COCOMO模型适用于以下 3种类型的软件项目。 (1)组织型:组织模式较小的、简单的软件项目,开发人员对开发目标理解比较充分,对软

件的使用环境很熟悉,受硬件的约束较小,有良好应用经验的小型项目组,针对一组不是很严格

的需求开展工作,程序规模一般不是很大。 (2)半独立型:一个中等规模和复杂度的软件项目,具有不同经验水平的项目组必须满足严

格的或不严格的需求,如一个事务处理系统,对于终端硬件和数据库软件有确定需求。程序规模

一般属于中等或较大。 (3)嵌入型:要求在紧密联系的硬件、软件和操作限制条件下运行,通常与某种复杂的硬件

设备紧密结合在一起。对接口、数据结构、算法的要求高。 4.软件方程式估算法

软件方程式估算是一个多变量模型,它假定在软件开发项目的整个生命周期中的一个特定的

工作量分布。该模型是从 4000 多个当代的软件项目中收集的生产率数据中导出的公式。由于公式基于大量的实际参考数据,因此,准确度比较高。

5.类比估算法

类比估算通过与历史项目比较来估算新项目的规模或工作量。类比估算的精度一方面取决于项目与

历史项目在应用领域、环境、复杂度等方面的相似程度,另一方面取决于历史数据的完整性和准确度。

256

第 6章 软件工程的其他相关内容

类比估算需要提前建立度量数据库以及项目完成后的评价与分析机制,保证可信赖的历史数据分析。 6.WBS估算法

工作任务分解(Work Breakdown Structure,WBS)是WBS方法的基础,以可交付成果为导向对项目要素进行细分,直至分解到可以确认的程度。每深入一层,都是对项目工作的更详细定

义。WBS的三要素中,W代表可以拆分的工作任务;B表示一种逐步细分和分类的层级结构;S表示按照一定的模式组织各部分。使用这一方法有以下前提条件: (1)项目需求明确,包括项目的范围、约束、功能性需求、非功能需求等,以便于任务分解。 (2)完成任务必需的步骤已经明确,以便于任务分解。 (3)WBS表确定。 WBS表可以基于开发过程,也可以基于软件结构划分来进行分解,许多时候是将两者结合进

行划分。WBS方法基本都是和其他估算方法结合使用,如 Delphi、PERT方法等。 7.Delphi 估算法

Delphi估算法是一种专家评估法,在没有历史数据的情况下,通过综合多位专家的估算结果作为最终估算结果的方法。特别适合于需要预测和深度分析的领域,依赖于专家的评估能力,一

般来说可以获得相对客观的结果。 Delphi估算法的基础假设是: (1)如果多位专家基于相同的假设独立地做出了相同的评估,那么该评估多半是正确的。 (2)必须确保专家针对相同的正确的假定进行估算工作。 8.PERT 估算法

PERT估算法是一种基于统计原理的估算法,对指定的估算单元(如规模、进度或工作量等),由直接负责人给出 3个估算结果,分别为乐观估计、悲观估计和最可能估计,对应有最小值、最大值和最可能值。然后通过公式计算期望值和标准偏差,并用其表述估算结果。

PERT方法通常与WBS方法结合使用,尤其适用于专家不足的情况。当然,如果有条件结合Delphi方法,将会大大提高估算结果的准确性。

9.综合估算法

WBS、Delphi、PERT方法经常综合使用,以期获得更为准确的估算。在这种综合估算法中,WBS是估算的基础,将作业进行分解,并用WBS表格给出;然后每位专家针对作业项使用 PERT估算法,得出期望值;再用 Delphi方法综合评估专家结果。

6.4.3 软件估算的原则与技巧

估算毕竟只是预计,与实际值必定存在差距。注意结合以下的估算原则和技巧,有利于提高

估算准确度。 (1)估算时间越早,误差越大。但有估算总比没估算好。 (2)估算能够用来辅助决策。良好的估算有利于项目负责人作出符合实际的决策。 (3)在项目计划中预留估算时间,并做好估算计划。 (4)避免无准备估算,估算前能收集到越多数据,越利于估算结果的准确性。 (5)估算尽量实现文档化,以便于将估算经验应用于以后的估算中。 (6)尽量结合以前的项目估算数据和经验,有利于提高当前估算准确度。 (7)估算工作单元最好有一个合适粒度,而且各单元之间最好互相独立。 (8)尽量考虑到各类因素,如假期、会议、验收检查等影响估算结果的因素。

257

软件工程——理论与实践

(9)尽量使用专用人士做估算员,如涉及代码量的,最好使用负责实现该任务的程序员来估算。 (10)使用估算工具,提高估算精度和速度。 (11)结合多种估算方法,从不同角度进行估算。 (12)估算目的是得到准确结果,而不是寻求特定结果。比如,不要因为预算不够而刻意压低

估算,或隐匿不确定成本等。

6.5 软件过程能力成熟度模型

软件过程能力成熟度模型(Capability Maturity Model,CMM)是用于评估软件能力与成熟度的一套标准,它由美国卡内基·梅隆大学软件工程研究所推出,侧重于软件开发过程的管理及工

程能力的提高与评估,是国际软件业的质量管理标准。 软件过程能力成熟度模型认为,软件质量难以保证的问题在很大程度上是由管理上的缺陷造

成的,而不是由技术方面的问题造成的。因此,软件过程能力成熟度模型从管理学的角度出发,

通过控制软件的开发和维护过程来保证软件产品的质量。它的核心是对软件开发和维护的全过程

进行监控和研究,使其科学化、标准化,能够合理地实现预定目标。 此外,软件过程能力成熟度模型建立在很多软件开发实践经验的基础上,汲取了成功的实践因

素,指明了一个软件开发机构在软件开发方面需要管理哪些方面的工作、这些工作之间的关系以及

各项工作的优先级和先后次序等,进而保证软件产品的质量,使软件开发工作更加高效、科学。 软件过程能力成熟度模型的内容如图 6-5所示。

图 6-5 软件过程能力成熟度模型图

软件过程能力成熟度模型中包含 5个成熟度等级,它们描述了过程能力,即通过遵循一系列软件过程的标准所能实现预期结果的程度。这 5个等级分别是初始级、可重复级、已定义级、已管理级和优化级,如图 6-6所示。5个成熟度等级构成了软件过程能力成熟度模型的顶层结构。

图 6-6 软件过程能力成熟度模型的成熟度等级

初始级的软件过程是无秩序的,它几乎处于无步骤可循的状态。管理是随机的,软件产品的成功

258

第 6章 软件工程的其他相关内容

往往取决于个人。在可重复级已建立了基本的项目管理过程,对成本、进度和功能特性可进行跟踪,

并且在借鉴以往经验的基础上制订了必要的规范。在已定义级,用于管理和工程两个方面的过程均已

文档化、标准化,并形成了整个软件组织的标准软件过程,所有项目均使用经过批准、裁减的标准软

件过程来开发和维护软件。已管理级的软件过程和产品质量有详细的度量标准并且得到了定量的认

证和控制。优化级的软件过程可以通过量化反馈和先进的新思想、新技术来不断地、持续性地改进。 好的管理比好的技术更重要。

——Alan M. Davis 在软件过程能力成熟度模型中,每个成熟度等级都由若干个关键过程域组成。关键过程域是

指相互关联的若干个软件实践活动和相关设施的集合,它指明了改善软件过程能力应该关注的区

域以及为达到某个成熟度等级应该重点解决的问题。达到某个成熟度等级的软件开发过程必须满

足相应等级上的全部关键过程域。 对于每个关键过程域,都标识了一系列为完成一组相同目标的活动。这一组目标概括了关键

域中所有活动应该达到的总体要求,表明了每个过程域的范围、边界和意图。关键过程域为了达

到相应的目标,组织了一些活动的共同特征,用于描述有关的职责。 关键实践是指在基础设施或能力中对关键过程域的实施和规范化起重大作用的部分。关键实

践以 5个共同特征加以组织:执行约定、执行能力、执行活动、测量和分析与验证实施。对于每一个特征,其中的每一项操作都属于一个关键实践。 (1)执行约定:企业为了保证过程建立,并且在建立后继续长期有效而必须采取的行动一般

包括构建组织方针、获得高级管理者的支持。 (2)执行能力:描述了组织和实施软件开发过程的先决条件,包括资源获取、人员职责分配等。 (3)执行活动:指实施关键过程域时所必需的角色和规程,一般涉及计划制订、跟踪与监督、

修正措施等。 (4)测量和分析:对过程的执行状况进行测量,并对执行结果进行分析。 (5)验证实施:保证软件开发过程按照已建立的标准或计划执行。

6.6 软件项目管理

进行软件项目管理是一项比较复杂的工作,它是为了实现项目目标,运用相关的知识、技能、

方法和工具,对项目的计划、进度、质量、成本、资源等进行管理、控制或协调的活动。有效的

项目管理不仅可以节省项目的资金,同时也可以节省开发时间,缩短工期,提高软件产品的质量。 在所有恐怖的民间传说中,最可怕的妖怪是人狼,因为它们可以完全出乎意料地从熟悉的

面孔变成可怕的怪物。为了对付人狼,我们在寻找可以消灭它们的银弹。 大家熟悉的软件项目具有一些人狼的特性,常常看似简单明了的东西,却有可能变成一个

落后进度、超出预算、存在大量缺陷的怪物。因此,我们听到了近乎绝望的寻求银弹的呼唤,

寻求一种可以使软件成本像计算机硬件一样迅速降低的尚方宝剑。 但是,我们看看近十年来的情况,没有发现银弹的踪迹。没有任何技术和管理上的进展,

能够独立地许诺在生产率、可靠性或间接性上取得数量级的提高。 ——《人月神话》

259

软件工程——理论与实践

在这里主要介绍软件项目管理中有关成本估计、进度安排及人员组织与分配、风险分析等方

面的内容。 软件开发成本是指项目从设计到完成期间所需全部费用的总和。成本管理就是在整个项目的

实施过程中,为确保项目在批准的成本预算内尽可能好地完成而对所需的各个过程进行的管理与

控制,其内容主要包括资源计划编制、成本估算、项目预算和成本控制 4个过程。 (1)资源计划编制是根据项目结构确定完成项目所需的资源种类和数量。 (2)成本估算是对完成项目所需资源成本的近似估算,常用的方法有自顶向下估算法、自底

向上估算法和差别估计法。 (3)项目预算是根据项目结构将成本估算分配到各个单项工作中。 (4)成本控制就是对项目成本预算的变更控制。 我常常重复这样一个观点,需要协作沟通的人员数量影响着开发成本,因为成本的主要组

成部分是相互的沟通和交流以及更正沟通不当所引起的不良结果。这暗示系统应该由尽可能少

的人员来开发。 ——Frederick P. Brooks, Jr.

软件进度安排的主要目标就是使软件产品能够如期地交付到用户手中。软件进度安排的不合

理会直接导致用户的满意度下降,所以合理地安排软件开发进度非常重要。 在众多软件项目中,缺乏合理的进度安排是造成项目滞后的最主要的原因,它比其他所有

因素加起来的影响还要大。 ——《人月神话》

常用的进度安排方法有甘特图法、PERT技术和 CMP方法等。甘特图(Gantt Chart)是由

亨利·甘特于 1910年开发的,它可以直观地表明任务计划在什么时候进行以及实际进展与计划要求的对比。 如图 6-7所示为某软件开发项目的甘特图。

图 6-7 某软件开发项目的甘特图

PERT技术叫做计划评审技术,CMP方法叫做关键路径法。它们的基本原理是一致的,即用

260

第 6章 软件工程的其他相关内容

网络图来表达项目中各项活动的进度和它们之间的相互关系,并在此基础上进行网络分析,确定

关键活动与关键路线,利用时差不断地调整与优化网络,以求得最短周期。因为这两种方法都是

通过网络图和相应的计算来反映整个项目的全貌,所以又叫做网络计划技术。 对人员有效地组织与分配也是软件项目管理的一个重要方面。合理地组织与分配人员能够有

效地缩短软件开发的周期,提高软件开发的质量。由于每个项目成员都有各自的特长和性格特点,

所以必须要充分考虑项目成员的技能情况和性格特点来为他们分配正确的工作,使他们能尽量发

挥自己的特长。 任何事情都存在着风险,软件项目的开发也不例外。例如,项目可能会在预期的时间内无法

完成,项目的经费可能会超过预支,软件产品的功能与用户的要求不符等。这些风险都具有不确

定性,一旦发生就会造成不同程度的危害。 如果你不主动进攻风险,风险就会主动进攻你。

——Tom Gilb 软件风险可以分为项目风险、技术风险和商业风险。 (1)项目风险是指在预算、人力、资源、需求等方面存在的问题,可能会造成项目的成本提

高、开发时间延长的风险因素。 (2)技术风险是指在软件设计、实现方法等方面的不足造成软件开发质量降低的问题。 (3)商业风险主要与市场、销售策略等因素有关。 软件项目的风险分析主要在可行性分析阶段进行,其内容包括风险识别、风险预测和风险管理。 (1)风险识别主要从项目、技术和商业的角度对潜在的风险进行识别。 (2)风险预测利用定量的方法对风险发生的可能性和产生后果的严重程度做出估计。 (3)风险管理的内容涉及两个方面。一方面,风险管理者需要综合考虑风险发生的概率及发

生后产生后果的严重性,确定特定风险的处理策略。对于发生概率低,影响也低的风险可以采用

规避策略,即不需要考虑。另一方面,风险管理者需要对已经识别出的风险定期进行评估,重新

预测其发生的可能性和产生后果的严重程度,从而根据变化及时调整对该风险的处理策略。由于

变化具有永恒性,风险管理的活动应该存在于项目进行的整个过程中。

6.7 软 件 文 档

文档是指某种数据介质和其中所记录的数据。软件文档是用来表示对需求、过程或结果进行

描述、定义、规定或认证的图示信息,它描述或规定了软件设计和实现的细节。在软件工程中,

文档记录了从需求分析到产品设计再到产品实现及测试的过程,甚至到产品交付以及交付后的使

用情况等各个阶段的相关信息。 软件文档的编制在软件开发工作中占有突出的地位和相当的工作量。具体来讲,文档一方面

充当了各个开发阶段之间的桥梁,作为前一阶段的工作成果及结束标志,它使分析有条不紊地过

渡到设计,再使设计的成果物化为软件。 另一方面,文档在团队的开发中起到了重要的协调作用。随着科学技术的发展,现在几乎所

有的软件开发都需要一个团队的力量。团队成员之间的协调与配合不能光靠口头的交流,而是要

靠编制规范的文档。它告诉每个成员应该做什么,不应该做什么,应该按照怎样的要求去做以及

261

软件工程——理论与实践

要遵守哪些规范。此外,还有一些与用户打交道的文档成为用户使用软件产品时最得力的助手。 如果你要做得更好,那就要竞争。如果你要做得非常好,那就要合作。

——匿名 合格的软件工程文档应该具备以下几个特性。 (1)及时性。在一个阶段的工作完成后,此阶段的相关文档应该及时地完成,而且开发人员

应该根据工作的变更及时更改文档,保证文档是最新的。可以说,文档的组织和编写是不断细化、

不断修改、不断完善的过程。 (2)完整性。应该按有关标准或规范,将软件各个阶段的工作成果写入有关文档,极力防止

丢失一些重要的技术细节而造成源代码与文档不一致的情况出现,从而影响文档的使用价值。 (3)实用性。文档的描述应该采用文字、图形等多种方式,语言准确、简洁、清晰、易懂。 (4)规范性。文档编写人员应该按有关规定采用统一的书写格式,包括各类图形、符号等的

约定。此外,文档还应该具有连续性、一致性和可追溯性。 (5)结构化。文档应该具有非常清晰的结构,内容上脉络要清楚,形式上要遵守标准,让人

易读、易理解。 (6)简洁性。切忌无意义地扩充文档,内容才是第一位的。充实的文档在于用简练的语言,

深刻而全面地对问题展开论述,而不在于文档的字数多少。 总体上说,软件工程文档可以分为用户文档、开发文档和管理文档 3类,见表 6-1。

表 6-1 软件文档的分类

文 档 类 型 文 档 名 称

用户文档

用户手册

操作手册

修改维护建议

用户需求报告

开发文档

软件需求规格说明书

数据要求说明书

概要设计说明书

详细设计说明书

可行性研究报告

项目开发计划

管理文档

项目开发计划

测试计划

测试分析报告

开发进度月报

开发总结报告 下面是对几个重要文档的说明。 (1)可行性研究报告:说明该软件开发项目的实现在技术上、经济上和社会因素上的可行性,

评述为了合理地达到开发目标可供选择的各种可能实施的方案。 (2)项目开发计划:为软件项目实施方案制定出的具体计划,应该包括各项工作的负责人员、

开发的进度、开发经费的预算、所需的硬件及软件资源等。

262

第 6章 软件工程的其他相关内容

(3)软件需求规格说明书:也称软件规格说明书,是对所开发软件的功能、性能、用户界面

及运行环境等做出的详细的说明。 (4)概要设计说明书:是概要设计阶段的工作成果,它应说明功能分配、模块划分、程序的

总体结构、输入/输出以及接口设计、运行设计、数据结构设计和出错处理设计等,为详细设计奠定基础。 (5)详细设计说明书:重点描述每一模块是怎样实现的,包括实现算法、逻辑流程等。 (6)用户手册:详细描述软件的功能、性能和用户界面,使用户了解如何使用该软件。 (7)测试计划:为组织测试制定的实施计划,包括测试的内容、进度、条件、人员、测试用

例的选取原则、测试结果允许的偏差范围等。 (8)测试分析报告:是在测试工作完成以后提交的测试计划执行情况的说明。对测试结果加

以分析,并提出测试的结论意见。

6.8 Project 的功能及使用方法介绍

6.8.1 Project 概述

Project是微软公司推出的最优秀的项目管理软件之一,它是Microsoft Office家族的一员,在软件开发、机械制造、工程建设等活动中有着广泛的应用。由于软件开发项目管理工作很复杂,

人们需要借助一些软件工具来进行开发实践。Project作为最常用的软件项目管理工具之一,可以进行项目的控制和跟踪、时间进度安排、资源管理和分配、关键路径分析、工作进度跟踪等。可

以说,Project集范围管理、时间管理、成本管理、人力资源管理、沟通管理和集成管理等所有项目管理功能于一体,是必不可少的软件项目管理工具。

Project的最早版本发布于 1995年,是为Windows 95设计的。随后,微软公司又相继发布了多个版本的 Project。目前,最新版本的 Project为Microsoft Office Project 2010,它包括Microsoft Office Project Standard 2010、Microsoft Office Project Server 2010、Microsoft Office Project Professional 2010以及Microsoft Office Project Web Access 2010。

Microsoft Office Project Standard 2010专为无需基于网站的协调或协作的用户而设计,它兼有可用性、功能性和灵活性,可以帮助用户高效地进行项目管理。用户不仅可以通过控制项目工时、

日程和财务来了解项目进展情况,还可以将 Project与Microsoft Office System程序、强大的报告选项以及指导性的规划、向导与模板进行集成,使项目工作组保持统一。

Microsoft Office Project Professional 2010不仅可以作为单用户的解决方案运行,也可以连接到Microsoft Office Project Server 2010以获得企业项目管理的功能。它专为需要与企业中其他人协同工作,以通过连接到 Office Project Server 2010来共享日程和资源的项目经理设计。

Microsoft Office Project Web Access 2010是Microsoft Office Project Server 2010的网站客户端,它为用户提供了简单的网站界面,来使用Microsoft Office Project 2010的各种功能。用户可以查看、分析和报告包括时间表在内的项目信息,并创建项目建议和活动计划。要使用Microsoft Office Project Web Access 2010,必须具备Microsoft Office Project Server 2010客户端访问许可证。 本书主要介绍Microsoft Office Project Professional 2010(以下简称 Project 2010)的使用。启

动 Project 2010,其工作界面如图 6-8所示。

263

软件工程——理论与实践

标题栏 菜单栏

功能区

编辑域

甘特图域

状态栏

图 6-8 Project 2010工作界面

Project 2010工作界面中各栏的作用如下。 (1)标题栏:显示项目的名称,包含了“最大化”、“最小化”和“关闭”按钮。其中的“自

定义快速访问工具栏”可以自定义快捷操作到标题栏中,如图 6-8中所示,默认包含“保存”、“撤销”和“恢复”操作。 (2)菜单栏:显示用户可以执行的各种操作和命令。每个菜单下面都包含一个功能区,每个

功能区还可以进一步打开。功能区还可以使用紧邻菜单栏右侧“帮助”按钮的“功能区最小化/展开功能区”按钮隐藏和展开功能区(也可使用快捷键“Ctrl+F1”进行操作)。 (3)功能区:显示选择的菜单项中常用的功能按钮,多数可以根据情况进一步展开。 (4)编辑域:输入或编辑域中的信息。 (5)甘特图域:在初始界面中,甘特图域显示左侧编辑域中数据的甘特图。编辑域和甘特图

域的具体情况视选择的甘特图类型而定。 (6)状态栏:位于窗口底部,显示当前操作或模式的有关信息。当 Project 2010 等待用户操

作时,状态栏会显示“就绪”状态。当用户开始输入数据时,状态栏会显示“编辑”状态。其中

的“新任务”状态按钮可以在“手动计划”和“自动计划”之间切换,自动计划时,Project会自动辅助计算时间日期。状态栏的最右侧还有 4个视图切换窗口和缩放轴,视图切换更一般的方法是在菜单“任务”→“甘特图”视图中切换。

Project 2010相对于之前的版本新增了很多功能,下面我们来大致讲解一下在实际项目管理中常用到的一些功能。 (1)新建项目。启动 Project 2010,出现如图 6-8所示的界面。可以新建项目,也可以直接编

辑空白项目,完毕后另存为新项目。如果是团队项目,可能需要连接 Project Server 或是 Team Foundation Server(简称 TFS),后者对于团队项目非常有必要,便于文档的统一管理。对于由 TFS托管的 Project 项目来说,可以用类似于版本管理的方式获取与发布项目。 (2)视图切换。如果需要切换其他视图,可以在“任务”→“甘特图”中切换各类视图。Project

2010支持的视图非常多,所有的视图都存储在“Global.MPT”文件中,用户可以在视图管理器中

264

第 6章 软件工程的其他相关内容

选择当前项目所使用到的视图。管理器可以通过“任务”→“甘特图”→“其他视图”→“管理

器”打开。管理器如图 6-9所示,可以对视图、报表、模块、表等众多资源进行管理。

图 6-9 Project 管理器

(3)编辑数据。在甘特图视图中,编辑域可以编辑任务信息。在甘特图域中可以自动显示编辑域中数据对应的甘特图。假如项目任务包含的任务信息见表 6-2。

表 6-2 项目任务信息

任 务 编 号 任 务 名 称 工 期 前 置 任 务

1 需求分析 15 无

2 系统设计 10 1

3 编码 20 2

4 单元测试 10 3

5 集成测试 5 4 首先在“任务”功能区中选择“自动安排”,以便利用系统自动计算项目时间。然后在编辑域

中依次输入 4项任务名称、第 1项任务的开始时间、每个任务的工期和前置任务,如图 6-10所示。输入任务信息的方式有多种,可以直接从 Excel 表格导入,也可以在编辑区中输入。在项目管理中,所谓任务是指具有开始日期和完成日期的具体工作,它是日程的组成单元。相互关联的任务

便组成了项目。在甘特图的数据域中,可以看到,每一项任务的关联信息有任务名称、工期、开

始时间、完成时间、前置任务和资源。其中,工期是指完成某项任务所需的工作时间长度,它通

常是从任务开始日期到完成日期的工作时间量。资源是指完成任务所需的人员、设备和原材料等,

它分为工时资源和材料资源。工时资源是指人员和设备,材料资源是指可消耗的材料或物品。

图 6-10 项目甘特图

(4)任务摘要。对于某些连续任务,可以添加摘要。类似于分组功能,摘要将多个任务合并为一个任务组。例如,给任务“单元测试”和“集成测试”添加摘要“测试”,方法是连续选中任

务 4和任务 5,选择“任务”→“插入”→“摘要”。生成摘要后,将新摘要任务重命名为“测试”,

265

软件工程——理论与实践

如图 6-11所示。注意,无法直接改变摘要任务的工期和日期,因为它们是基于子任务计算出来的。另外,在右侧窗口的条形图中,摘要任务和普通的任务具有不同的形状。按照上述方法,设定其

他摘要任务。

图 6-11 任务摘要

(5)添加里程碑。还可以在项目的某一阶段添加里程碑。需要注意的是,里程碑标志某一事件发生,是工期为 0的任务。比如在项目结束时,为项目添加“结项”里程碑,标志项目正式结束。方法是选择任务 7,选择“任务”→“插入”→“里程碑”,如图 6-12所示。

图 6-12 里程碑

(6)编辑任务详细信息。对于每一项任务,可以进一步编辑详细信息,例如编辑任务所需资源、任务备注、日历类型等。方法是双击需要编辑的任务,或者是选中需要编辑的任务,选择“任

务”→“属性”→“信息”,打开“任务信息”管理器,如图 6-13 所示。在“前置任务”的类型中,任务关系一共 4类:

图 6-13 任务信息管理器

完成—开始:只有在任务 A完成后,任务 B才能开始。 开始—开始:只有在任务 A开始后,任务 B才能开始。 完成—完成:只有在任务 A完成后,任务 B才能完成。 开始—完成:只有在任务 A开始后,任务 B才能完成。

266

第 6章 软件工程的其他相关内容

(7)设置日历。根据项目组的具体时间安排,设置工作日历。选择“项目”→“属性”→“更

改工作时间”,打开“更改工作时间”管理器,

可在其中设置日历类型、例外日期和例外工

作周。例如,设置 2月 29日为例外日期,在“例外日期”数据栏中填写相应日期,并在“详

细信息”中进一步编辑,如图 6-14所示。 设置 2月 12日到 2月 18日为放假周,

在“工作周”数据栏中填写相应日期即可。最

终的工作时间情况如图 6-15 所示。具体每个工作日的工作起始时间也可以在工作日中编

辑,例如设置某天的工作时间为上午 10点到下午 16点等。如果需要修改所有工作日时间,可以在“文件”→“选项”→“日程”中修改每

天的起止工作时间,也可以修改每天/每周工作多少小时等信息。

图 6-14 设置例外日期

图 6-15 最终工作时间

(8)任务分配。在“任务”→“甘特图”中切换到“任务分配状况”视图,编辑每个任务的

工时信息,Project会自动为每个任务计算具体到每天的工作时间,并自动跳过设置为例外工作日的时间,如图 6-16所示。

图 6-16 任务分配视图

267

软件工程——理论与实践

(9)工作组规划器视图可以跟踪和编辑任务执行信息,如图 6-17所示。在“跟踪甘特图”中也可以查看项目的任务执行信息。

图 6-17 工作组规划器视图

(10)“任务”→“甘特图”→“日历”视图可以提供直观的工作任务日期图,如图 6-18所示。

图 6-18 日历视图

(11)项目详细。在“项目”菜单中提供了 Project项目相关的功能操作,每个 Project项目还可以包含多个子项目,也可以拥有其他关联项目,每个项目还可以自动生成报表、可视报表等统

计信息。这些信息还可以自动导出为Word或 Excel等文件格式,方便项目团队中各类角色人员查看,如图 6-19~图 6-21所示。

图 6-19 项目统计信息

268

第 6章 软件工程的其他相关内容

图 6-20 创建可视报表

图 6-21 Excel中查看可视报表

(12)Project 2010还提供了强大的团队支持功能,当完成一个项目计划时,可以将其发布到TFS服务器上。之后任何团队成员都可以通过Web Access查看任务了,如图 6-22所示。

图 6-22 在Web Access中查看工作项

269

软件工程——理论与实践

6.8.2 利用 Project 管理网上书店系统的开发过程

现在我们对 Project 2010 已有了大致的了解,并熟悉了其中甘特图等的基本绘制方法。在这一节,我们以对网上书店系统开发过程进行管理为例,进一步演示 Project的用法。 (1)启动 Project 2010,在菜单栏里选择“文件”→“新建”,工作界面中会出现一个“新

建项目”的窗口。该窗口中显示了可用的模板,如果没有合适模板,则可以使用“office.com 模板”,系统会自动到 Office官方网站上搜索合适的模板,例如搜索“软件开发”模板,如图 6-23所示。

图 6-23 新建项目

(2)搜索到相关模板后,下载到本地,如图 6-24所示。接下来所要做的工作就是对这份计划进行修改,以适合网上书店系统开发过程的需要,初始模板如图 6-25所示。

图 6-24 下载模板

270

第 6章 软件工程的其他相关内容

图 6-25 软件开发模板

(3)根据网上书店系统开发团队的时间限制和项目规模的实际情况,删除不需要的任务,增加需要的新任务,并更新每项任务的工期。

在菜单栏里选择“项目”→“项目信息”,在弹出的对话框(见图 6-26)中,把项目的开始日期改为其实际开始日期,并选择合适的日程排定方法及日历。

图 6-26 修改项目信息

删除不需要的任务项,增加必要的新任务。在本软件开发模板中,需要删除的任务有:项目范围规划、培训、试生产、部署和实施工作结束后的回顾。

更新工期及任务所需的资源名称。 (4)删减完毕,再通过其他视图审查和修剪相关的任务及时间、资源等数据,如图 6-27所示。 (5)项目计划制订好之后,就可以发布到 TFS 服务器上。在项目进展过程中,还应该对项目

的进展情况进行跟踪。双击相应的任务项,在弹出的对话框(见图 6-28)中修改项目完成的百分比即可。也可通过Web Access跟踪进度,如图 6-29所示。

271

软件工程——理论与实践

图 6-27 审查任务工作

图 6-28 项目跟踪

图 6-29 Web Access跟踪进度

272

第 6章 软件工程的其他相关内容

至此,我们对 Project 2010的使用已经有了基本的了解。

6.9 用户手册编写指南

下面的用户手册模板仅供参考。 1 前言

提供手册的概述,在此可以说明编写这份手册的目的,指明本手册的读者。 1.1 内容简介

简单地介绍编写背景及系统适用的用户。 1.2 基本概念

说明定义的术语在本手册中的含义。 1.3 主要功能

对系统进行简单讲解和功能介绍。 1.4 操作流程

操作流程说明。全面模拟用户操作,从安装、进入、初始化到用户具体操作,对整个流程

进行描述。 1.5 步骤说明

针对操作流程的每一步进行说明。如果在使用说明中有相应的解释,应指明用户查找的位置。 2 功能

这部分包括用户使用的所有功能,是用户使用手册的最重要的部分,要详细描述。 2.1 使用流程

描述具体功能的使用顺序。如果功能之中有分类,例如,有些功能用户用不到,有些用得

到,就要分开写流程。 2.2 具体描述

描述顺序是按照使用流程的每一步进行的。 2.3 进行此功能的业务介绍

对此功能进行简单介绍,说明其所起的作用。 2.4 操作步骤

用鼠标选择相应的功能,进入相应的界面,进行功能键以及栏目的介绍。 2.5 举例

针对某一功能,对于一些比较难的问题,应该进行举例说明。 2.6 特殊提示及注意事项

在使用说明中,每一部分都会归纳一些问题,需要提示用户或者让用户注意,应按照以下规

定的格式进行编写:字体采用仿宋字,字号采用小五号字。 3 附录

对一些在正文中描述不够详尽的地方,可在附录中进行补充;用户经常遇到的问题及问题

解答也可放在附录中。

273

软件工程——理论与实践

6.10 用户安装手册编写指南

下面的用户安装手册的模板可供参考。 1 前言

指明编制该手册的目的和预期的读者,简要介绍该系统的运行环境:操作系统 OS、数据

库系统 DBMS、C/S 二层结构或 B/A/S 三层结构、界面特点以及技术特色。 1.1 内容简介

介绍本手册提供的几个部分:简单介绍大概内容。 1.2 使用约定

提示:安装过程的一些好的方法。 注意:安装过程中需特别注意的地方。 警告:指出危险动作或状态,否则,会对用户的安装造成破坏。

2 单机版的安装及配置 2.1 运行环境

(1)硬件环境:列出运行本系统所要求的硬设备的最小配置。微机要求包括型号、内存、

硬盘、显示器的要求以及一些其他 I/O 设备的要求。 (2)软件环境:列出运行本系统所需要的支持软件,如操作系统、程序语言及数据库管理

系统。 2.2 安装单机版

(1)简单介绍单机版打包光盘的定义和内容。 (2)介绍该系统单机版的安装步骤。

2.3 安装后的系统配置 介绍系统安装之后,查看该系统配置信息的情况,以确定是否需要改动,是否是最优配置。 另外,运行系统的时候,有时会出现数据库连接不成功的情况。在这部分应介绍会有哪几

种可能的原因,并分别简述。 3 网络版的安装及配置 3.1 运行环境

除了对硬件环境提出要求外,对软件环境的要求还应列出运行本系统所需的操作系统、与

操作系统兼容的网络环境、程序语言以及数据库管理系统。 另外,还应简单介绍一下安装网络和数据库所需注意事项和可参考的工具书。

3.2 安装网络版 介绍该系统网络版的安装步骤、如何进行系统环境配置、数据库的默认用户及口令等。

3.3 安装后的系统配置 4 附录 附录 1

安装过程提供的技术支持。说明技术支持的几种方式以及常见安装疑难问题解答。 附录 2

参考资料,应写上书名、版本号、作者、出版社、出版日期。

274

第 6章 软件工程的其他相关内容

小 结

本章涵盖的内容较广,介绍了软件维护、质量管理、配置管理、软件估算、项目管理、文档

编写等,这些内容都是软件工程的重要组成部分。 软件维护是指在软件产品交付给用户之后,为了改正在软件测试阶段未发现的缺陷,改进软

件产品的性能,补充软件产品的新功能等所进行的修改软件的过程。根据维护工作的特征以及维

护目的的不同,软件维护可以分为 4种类型:纠错性维护、适应性维护、完善性维护和预防性维护。在学习本章后,读者应该对各种类型的软件维护的特点有所了解。 软件的可维护性是用来衡量对软件产品进行维护的难易程度的标准,它与软件的可理解性、

可修改性、可测试性密切相关。软件维护具有副作用,所以在进行软件维护时要慎之又慎。 软件质量是软件产品的生命线,也是软件企业的生命线。在软件质量管理方面,本章主要介

绍了软件质量的相关定义、质量管理的措施、软件估算和软件过程能力成熟度模型。 根据 ISO Standard 9126,软件质量的特性包括功能性、可靠性、可用性、效率、可维护性和

可移植性。除 ISO Standard 9126的定义外,McCall软件质量特性模型也很受人们欢迎。保证软件质量的措施有:基于非执行的测试、基于执行的测试和程序的正确性证明。 本章介绍了软件配置管理相关的基础知识相关内容,配置管理中经常用到的术语以及配置管

理过程和角色划分。 软件估算对于制订良好的项目计划是必需的,良好的估算不仅能够提供项目的宏观概要,还

能够从估算中明确地估计到项目日后进展中可能遇到的一系列问题。对于制订合理的计划和分配

资源非常重要。 能力成熟度模型(CMM)是评估软件能力与成熟度的一套标准,它侧重于软件开发过程的管

理及工程能力的提高与评估,是国际软件业的质量管理标准。 此外,本章还介绍了软件项目管理的工作内容。进行软件项目管理是一项比较复杂的工作,

它是为了实现项目目标,运用相关的知识、技能、方法和工具,对项目的计划、进度、质量、成

本、资源等进行管理、控制或协调的活动。软件项目管理是现代项目管理在软件领域的发展分支,

是软件工程学科和工程管理学科的交叉点。 当然,我们不能忽视软件文档在软件工程中的重要地位。软件文档的编制在软件开发工作中

占有突出的地位和相当的工作量。合格的软件工程的文档应该具备及时性、完整性、实用性、规

范性、结构化和简洁性等特点。通过学习,读者还应该清楚软件文档的分类。 最后,本章介绍了 Project的功能及使用方法、用户手册编写指南以及用户安装手册编写指南。

习 题

1.为什么要进行软件维护?软件维护的作用有哪些? 2.什么是软件的可维护性?软件的可维护性与哪些因素有关? 3.请简述McCall对软件质量的定义。 4.请简述配置管理的基本过程。

275

软件工程——理论与实践

5.请简述软件估算的意义。 6.什么是程序的正确性证明?它的意义在哪里? 7.在软件过程能力成熟度模型中,用于组织关键实践的共同特征是什么? 8.如何进行软件项目的风险分析? 9.软件工程文档可以分为哪几类?每类中具体包含的文档有哪些?

276

第7章 课程设计 本章目标 ● 以团队形式按要求完成选定课题。

7.1 课 程 设 计

通过学习本书,读者应该初步掌握软件工程的基础知识能够综合运用所学知识及合适过程模

型组队实现具有一定复杂度的软件系统。 软件工程是理论与实践结合非常紧密的学科,建议读者在学习的过程中,采用理论到实践,

再回归理论的学习策略。如果条件允许,可以尝试选择合适的题目进行课程设计。通过实际的项

目将所学的知识串联起来,同时也是对所学知识的检验。做软件切忌眼高手低,一定要通过深入

参与完整的软件项目来深切体会软件工程相关的知识理论。很多问题,只有在实际的工作中才能

发现;解决了这些问题,才能够真正提高读者的能力。 由于多数院校的软件工程课程设计要求为一学期内完成,题目自选,学生划分为 4-6人组(组

内人员分工协作),所以在设计课设题目时会尽量以此作为参考。对于软件工程的选题,还应避免

一些不太适合使用软件工程思想的项目,比如算法密集而功能简单的项目等。 本章后续部分提供了 20道课程设计题目供读者选择使用。 读者的课程设计评价重点从以下几个方面着手。 (1)团队的分工与协调。课程设计需要以团队的形式进行,团队的分工、各成员之间互相协

调是考核的重点。因为在以后的实际工作中,几乎所有的软件系统都是由团队来开发完成的,所

以团队协调程度是课程设计的首要因素。 (2)课题的复杂程度。无疑,软件系统越复杂,设计实现越困难,中间遇到的问题也越多,

需要投入的时间也越多,但最终的收获也越大。因此,课题的复杂程度也是评价课设的重要参考

因素之一。 (3)软件工程过程的完整性和规范性。完整的软件工程过程应至少包含需求分析、系统设计、

编码和测试 4个阶段。同时,项目管理、配置管理也是必不可少的工作,因此,过程的完整性和规范性能够反映团队对软件工程的理解以及实际操作能力,能很好地考察读者的软件工程素质。 (4)文档是否齐全和规范。课程设计对于各阶段的工作都有明确的文档要求,包括需求分析

文档、概要设计和详细设计文档、软件测试文档、用户手册等,这些文档的完备性和规范程度也

277

软件工程——理论与实践

能够反映读者对基础知识的掌握程度和运用能力。 根据以上 4点,给出一套评估方法,供读者参考。前 3点作为一个部分,第 4点单独作为一

个部分,最终成绩为两部分的平均。两部分的具体评分见表 7-1和表 7-2。

表 7-1 软件部分

团队成员分工和角色是否明确(10分)

项目经理的作用(10分) 团队分工与协调情况

团队沟通和协调机制(30分)

软件复杂程度(20分)

完成百分比(10分)

可用性(10分) 软件复杂度以及实现情况

软件实际情况

易用性(10分)

软件工程过程的完整性(20分)

软件工程各阶段工作的规范性(20分) 团队软件工程过程执行情况

软对在软件工程过程中的收获和进步(10分)

表 7-2 文档部分

需求、设计、测试、用户手册等主要文档是否齐全(20分)

各文档内容是否完整,是否包含文档规范要求的各个组成部分(15分) 文档完整性

各文档内部的诸如用例图等软件工程技术的完整性(15分)

文档规范性 按照各文档的规范性标准给分(50分)

文档正确性 按照各文档的内容正确性标准给分(50分)

7.2 课程设计题目

对于本部分的课程设计,读者应该尽可能地使用面向对象的设计原则。使用本书前面介绍的

理论,进行面向对象的需求分析、面向对象的系统设计、面向对象的程序实现和面向对象的软件

测试,并充分结合各章节实践部分介绍的各种知识和工具进行设计。题目难度分为 4个星等,推荐度分为 3个星等。如果时间充裕,推荐读者选择难度 2~3个星等,推荐度 3个星等的题目进行实践练习。

7.2.1 网上书店

【设计任务】 开发一个基于Web的网上书店,系统可以分类录入书籍和相关信息(如书名、作者、版本、

出版社、出版时间、摘要、目录、页数等);用户可以注册、登录系统,浏览/搜索图书,购买图书,查看订单状况;管理员可以登陆系统后台,维护用户信息、图书信息,入库和下架图书,统

计订单,发布站点公告,图书荐购信息。 难度:★★★★ 推荐指数:★★★

278

第 7章 课程设计

【设计要求】 1.团队合作,4~6人,10~15周时间。 2.文档完善,必须包括《项目计划书》、《需求规格说明书》、《系统概要设计》、《系统详细设

计》、《系统测试说明书》、《用户手册》、《会议记录》和《项目结项总结》文档。 3.团队中必须具有项目经理、架构师、开发人员、测试人员角色。

【扩充功能】 1.支持用户之间的站内信。 2.采用MVC设计模式。

7.2.2 图书馆图书管理系统

【设计任务】 开发一个图书馆图书管理系统,系统可以分类录入书籍和相关信息如书名、作者、版本、出

版社、出版时间、摘要、目录、页数等;学生可以使用系统分配的账号登录系统,浏览/搜索图书,借阅/续借图书,预约图书,给图书馆荐购图书;管理员可以登录系统后台,维护学生信息、书籍信息,负责新书的入库和下架,发布公告。 难度:★★★★ 推荐指数:★★★

【设计要求】 1.团队合作,4~6人,10~15周时间。 2.文档完善,必须包括《项目计划书》、《需求规格说明书》、《系统概要设计》、《系统详细设

计》、《系统测试说明书》、《用户手册》、《会议记录》和《项目结项总结》文档。 3.团队中必须具有项目经理、架构师、开发人员、测试人员角色。

【扩充功能】 1.学生可以对每本书发表评论。 2.书籍快要到期或预约书籍可借时给学生发送邮件提醒。

7.2.3 教务系统

【设计任务】 开发一个本科生教务系统,学生可以登录在线选择选修课,查看自己的必修课程和选择的选修课

程,查看自己的考试日期、课程成绩,给课程老师评分;老师可以登录系统查看自己的授课表,设置

所授课程考试日期,给每个学生打分;管理员可以在线排课,管理学生、老师信息,发布系统公告。 难度:★★★★ 推荐指数:★★★ 【设计要求】 1.团队合作,4~6人,10~15周时间。 2.文档完善,必须包括《项目计划书》、《需求规格说明书》、《系统概要设计》、《系统详细设

计》、《系统测试说明书》、《用户手册》、《会议记录》和《项目结项总结》文档。 3.团队中必须具有项目经理、架构师、开发人员、测试人员角色。

【扩充功能】 1.学生可以使用网站导出 Excel格式的课程表。

279

软件工程——理论与实践

2.老师可以上传 Excel格式的成绩单到系统中,以方便录入成绩。 3.实现自动无冲突排课,并尽可能考虑同一课程的合理时间间隔。

7.2.4 会议室管理系统

【设计任务】 开发一个基于 Web 的会议室管理系统,包含会议室申请,会议室安排以及各种会议室资源(如

投影仪、计算机、钥匙)的借还等,自动生成会议资源通知单以邮件方式通知申请单位,会议室

使用情况在线即时查阅以及存档会议纪要信息。 难度:★★★★ 推荐指数:★★★

【设计要求】 1.团队合作,4~6人,6~10周时间。 2.文档完善,必须包括《项目计划书》、《需求规格说明书》、《系统概要设计》、《系统详细设

计》、《系统测试说明书》、《用户手册》、《会议记录》和《项目结项总结》文档。 3.团队中必须具有项目经理、架构师、开发人员、测试人员角色。

7.2.5 财务管理系统

【设计任务】 开发一个基于Web的财务管理系统,包含基础信息管理(用户登录、用户信息管理、数据备

份),支出信息管理(支出类别、金额),收入信息管理(收入类别、金额)和数据报表(支持周

报表、月报表、年报表以及任意时段报表)。 难度:★★★ 推荐指数:★★★

【设计要求】 1.团队合作,3~5人,6~10周时间。 2.文档完善,必须包括《项目计划书》、《需求规格说明书》、《系统概要设计》、《系统详细设

计》、《系统测试说明书》、《用户手册》、《会议记录》和《项目结项总结》文档。 3.团队中必须具有项目经理、架构师、开发人员、测试人员角色。

【扩充功能】 支持自动输出为 word 和 pdf 格式的财务报告。

7.2.6 本科生毕业设计管理

【设计任务】 开发一个基于Web的本科生毕设管理系统,包含学生选题、开题答辩、中期答辩、最终答辩

以及论文评阅流程。每次答辩需要 3位老师作为评委,本次答辩成绩取评委的评分均值。最终论文评阅需要学生指导老师和评审老师依次评阅。 难度:★★★ 推荐指数:★★★

【设计要求】 1.团队合作,3~5人,6~10周时间。

280

第 7章 课程设计

2.文档完善,必须包括《项目计划书》、《需求规格说明书》、《系统概要设计》、《系统详细设计》、《系统测试说明书》、《用户手册》、《会议记录》和《项目结项总结》文档。

3.团队中必须具有项目经理、架构师、开发人员、测试人员角色。 【扩充功能】 采用MVC设计模式。

7.2.7 BBS 系统

【设计任务】 开发一个基于Web的 BBS系统,包含一般 BBS所具有的功能,如用户注册、登录、个人信

息管理、发帖/回帖、帖子管理、主题词查询功能;管理员可以封禁指定用户,删除或锁定指定帖子,统计帖子,发布站点公告。 难度:★★★ 推荐指数:★★★

【设计要求】 1.团队合作,3~5人,6~10周时间。 2.文档完善,必须包括《项目计划书》、《需求规格说明书》、《系统概要设计》、《系统详细设

计》、《系统测试说明书》、《用户手册》、《会议记录》和《项目结项总结》文档。 3.团队中必须具有项目经理、架构师、开发人员、测试人员角色。

【扩充功能】 1.利用异步交互技术实现帖子即时更新。 2.支持用户之间的站内信。

7.2.8 教师工资管理系统

【设计任务】 开发一个基于Web的教师工资管理系统,包括教师基本信息管理,考勤信息管理,课程信息

管理(排课、临时调整课程),工资信息管理,工资类别设置和年终福利发放等。 每个教师的基本信息包括教工类别、部门、职称、级别、性别、地址、工作时间、出生

日期、联系电话、政治面貌和教育程度等,其中部分信息可由教师本人修改,部分信息由管

理员修改。 难度:★★★ 推荐指数:★★★

【设计要求】 1.团队合作,3~5人,5~8周时间。 2.文档完善,必须包括《项目计划书》、《需求规格说明书》、《系统概要设计》、《系统详细设

计》、《系统测试说明书》、《用户手册》、《会议记录》和《项目结项总结》文档。 3.团队中必须具有项目经理、架构师、开发人员、测试人员角色。

7.2.9 网上投稿系统

【设计任务】 开发一个基于Web的网上投稿系统,该系统可以接收作者的Word格式电子稿件以及作者的

281

软件工程——理论与实践

注册信息(包括姓名、单位、通信地址、电话号码、E-mail地址等信息),并能供投稿人查询稿件处理情况,以及在稿件处理后(退稿、录用、修改后再审等)发送 E-mail通知投稿人;管理员负责维护作者信息并处理稿件。 难度:★★★ 推荐指数:★★★

【设计要求】 1.团队合作,3~5人,5~8周时间。 2.文档完善,必须包括《项目计划书》、《需求规格说明书》、《系统概要设计》、《系统详细设

计》、《系统测试说明书》、《用户手册》、《会议记录》和《项目结项总结》文档。 3.团队中必须具有项目经理、架构师、开发人员、测试人员角色。

【扩充功能】 作者可以在线预览提交的稿件内容。

7.2.10 学校教材订购系统

开发一个基于 Web 的学校教材订购系统,主要包含销售和采购两个分系统。销售系统的主要工作过程为:由教师和学生提交购书单,经教材发行人员审核后交费用,登记并返回给

教师或学生领书单,在指定的时间内教师或学生可以到书库领书。采购系统的主要工作过程

为:如果教材脱销,则登记缺书,生成缺书单给书库采购人员,新书入库,发通知给教材发

行人员。 难度:★★★ 推荐指数:★★★ 【设计要求】 1.团队合作,3~5人,5~8周时间。 2.文档完善,必须包括《项目计划书》、《需求规格说明书》、《系统概要设计》、《系统详细设

计》、《系统测试说明书》、《用户手册》、《会议记录》和《项目结项总结》文档。 3.团队中必须具有项目经理、架构师、开发人员、测试人员角色。

7.2.11 网上机票订约系统

【设计任务】 开发一个基于 Web 的网上机票订约系统,该系统可以接收用户的订单(指定日期和航班信

息);用户搜索航班信息,查询机票和折扣信息,下订单,然后支付机票;支付成功后,系统返回

给用户订单号,并根据用户订单中的地址把机票邮寄给用户;用户可以通过订单号查询机票当前

状态;管理员负责录入机票和航班信息,统计订单,并可以发布公告。 难度:★★★ 推荐指数:★★

【设计要求】 1.团队合作,3~5人,5~8周时间。 2.文档完善,必须包括《项目计划书》、《需求规格说明书》、《系统概要设计》、《系统详细设

计》、《系统测试说明书》、《用户手册》、《会议记录》和《项目结项总结》文档。 3.团队中必须具有项目经理、架构师、开发人员、测试人员角色。

282

第 7章 课程设计

【扩充功能】 采用MVC设计模式。

7.2.12 网上选课管理系统

【设计任务】 开发一个基于Web的学生网上选课管理系统,包括学生信息维护,学生登录选课(包括必

修课和选修课),课程信息查询(教师、学分、学时、上课时间、上课地点)以及课程成绩查询

功能。 难度:★★ 推荐指数:★★

【设计要求】 1.团队合作,2~4人,3~5周时间。 2.文档完善,必须包括《项目计划书》、《需求规格说明书》、《系统概要设计》、《系统详细设

计》、《系统测试说明书》、《用户手册》、《会议记录》和《项目结项总结》文档。 3.团队中必须具有项目经理、架构师、开发人员、测试人员角色。

7.2.13 远程教学平台

【设计任务】 开发一个基于Web的远程教学平台,学生可以登陆网站选择指定老师的课程,可以在线观看

老师讲课视频以及讲义;管理员负责维护学生信息和老师的课程资料。 难度:★★ 推荐指数:★★

【设计要求】 1.团队合作,2~4人,3~5周时间。 2.文档完善,必须包括《项目计划书》、《需求规格说明书》、《系统概要设计》、《系统详细设

计》、《系统测试说明书》、《用户手册》、《会议记录》和《项目结项总结》文档。 3.团队中必须具有项目经理、架构师、开发人员、测试人员角色。

【扩充功能】 学生可以对老师的课程进行评论。

7.2.14 小型商业网站

【设计任务】 开发一个基于Web的小型商业网站,主要作用是公司简介、产品展示、销售查询、销售排行、

商品管理、公告管理等。 难度:★★ 推荐指数:★★

【设计要求】 1.团队合作,2~3人,3~5周时间。 2.文档完善,必须包括《项目计划书》、《需求规格说明书》、《系统概要设计》、《系统详细设

283

软件工程——理论与实践

计》、《系统测试说明书》、《用户手册》、《会议记录》和《项目结项总结》文档。 3.团队中必须具有项目经理、开发人员、测试人员角色。

7.2.15 小型超市收银系统

【设计任务】 开发一个基于 C/S结构的小型超市收银系统,客户端由收银员输入商品货号以及顾客的会员

卡号(如果是会员),服务器从数据库中读取有关价格和折扣信息以及最终金额,把相关信息返回

给客户端。同时,系统支持商品储量查询以及销售报表。 难度:★★ 推荐指数:★★ 【设计要求】 1.团队合作,2~3人,3~5周时间。 2.文档完善,必须包括《需求规格说明书》、《系统设计说明书》、《系统测试说明书》、《用户

手册》和《项目结项总结》文档。 3.团队中必须具有项目经理、开发人员、测试人员角色。

7.2.16 ATM柜员机模拟程序

开发一个基于 C/S结构的 ATM柜员机模拟程序,用户输入卡号和密码登录系统,可以取款、存款、查询余额、查询历史交易记录、转账和修改密码。 难度:★ 推荐指数:★★

【设计要求】 1.个人/团队合作,1~2人,1~3周时间。 2.文档包括《需求规格说明书》、《系统设计说明书》、《系统测试说明书》和《用户手册》文档。

【扩充功能】 多个客户端同时存取款时保证数据同步。

7.2.17 模拟计算器

【设计任务】 开发一个科学计算器模拟程序,实现通常的科学计算功能,如加减乘除以及平方、开方、对数、

清零等运算。具体功能要求和界面设计参考图 7-1。

图 7-1 模拟计算器参考界面

难度:★ 推荐指数:★★

【设计要求】 1.个人/团队合作,1~2人,1~3周时间。 2.文档包括《需求规格说明书》、《系统设计说明书》、

《系统测试说明书》和《用户手册》文档。

【扩充功能】 实现可用于二进制计算和转换的面向程序员使用的功能。

284

第 7章 课程设计

7.2.18 俄罗斯方块游戏

【设计任务】 实现俄罗斯方块游戏,具体的游戏规则可以自己定义,也可以加入更好的创意。 难度:★ 推荐指数:★★

【设计要求】 1.个人/团队合作,1~2人,1~3周时间。 2.文档包括《需求规格说明书》、《系统设计说明书》、《系统测试说明书》和《用户手册》文档。

7.2.19 通讯录

【设计任务】 开发一个本地应用程序,实现通讯录的功能,包括添加/删除/搜索用户;用户信息包括姓名、

联系方式、家庭住址、生日、类别、公司等信息。 难度:★ 推荐指数:★★

【设计要求】 1.个人/团队合作,1~2人,1~3周时间。 2.文档包括《需求规格说明书》、《系统设计说明书》、《系统测试说明书》和《用户手册》文档。

【扩充功能】 通过网络实现多人的通讯录之间同步、互相导入联系人。

7.2.20 即时通信系统

【设计任务】 开发一个本地即时通信工具,实现功能包括两人或多人之间的即时文字或图片聊天。 难度:★ 推荐指数:★ 【设计要求】 1.个人,1~2周时间。 2.文档包括《需求规格说明书》、《系统设计说明书》、《系统测试说明书》和《用户手册》文档。

【扩充功能】 1.支持语音聊天。 2.支持视频聊天。 3.支持多人语音聊天。 4.支持多人视频聊天。

7.2.21 游戏编程

【设计任务】 设计一个支持多人在线的 C/S结构 2D 或 3D 游戏,具体游戏内容不限;要求具有一定创意和

可玩性。可以基于 OpenGL 或 DirectX,要求学生自己开发视图、场景和音频等模块,不能使用已

285

软件工程——理论与实践

有的游戏引擎。 难度:★★★★★ 推荐指数:★ 【设计要求】 1.团队合作,4~6人,10~15周时间。 2.文档完善,必须包括《项目计划书》、《需求规格说明书》、《系统概要设计》、《系统详细设

计》、《系统测试说明书》、《用户手册》、《会议记录》和《项目结项总结》文档。 3.团队中必须具有项目经理、架构人员、开发人员、测试人员角色。

【扩充功能】 1.游戏具有创意和较高的可玩性。 2.优秀的视觉效果。 3.实现独立的游戏引擎。

7.2.22 高校医院管理信息系统

【设计任务】 高校医院主要为全校教职工、学生、家属提供医疗服务,包括门诊、住院、保健等服务项目。

高校医院管理信息系统应将这些项目有关信息纳入电脑系统统一管理,以便及时获取有关信息,

提高医疗效果和管理效率。 该系统包含以下几个子系统:住院部管理子系统、门诊部管理子系统、中西药房管理子系统、

保健档案管理子系统、公费医疗管理子系统、病情管理子系统、业务管理子系统、人事管理子系

统和系统管理子系统。 难度:★★★★★ 推荐指数:★

【设计要求】 1.团队合作,4~6人,10~15周时间。 2.文档完善,必须包括《项目计划书》、《需求规格说明书》、《系统概要设计》、《系统详细设

计》、《系统测试说明书》、《用户手册》、《会议记录》和《项目结项总结》文档。 3.团队中必须具有项目经理、需求分析人员、架构人员、开发人员、测试人员角色。 4.要求使用版本管理工具(如 TFS、SVN、Git等)辅助开发。

【扩充功能】 1.友好的用户界面,使操作量尽可能降低。 2.良好的可扩展性,可以方便地与其他系统整合。

7.2.23 酒店管理系统

【设计任务】 为实现酒店日常工作的高效管理,弥补人工管理的不足,开发酒店管理系统。酒店经理可以通

过系统掌握整个酒店情况,前台人员可以进行接待和收银工作,财务人员可以进行结账统计和报表

管理等。 系统分为前台和后台,前台的主要功能是接待、预订、收银等;后台主要是管理、统计等。

系统用户登录后,根据相应权限,服务人员可以通过用户界面获取信息、登记客户等;管理人员

286

第 7章 课程设计

可以即时掌握酒店动态,并进行管理。主要包含以下 5个子系统。 用户信息管理系统:主要执行数据库的运行权限管理。 客房标准管理系统:包括客房的编号、类型、面积、最多容纳人数、价格以及客房的硬件设

施,如空调、电视、网络、卫生间等。当添加新的客房时,就添加相应的标准信息,可以随时查

看客房的标准信息,根据需要进行修改和删除等操作。 客房信息管理系统:主要查看客房的入住情况,了解客房的入住率。 订房信息管理系统:酒店客房管理的核心部分,存储订房时的信息,包括登记人姓名、证

件号、登记类型、所选的餐饮标准、押金及入住时间等。这些信息直接关系到后续的结算信息

管理。 结算信息管理系统:结合订房的信息进行自动化结账,并存储结算信息,包括客房定价、

押金、餐饮消费、客房消费、客户类型、结算时间、入住天数、消费总额等,结算完毕就可

以退房。 难度:★★★★★ 推荐指数:★★

【设计要求】 1.团队合作,4~6人,10~15周时间。 2.文档完善,必须包括《项目计划书》、《需求规格说明书》、《系统概要设计》、《系统详细设

计》、《系统测试说明书》、《用户手册》、《会议记录》和《项目结项总结》文档。 3.团队中必须具有项目经理、需求分析人员、架构人员、开发人员、测试人员角色。 4.要求使用版本管理工具(如 TFS、SVN、Git等)辅助开发。

7.2.24 复杂网络环境下的 B/S、C/S 混合系统

【设计任务】 设计一个 B/S、C/S 混合的即时交流系统,具体应用内容不限;服务端既可以通过浏览器直接

访问,也可以通过客户端访问。 通过浏览器访问时,要结合异步交互技术实现即时通信。 客户端不能直接和服务器端通信,必须通过中间代理(代理只需做简单的消息转发即可);所

有用户可以实现即时通信。 难度:★★★★★ 推荐指数:★★

【设计要求】 1.团队合作,4~6人,10~15周时间。 2.文档完善,必须包括《项目计划书》、《需求规格说明书》、《系统概要设计》、《系统详细设

计》、《系统测试说明书》、《用户手册》、《会议记录》和《项目结项总结》文档。 3.团队中必须具有项目经理、架构人员、开发人员、测试人员角色。 4.要求使用版本管理工具(如 TFS、SVN、Git 等)辅助开发。

【扩充功能】 1.所有用户之间支持文件传输,并且显示传输进度。 2.同一个代理支持多客户端用户同时通信。 3.代理软件作为系统服务随代理机器启动而启动。

287

参考文献

[1]张海蕃.软件工程导论[M].北京:清华大学出版社,2004. [2]Roger S Pressman.软件工程:实践者的研究方法[M].第 5版.梅宏译.北京:机械工业出版

社,2002. [3]刘冰,赖函,瞿中,王化晶.软件工程实践教程[M].北京:机械工业出版社,2009. [4]Frederick P.Brooks Jr.人月神话[M].汪颖译.北京:清华大学出版社,2002. [5]赵池龙,杨林,孙伟.实用软件工程[M].第 2版.北京:电子工业出版社,2006. [6]韩万江.软件工程案例教程[M].北京:机械工业出版社,2007. [7]Robert L.Glass.软件工程的事实与廖误[M].严亚军,龚波译.北京:中国电力出版社,2005. [8]钱乐秋,赵文耘,牛军玉.软件工程[M].北京:清华大学出版社,2007. [9]孙家广,刘强.软件工程—理论、方法与实践.北京:高等教育出版社,2005. [10]王钧.极限编程实践.北京:人民邮电出版社,2002. [11]Bermd Bruegge,Allen H.Dutoite,面向对象软件工程:使用 UML、模式与 Java.叶俊民,

汪望珠译.北京:清华大学出版社,2006. [12]王忠群.软件工程[M].北京:中国科技大学出版社,2009. [13](美)埃里克森(Eriksson,H.E.)等.UML2 工具箱[M].余安萍译.北京:电了工业出版

社,2004. [14]郑人杰,马素霞,麻志毅.软件工程[M].北京:人民邮电出版社,2009. [15]Simone Chiaretta,Keyvan Nayyeri.ASP.NET MVC 1.0入门经典.王德才等译.北京:清华

大学出版社,2011. [16]Rob Conery等.ASP .NET MVC 1.0主级编程.冯飞译.北京:清华大学出版社,2010. [17]上海艾微软件技术有限公司主编.软件测试技术概论.北京:清华大学出版社,2004. [18]黄军,刘晓梅,熊勇.软件配置管理及其工具应用[M].北京:人民邮电出版社,2002. [19]康一梅.软件项目管理.北京:清华大学出版社,2010. [20]吕云翔,王洋,王昕鹏.软件工程实用教程[M].北京:机械工业出版社,2010. [21]吕云翔,刘浩,王昕鹏,周建等.软件工程课程设计.北京:机械工业出版社,2009. [22]SWEBOK,IEEE-2004 Version.

288

21世纪高等学校计算机规划教材

封面设计:董志桢

教材服务热线:010-67170985

反馈 / 投稿 / 推荐信箱:[email protected]

人民邮电出版社教学服务与资源网:www.ptpedu.com.cn

免费提供PPT等教学相关资料

人民邮电出版社

教学服务与资源网

软件工程——理论与实践

Theory and Practice of Software Engineering

■ 完善的理论和充分实践的有机结合

■ 实际的案例贯穿软件开发的各过程

■ 丰富的软件工程课程设计可选题目

吕云翔 王昕鹏 邱玉龙 编著

Theory and Practice of Software Engineering

精品系列

软件工程—

理论与实践

21st Century University Planned Textbooks of Computer Science

21世纪高等学校计算机规划教材

这是一本理论与实践并重的实用软件工程教材,书中不仅介绍了与软件工程相关的基本概念、方法和原理,而且还在此

基础上讲述了可以实际用于软件开发实践的各种技能。各章分为“理论部分”和“实践部分”。“理论部分”组织合理、

切中要点、详略得当;“实践部分”贴近实际,以具体的一个完整案例(贯穿全文)为示范,指导读者利用相关的工具

对所学内容进行具体的运用。此外,还有多个软件工程课程设计题目可供选择,配合丰富的习题,可帮助读者检验各章

的学习效果。

本书旨在使读者在有限的课时内,不仅能对软件工程的原理有所认识,而且能够具备实际的软件开发技能,并且可以熟

练地使用相关的软件工程工具,学会按照标准和规范编写文档等。

软件工程——理论与实践

本教材的结构框图

软件工程理论与实践

其他相关内容

软件工程的其他相关内容

综合实践

课程设计

理论概述

软件工程概述

可行性及需求

可行性研究及需求分析

设计实现及测试

软件测试

软件设计

编码及实现

精品-FM28228软件工程——理论与实践.indd 1 12-6-21 下午1:47