5. 软件工程基础知识
1 软件工程
为了解决软件危机,1968、1969 年北约连续召开了两次会议,提出了软件工程的概念。
1.1 软件工程定义
- 软件工程定义:运用现代科学技术来设计并构造出计算机程序及为开发、运行和维护这些程序所必须的相关文件资料。
- IEEE 定义:0 种系统化的、严格约束的、可量化的方法应用于软件的开发、运行和维护。
- Fritz Bauer 定义:在 NATO 会议上给出的定义,建立并使用完善的工程化原则,以较经济的手段获得能在实际机器上有效运行的可靠软件的一系列方法。
1.2 软件过程模型
- 瀑布模型(Waterfall Model):最早使用的软件过程模型之一,包含一系列活动。这些活动从一个阶段到另一个阶段逐次下降,它的工流程在形式上很像瀑布,因此被称为瀑布模型。
- 特点:阶段间有明确的界限,前一阶段的输出是后一阶段的输入,每个阶段工作完成后才能进入下一阶段。
- 原型模型(Prototype Model):又称快速原型,用于解决早期需求不明确的问题。该模型包括两个阶段。
- 阶段:原型开发阶段、软件开发阶段。
- 螺旋模型(Spiral Model):在快速原型的基础上扩展而成,也有人把螺旋模型归到快速原型。该模型把整个软件开发流程分成多个段,每个阶段都由部分迭代组成。
- 阶段:需求分析、风险分析、工程实施、计划。
1.3 敏捷模型
1.3.1 敏捷方法的特点
- 适应性(Adaptive)而非预测性(Predictive)
- 适应变化的需求,利用变化来发展
- 面向人(People-oriented)而非面向过程(Process-oriented)
- 强调软件开发过程中人的作用
1.3.2 敏捷方法的核心思想
- 适应型而非可预测型
- 以人为本而非以过程为本
- 迭代增量式开发
1.3.3 主要敏捷方法简介
- 极限编程(XP)
- 强调交流、反馈和勇气,简化开发过程
- 水晶系列方法
- 发展一种快速、机动性的方法
- Scrum
- 迭代式增量软件开发过程。强调项目管理,包含一系列实践和预定义角色
- 特征驱动开发(FDD)
- 迭代的开发模型,强调人、过程和技术
1.4 统一过程模型 (RUP)
1.4.1 RUP 的生命周期
- RUP 是二维的软件开发模型,包含 9 个核心工作流。
- 核心工作流包括:
- 业务建模(Business Modeling)
- 需求(Requirements)
- 分析与设计(Analysis & Design)
- 实现(Implementation)
- 测试(Test)
- 部署(Deployment)
- 配置与变更管理(Configuration & Change Management)
- 项目管理(Project Management)
- 环境(Environment)
RUP 把软件开发生命周期划分为多个循环 (Cycle), 每个循环生成产品的一个新的版本,每个循环依次由 4 个连续的阶段 (Phase) 组成,每个阶段完成确定的任务。每一个阶段都由一个或多个连续的迭代 (Iteration) 组成。
1.4.2 RUP 中的核心概念
- 角色(Role):描述参与 RUP 的人员或小组的行为与职责。
- 例如:体系结构师(Architect)、设计人员(Designer)、实现人员(Implementer)、测试员(tester)和配置管理人员(Configuration Manager)。
- 工件(Artifact):开发过程中产生的产品、工作等。
- 活动(Activity):活动是一个有明确目的的独立工作单元。
- 制品(Artifact):制品是活动生成、创建或修改的一段信息。
RUP 2003 还有其他一些基本概念,如工具教程 (ToolMentor)、 检查点 (Checkpoints)、 模板 (Template) 和报告 (Report) 等。
1.4.3 RUP 的特点
- 用例驱动:开发活动以用例为中心。
- 以体系结构为中心:设计和代码设计不依赖于具体编程语言。
- 迭代与增量:采用迭代和增量的方式开发软件。
1.5 软件能力成熟度模型
- 软件能力成熟度模型(CMM)是一个概念模型,用于指导软件开发过程的改进和评估。
- CMMI 是 CMM 的发展,由美国卡耐基梅隆大学软件工程研究所(SEI)组织开发。
- CMMI 将软件过程改进的步骤组织成 5 个成熟度等级,包含 18 个关键过程域,52 个过程目标,3168 种关键时间。
- CMMI 的成熟度等级
- Level 1 初始级
- 过程通常是随意且混乱的,依赖个人能力。
- Level 2 已管理级
- 组织确保策划、文档化、执行、监督和控制项目级的过程。
- Level 3 已定义级
- 企业根据自身情况定义适合的标准流程,并制度化。
- Level 4 量化管理级
- 组织建立了产品质量、服务质量以及过程性能的定量目标。
- Level 5 优化级
- 项目管理达到最高境界,关注通过增量式的与创新式的过程与技术改进,不断改进过程性能。
- Level 1 初始级
- CMMI 的成熟度等级
2 需求工程
软件需求包括 3 个不同的层次:业务需求、用户需求和功能需求(也包括非功能需求)。
- 业务需求 (business requirement) 反映了组织机构或客户对系统、产品高层次的目标要求。
- 用户需求 (user requirement) 描述了用户使用产品必须要完成的任务,是用户对该软件产品的期望。这两种构成了用户原始需求文档的内容。
- 功能需求 (functional requirement) 定义了开发人员必须实现的软件功能,使得用户能完成他们的任务,从而满足业务需求。
需求工程的活动主要被划分为以下几个阶段。
- 需求获取:通过与用户的交流,对现有系统的观察及对任务进行分析,从而开发、捕获和修订用户的需求。
- 需求分析:对获取的需求进行整理和总结,确定对软件系统的综合要求。
- 形成需求规格(或称之为需求文档化):按照相关标准,生成需求模型的文档描述,用户原始需求书作为用户和开发者之间的一个协约,往往被作为合同的附件;软件需求描述规约作为后续软件系统开发的指南。
- 需求确认与验证:以需求规格说明为输入,通过用户确认、复审会议、符号执行、模拟仿真或快速原型等途径与方法,确认和验证需求规格的完整性、正确性、一致性、可测试性和可行性,包含有效性检查、一致性检查、可行性检查和确认可验证性。
- 需求管理:包括需求文档的追踪管理、变更控制、版本控制等管理性活动。
需求管理的主要活动
需求管理是一个对系统需求变更、了解和控制的过程。需求管理过程与需求开发过程相互关联,当初始需求导出的同时就启动了需求管理规划,一旦形成了需求文档的初稿,需求管理活动就开始了。
- 变更控制
- 版本控制
- 需求跟踪
- 需求状态跟踪
2.1 需求获取
- 定义:获取用户需求并将其转化为软件需求的过程。
- 目标:确保软件产品满足用户需求。
2.1.1 需求获取的基本步骤
- 开发高层的业务模型
- 定义项目范围和高层需求
- 识别用户角色和用户代表
- 获取具体的需求
- 确定目标系统的业务工作流
- 需求整理与总结
2.1.2 需求获取方法
- 用户访谈:通过与用户交谈获取需求。
- 需求专题讨论会:通过讨论会获取需求。
- 问卷调查:通过问卷获取需求。
- 现场观察:通过观察用户实际操作获取需求。
- 原型化方法:通过原型获取需求。
- 头脑风暴法:参会者敞开思想使各种设想在相互碰撞中激起大脑的创造性风暴
2.2 需求变更
需求变更概述
- 需求变更在软件开发过程中已成为常态。
- 原因:需求获取不完整、理解错误、业务变化等。
- 影响:可能导致项目混乱,影响进度和质量。
2.2.1 需求变更控制过程
- 识别出问题
- 问题分析和变更描述
- 变更分析和成本计算
- 变更实现
- 修改后的需求
2.2.2 需求变更控制委员会
- 定义:项目所有者权益代表,负责决定接受哪些变更。
- 组成:用户和实施方的决策人员。
- 职责:评审变更请求,决定是否变更。
变更控制委员会的代表
- 产品或计划管理部门
- 项目管理部门
- 开发部门
- 测试或质量保证部门
- 市场部或客户代表
- 制作用户文档的部门
- 技术支持部门
- 帮助或用户支持热线部门
- 配置管理部门
变更决策过程
- 制定决策
- 描述确认
- 出席人数
- 决策方法
- 主席决策
- 交流情况
- 重新协商约定
2.3 需求追踪
- 内容:包括编制每个需求同系统元素之间的联系文档。
- 目的:建立与维护“需求-设计-编程-测试”之间的一致性。确保需求从提出到实现的整个过程中保持一致性和可追溯性的过程。确保所有的工作成果符合用户需求。有利于确认和评估实现某个建议的需求变更所必须的工作。
追踪方式
- 正向追踪
- 检查《产品需求规格说明书》中的每个需求是否都能在后续工作成果中找到对应点。
- 逆向追踪
- 检查设计文档、代码、测试用例等工作成果是否都能在《产品需求规格说明书》中找到出处。
正向追踪和逆向追踪合称为“双向追踪”。需求跟踪矩阵保存了需求与后续工作成果的对应关系。
重要性
- 需求追踪是优秀需求规格说明书的一个特征。
- 为了实现可跟踪能力,必须统一地标识出每一个需求,以便能明确地进行查阅。
- 需求追踪是确保需求与实际一致的重要手段,有助于确认和评估实现某个建议的需求变更所必须的工作。
3 系统分析与设计
- 系统分析
- 该阶段是应用系统思想和方法,把复杂的对象分解为简单的组成部分,找出这些部分的基本属性和彼此之间的关系的过程
- 基本任务是系统分析师和用户在充分了解用户需求的基础上,把双方对新系统的理解表达为。
- 输出:系统需求规格说明书
- 系统设计
- 主要内容包括概要设计和详细设计。
- 目标是根据系统分析的结果,完成系统的构建过程。
- 主要目的是绘制系统的蓝图,权衡和比较各种技术和实施方法的利弊,合理分配各种资源,构建新系统的详细设计方案和相关模型,指导系统实施工作的顺利开展。
3.1 结构化方法
3.1.1 结构化分析
- 结构化分析方法:帮助系统分析人员产生功能模型的原型与技术。
- 常用手段:数据流图(DFD)和数据字典等。
结构化分析的步骤如下:
- 分析业务情况,做出反映当前物理模型的数据流图 (Data Flow Diagram,DFD);
- 推导出等价的逻辑模型的 DFD;
- 设计新的逻辑系统,生成数据字典和基元描述;
- 建立人机接口,提出可供选择的目标系统物理模型的 DFD;
- 确定各种方案的成本和风险等级,据此对各种方案进行分析;
- 选择一种方案;
- 建立完整的需求规约。
数据流图(DFD)
- 功能需求:描述过程建模和功能建模方法。
- 数据流图:表示数据流的流向,箭头上标注的内容可以是信息说明或数据流。
- 处理(Process):对数据进行的加工转换。
- 外部项:为系统提供数据或接收数据的实体。
- 数据存储:数据存储是数据结构中的数据项说明。
数据字典
- 数据字典:对数据流图中数据项、数据流、数据存储、处理逻辑等进行定义。
- 目的:描述数据的信息。
3.1.2 结构化设计
- 结构化设计(Structured Design, SD)是一种面向数据流的设计方法。
- 以数据流图和数据字典为基础,自顶向下、逐步求精。
- 目标:将软件系统划分为若干功能模块,各模块独立开发。
3.1.2.1 模块化设计
- 模块:实现特定功能的程序单元。
- 特点:独立性、可组合性、可分解性。
模块结构
- 模块:实现特定功能的程序单元。
- 模块化:将系统划分为模块,模块间通过接口联系。
- 内聚:模块内部各组成部分之间联系的紧密程度。
- 耦合:模块之间相互依赖的程度。
模块的内聚类型
- 功能内聚:完成单一功能。
- 顺序内聚:处理元素相关。
- 通信内聚:处理元素集中。
- 过程内聚:处理元素相关。
- 逻辑内聚:完成逻辑任务。
- 偶然内聚:完成无关任务。
模块的耦合类型
- 非直接耦合:无直接联系。
- 数据耦合:通过参数传递。
- 标记耦合:通过数据结构。
- 控制耦合:通过控制信息。
- 公共耦合:共享公共数据。
- 内容耦合:直接访问内部数据。
3.1.2.2 系统结构图
- 系统结构图(Structure Chart, SC):反映系统功能实现和模块间联系。
- 详细设计:设计每个模块的实现算法和数据结构。
详细设计,应该完成详细设计文档,主要是模块的详细设计方案说明。设计的基本步骤如下。
- 分析并确定输入/输出数据的逻辑结构。
- 找出输入数据结构和输出数据结构中有对应关系的数据单元。
- 按一定的规则由输入、输出的数据结构导出程序结构。
- 列出基本操作与条件,并把它们分配到程序结构图的适当位置。
- 用伪码写出程序。详细设计的表示工具有图形工具、表格工具和语言工具。
3.1.3 结构化编程
结构化编程概述
- 结构化程序设计(Structured Programming, SP)由 E.W. Dijkstra 在 1965 年提出。
- 强调程序的结构性,易于理解。
- 采用自顶向下、逐步求精的设计方法。
- 通过“顺序、选择、循环”三种基本控制结构进行连接。
结构化程序设计原则
- 结构化程序设计的原则可表示为:程序 = (算法) + (数据结构)。
- 算法和数据结构是独立的整体,分开设计。
- 原则:自顶向下、逐步细化;清晰第一,效率第二;书写规范,缩进格式;基本结构,组合而成。
3.1.4 数据库设计
数据库设计是指根据用户的需求,在某一具体的数据库管理系统上,设计数据库的结构和建立数据库的过程。
数据库设计的内容包括:需求分析、概念结构设计、逻辑结构设计、物理结构设计、数据库的实施和数据库的运行和维护。
- 概念结构设计:建立实体-联系图(ER 图)。
- 逻辑结构设计:将ER图转换为逻辑模型。
- 物理结构设计:数据库的存储结构和存取方法。
E-R 图的基本作图步骤如下:
- 确定所有的实体集合。
- 选择每个实体集应该包含的属性。
- 确定实体集之间的联系。
- 确定实体集的关键字,用下画线在属性上表明关键字的属性组合。
- 确定联系的类型,在用线将表示联系的菱形框联系到实体集时,在线旁注明是 1 或 n 来表示联系的类型。
3.2 面向对象方法
- 面向对象:以对象为中心,强调对象之间的交互。
- 优点:提高软件重用性,简化软件开发过程。
3.2.1 面向对象分析
- 面向对象分析(Object-Oriented Analysis, OOA)是在系统开发过程中进行系统分析和业务建模的方法。
- 强调从现实世界中的事物及其关系出发,建立“对象”概念基础的方法学。
- 0-0 A 模型包含 5 个层次:主题层、对象类层、结构层、属性层和服务层。
- 5 个活动:标识对象类、标识结构、定义主题、定义属性和定义服务。
3.2.2 面向对象设计
- 面向对象设计(Object-Oriented Design, OOD)是 OOA 方法的延续。
- 基本思想包括抽象、封装和可扩展性。
- 类和对象是 OOD 方法中最重要的组成部分。
- 类可以分为 3 种类型:实体类、控制类和边界类。
3.2.3 面向对象编程
- 面向对象编程设计(Object Oriented Programming, OOP)是 OOD 方法的实现。
- 基本原则:封装、继承和多态。
- 封装:隐藏对象的内部状态和行为,只暴露必要的接口。
- 继承:允许新创建的类(子类)继承现有类(父类)的属性和方法。
- 多态:允许不同类的对象对同一消息做出不同的响应。
3.2.4 数据持久化与数据库
- 数据持久化:将内存中的对象保存到数据库或文件中,以便长期保存。
- 持久化技术:Hibernate、iBatis 和 JDO 等。
- Hibernate:一个开源的对象关系映射框架,简化了数据库操作。
- 特点:自动生成 SQL 语句,支持自动映射,减轻开发负担。
- iBatis:轻量级持久化解决方案,易于上手。
- 特点:简单灵活,适合小型项目。
- JDO(Java Data Object):SUN 公司制定的对象持久化标准。
- 特点:透明对象存储,灵活适用于各种数据库。
- Hibernate:一个开源的对象关系映射框架,简化了数据库操作。
4 软件测试
- 定义:使用人工或自动的手段来运行或测定某个软件系统的过程
- 目的:确保软件的质量、确认软件以正确的方式做了用户所期望的事情,
- 意义:是要确保软件的质量,还要给开发人员提供信息,以方便其为风险评估做相应的准备,重要的是软件测试要贯穿在整个软件开发的过程中,保证整个软件开发的过程是高质量的。
4.1 测试方法
软件测试方法的分类有很多种。以测试过程中程序执行状态为依据可分为静态测试 (StaticTesting,ST) 和动态测试 (Dynamic Testing,DT); 以具体实现算法细节和系统内部结构的相关情况为根据可分黑盒测试、白盒测试和灰盒测试 3 类。
- 软件测试方法分为静态测试和动态测试:
- 静态测试:不运行程序,通过分析或检查源程序的语句、结构、过程等来检查程序是否有错误。
- 动态测试:通过运行被测试程序,对得到的运行结果与预期的结果进行比较分析,以分析运行效率和健壮性。
- 动态测试包括:
- 黑盒测试:不考虑程序内部结构和特性,根据需求规格说明书设计测试用例。
- 白盒测试:根据程序内部逻辑和相关信息,通过检查每一条通路是否正确工作。
- 灰盒测试:介于黑盒与白盒测试之间,既考虑程序内部逻辑,也考虑输入输出的正确性。
从程序执行的方式来分类,可分为人工测试 (Manual Testing,MT) 和自动化测试 (Automatic Testing,AT)。
- 自动化测试:软件测试的自动化,在预先设定的条件下自动运行被测程序,并分析运行结果。
4.2 测试阶段
4.2.1 按阶段划分
- 单元测试:针对软件的最小可测试单元进行测试,检查逻辑结构是否合理,模块独立路径是否正常。
- 集成测试:对已经严格按照程序设计文档组装起来的模块进行测试,确认程序结构的正确性,发现和接口有关的问题。
- 系统测试:通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试。
- 功能测试
- 性能测试:通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试。
- 负载测试
- 压力测试
- 压力测试等
- 验收测试:最后一个阶段的测试,是软件产品投入正式交付前的工作。
4.2.2 其他测试
- AB 测试:为 Web 或 App 界面或流程制作两个(A/B)或多个(A/B/n)版本,在同一时间维度,分别让组成成分相同(相似)的访客群组(目标人群)随机的访问这些版本,收集各群组的用户体验数据和业务数据,最后分析、评估出最好版本,正式采用。
- Web 测试:软件测试的一部分,针对 Web 应用的一类测试。
- 链接测试:Web 应用系统中的一个重要部分,测试所有链接是否按预期工作。
5 净室软件工程
5.1 理论基础
净室软件工程的理论基础主要是函数理论和抽样理论。
- 函数理论:定义域到值域的映射,强调完备性和一致性。
- 抽样理论:通过统计手段对软件的所有可能使用情况进行抽样测试。
5.2 技术手段
净室软件工程中应用的技术手段主要有以下 4 种:
- 统计过程控制下的增量式开发(Incremental Development)
- 增量开发:将整个开发过程划分为一系列较小的累积增量。
- 基于函数的规范与设计
- 行为视图、有限状态机视图和过程视图:规范从外部行为视图开始,逐步细化。
- 正确性验证
- 正确性验证:确保软件行为符合预期。
- 统计测试(Statistically Based Testing)和软件认证
- 统计测试:通过抽样方法评估系统性能。
5.3 应用与缺点
5.5.3 应用与缺点
- 应用
- 净室软件工程方法在多个大型项目中得到应用,如 IBM 的海量存储控制器项目、NASA 的地面控制软件系统项目等。
- 这些项目通过净室方法的开发,提高了软件的质量和生产力。
- 缺点
- CSE 理论化,需要更多数学知识,验证步骤困难且耗时。
- CSE 开发小组不进行传统模块测试,可能导致未预期的错误。
- CSE 脱胎于传统软件工程,不可避免地带有传统软件工程的一些弊端。
6 基于构件的软件工程
6.1 构件和构件模型
- 构件:独立的软件单元,可与其他构件构成软件系统。
- 构件特征:
- 可组装性
- 可部署性:独立运行,提供外部访问。
- 文档化
- 独立性
- 标准化:符合标准。
- 构件模型:Web Services 模型、EJB 模型、.NET 模型。
6.2 CBSE 过程
- CBSE 过程:支持基于构件的软件开发过程。
- 主要活动:
- 系统需求概览;
- 识别候选构件;
- 根据发现的构件修改需求;
- 体系结构设计;
- 构件定制与适配;
- 组装构件,创建系统
6.3 构件组装
构件组装是指构件相互直接集成或是用专门编写的“胶水代码”将它们整合在一起来创造一个系统或另一个构件的过程。
常见的组装构件有以下 3 种组装方式。
- 顺序组装:调用已有构件。
- 层次组装:调用构件提供的服务。
- 叠加组装:创建新构件,合并功能。
7 软件项目管理
7.1 项目管理概述
- 软件项目管理:确保软件项目按预定成本、进度、质量顺利完成。
- 目标:对软件进度、配置、质量和风险进行管理。
7.2 软件进度管理
- 进度管理:确保项目按期完成。
- 活动:活动定义、活动排序、活动资源估计、活动历时估计、制定进度计划和进度控制。
7.2.1 工作分解结构(WBS)
- WBS:将项目分解为可管理的子任务。以可交付成果为导向,对项目要素进行的分组,它归纳和定义了项目的整个工作范围,每下降一层
代表对项目工作的更详细定义。 - 原则:不遗漏、不重叠、不超过 6 级。
7.2.2 任务活动图
经过工作分解之后,会得到一组活动任务,这是需要对每个活动进行定义,并确定活动之间的关系。
- 任务活动定义:为完成项目交付成果所必须进行的具体活动。
- 目的:明确每个活动的前驱、持续时间、必须完成日期和交付成果。
活动要素
- 前驱:活动开始前必须发生的事件或事件集。
- 持续时间:活动完成所需的时间长度(天或周)。
- 必须完成日期:活动必须完成的具体日期。
- 里程碑:判断活动完成的条件。
任务活动图的作用
- 项目管理:任务活动图是项目进度管理、成本管理的基础。
- 进度控制:帮助识别关键路径,优化项目进度。
甘特图
- 项目管理工具:甘特图用于展示和管理项目活动。
- 特点:直观展示活动顺序和依赖关系。
7.3 软件配置管理
- 配置管理:控制软件变更,确保变更有序进行。
- 活动:版本控制、变更控制。
7.4 软件质量管理
7.4.1 软件质量保证
- 软件质量保证(SQA):建立系统方法,确保软件符合标准和需求。
- 目标:预防缺陷、避免缺陷、确保软件质量。
- 活动:事前预防、SQA 审计、SQA 报告、处理不符合问题。
7.4.2 软件质量认证
- 认证:评估软件质量,确保符合标准。
- ISO 9000:能力成熟度模型。
- CMM:能力成熟度模型。
7.5 软件风险管理
- 风险管理:识别和控制软件开发风险。
- 目标:减少风险对项目的影响。
- 活动:风险估计和和风险控制。