1.1 软件的概念与特点
-
软件概念定义
- 软件=程序+数据+文档
- 程序:按照事先设计的功能和性能需求执行的指令序列
- 数据:是程序能正常操纵信息的数据结构
- 文档:与程序开发、维护和使用有关的图文材料
-
软件的特征
- 软件是设计开发的或者是工程化的,并不是制造的
- 软件开发时间和工作量难以估计
- 软件会多次修改
- 软件的开发进度几乎没有客观衡量标准
- 软件测试非常困难
- 软件不会磨损和老化
- 软件维护容易产生新的问题
-
按软件的功能进行划分
- 系统软件:服务于其他程序的程序
- 应用软件:解决特定需要的独立应用程序
- 支撑软件:支持其他软件的编制和维护的软件
-
软件发展阶段
-
软件发展迅速的原因
- 计算需求:软件必须适应新的计算环境或技术
- 业务需求:软件必须改善,以实现新的业务需求
- 嵌入需求:软件必须扩展,以满足和新一代系统或数据库之间的互操作性
- 架构需求:软件必须重新设计,使其在新的网络环境是可用的
- 软件危机:在计算机软件的开发和维护过程中所遇到的一系列严重问题
-
产生软件危机的原因
- 客观:逻辑部件,规模庞大
- 主观:忽视需求分析,错误认为软件开发=程序编写,轻视软件维护
- 消除软件危机的途径:软件工程
1.1 软件工程概述
软件过程模型
-
软件工程的定义
- 应用系统化的、学科化的、定量的方法,来开发、运行和维护软件,即将工程应用到软件
- 对上述中各种方法的研究。
-
软件工程三要素
-
工具,为软件工程的过程和方法提供自动化或半自动化的工具支持
- 方法,是完成软件工程项目的技术手段
- 过程,贯穿软件开发的各个环节,在各环节之间建立里程碑
-
-
软件工程四个阶段
-
第一代软件工程 — 传统的软件工程
-
第二代软件工程 — 对象工程
-
第三代软件工程 — 过程工程
-
第四代软件工程 — 构件工程
-
-
软件工程与计算机科学
-
易错点
- 构成软件工程基础的是
过程 - 软件交付形式不是可执行软件。
- 与硬件比较,
软件会退化 - 软件是
设计开发的 - 软件危机是
软件开发和维护中出现的一系列问题 - 软件工程重要原则是
软件可以提供价值 -
软工与计科的区别错误描述:
软件工程对于某一特定问题的正确解决方法将永远不会改变 - 软件是
具有技术和文化的双重属性 - 支持软件工程的根基在于
质量关注点
- 构成软件工程基础的是
2.1 软件过程的概念
-
软件生命周期定义
-
软件产品或软件系统从设计、投入使用到被淘汰的全过程
-
软件过程定义
- 是在工作产品构建过程中,所需完成的活动、动作和任务的集合
- 活动:主要实现宽泛的目标
- 动作:主要工作产品生产过程中的一系列任务
- 任务:关注小而明确的目标,能够产生实际产品
-
软件过程模型定义
- 是软件开发全部过程、活动和任务的结构框架
- 它能直观表达软件开发全过程,明确规定要完成的主要活动、任务和开发策略。
-
能力成熟度模型(CMM)
级别 项目标准 对应进度 初始级 工作无序,缺乏健全的管理制度 有能力的人和个人英雄主义 可重复级 管理制度化,建立了基本的管理制度和规程,初步实现标准化 基本的项目管理 已定义级 过程标准化,工作和管理工作,均已实现标准化、文档化 过程标准化 量化管理级 产品和过程已建立了定量的质量目标。开发活动中的生产率和质量是可度量的。 量化管理 优化级 持续的过程改进,拥有防止出现缺陷、识别薄弱环节以及加以改进的手段 持续的过程改进
2.2 常见软件过程模型
-
模型图
-
定义
- 软件开发过程与软件生命周期是一致的。
- 规定了各项软件工程活动,以及它们自上而下,相互衔接的固定次序,如同瀑布流水,逐级下落。
- 也称经典生命周期模型,是第一个软件过程模型
-
特点
- 以文档为驱动
- 线性模型
- 推迟实现的观点
-
缺点
- 增加工作量:各个阶段的划分完全固定,阶段之间产生大量的文档,极大的增加了工作量。
- 开发风险大:由于开发模型是线性的,用户只有等到整个过程的末期才能见到开发成果,从而增加了开发的风险。
- 早期错误发现晚:早期的错误可能要等到开发后期的测试阶段才能发现,进而带来严重的后果。
- 不适应需求变化:不能反映实际的开发方式,软件开发需要迭代;无法适应需求不明确和需求的变化。
-
适用场合
- 系统需求明确且稳定、技术成熟、工程管理较严格的场合。
- 军工、航天、医疗。
-
模型图
-
定义:瀑布模型的变种。
-
模型图
-
原型定义
- 一个部分开发的产品,使客户和开发人员能够对计划开发的系统的相关方面进行检查。
-
目的
- 明确并完善需求
- 研究技术选择方案
-
结果
- 抛弃原型
- 把原型发展成最终产品
-
优点
- 减少需求不明确带来的风险
-
缺点
- 构造原型采用的技术和工具不一定主流
- 快速建立起来的系统加上连续的修改可能导致原型质量低下
- 设计者在质量和原型中进行折中
- 客户意识不到一些质量问题
-
适用场合
- 客户定义一个总体目标集,但是他们并不清楚系统的具体输入输出
- 开发者不确定算法的效率、软件与操作系统是否兼容以及客户与计算机交互的方式
-
模型图
-
增量定义
- 满足用户需求的一个子集,能够完成一定功能、小而可用的软件。
-
增量定义
-
特点
- 一种非整体开发的模型,是一种进化式的开发过程
- 从部分需求出发,先建立一个不完整的系统,通过测试运行这个系统取得经验和反馈,进一步使系统扩充和完善
- 如此反复进行,直至软件人员和用户对所设计的软件系统满意为止
- 结合了原型模型的基本要素和迭代的特征,采用了基于时间的线性序列,每个线性序列都会输出该软件的一个增量
- 每个增量的开发可用瀑布或快速原型模型
-
优点
- 增量概念的引入,不需要提供完整的需求,只要有一个增量出现,开发就可以进行;
- 软件能够更早投入市场;
- 开放式体系结构,便于维护;
- 在项目的初始阶段不需要投入太多的人力资源;
- 产品逐步交付,软件开发能够较好地适应需求的变化;
- 能够看到软件中间产品,提出改进意见,减少返工,降低开发风险。
-
缺点
- 每个增量必须提供一些系统功能,这使得开发者很难根据客户需求给出大小适合的增量;
- 软件必须具备开放式体系结构;
- 易退化成边做边改的方式,使软件过程控制失去整体性。
-
适用场合
- 适用于软件开发中需求可能发生变化、具有较大风险或者希望尽早进入市场的项目
-
模型图
-
定义
- 把开发活动和风险管理结合起来控制风险。
-
特点
- 开发过程分成若干次迭代,每次迭代代表开发的一个阶段,对应模型中的一条环线
-
优点
- 强调原型的可扩展性和可修改性,原型的进化贯穿整个软件生存周期,这将有助于目标软件的适应能力,支持用户需求的动态变化;
- 原型可看作可执行的需求规格说明,易于为用户和开发人员共同理解,还可作为继续开发的基础,并为用户参与所有关键决策提供了方便;
- 螺旋模型为项目管理人员及时调整管理决策提供了方便,进而可降低开发风险。
-
缺点
- 如果每次迭代的效率不高,致使迭代次数过多,将会增加成本并推迟交付时间;
- 使用该模型需要有相当丰富的风险评估经验和专业知识,要求开发队伍水平较高,否则会带来更大风险。
-
适用场合
- 适用于需求不明确或者需求可能发生变化的大型复杂的软件系统
- 支持面向过程、面向对象等多种开发方法,是一种具有广阔前景的模型
-
定义
- 以用户需求为动力,以对象为驱动的模型。
-
特点
- 主要用于描述面向对象的软件开发过程
- 各个阶段使用统一的概念和表示方法,生命周期各阶段无缝连接
- 各个开发步骤多次反复迭代
-
优点
- 喷泉模型的各个阶段没有明显的界限,开发人员可以同步进行开发,可以提高软件项目开发效率,节省开发时间;
- 适应于面向对象的软件开发过程。
-
缺点
- 由于喷泉模型在各个开发阶段是重叠的,在开发过程中需要大量的开发人员,因此不利于项目的管理;
- 要求严格管理文档,使得审核的难度加大,尤其是面对可能随时加入的各种信息、需求与资料的情况。
-
适用场合
- 适用于面向对象开发
-
模型图
-
定义
-
一种专用的软件过程,需要使用构件开发方法。
-
特点
-
考虑的焦点是集成,而非实现
-
开发的四个阶段
- 需求分析阶段
- 构件分析阶段
- 系统设计阶段
- 开发集成阶段
-
优点
- 软件复用思想;
- 降低开发成本和风险,加快开发进度,提高软件质量。
-
缺点
- 模型复杂;
- 商业构件不能修改,会导致修改需求,进而导致系统不能完全符合客户需求;
- 无法完全控制所开发系统的演化;
- 项目划分的好坏直接影响项目结果的好坏。
-
适用场合
- 适用于系统之间有共性的情况
-
定义
- 基于面向对象分析和设计方法的软件过程。
-
特点
- 完整且完美
- 基于面向对象方法学
- 使用统一建模语言UML
-
观察软件开发过程的三个视角
- 动态视角:随时间变化的各个阶段
- 静态视角:所进行的活动
- 实践视角:可采用的良好实践建议
-
四个阶段
- 初始:项目计划、评估风险
- 精化:设计系统的体系结构、制定项目计划、确定资源需求
- 构建:开发出所有组件和应用程序,集成并进行详尽测试
- 产品化:将产品移交给用户
-
模型图
-
定义
-
基本原理和开发准则的结合。
-
优点
- 快速响应变化和不确定性;
- 可持续开发速度;
- 适应商业竞争环境下的有限资源和有限时间。
-
缺点
- 测试驱动开发可能导致通过测试但非用户期望;
- 重构而不降低质量尤其困难。
-
适用场合
- 适用于需求模糊且经常改变的场合;
- 适合商业竞争环境下的项目。
2.3 选择过程模型
- 前期需求明确的情况下,尽量采用瀑布模型
- 用户无系统使用经验,需求分析人员技能不足的情况下,尽量借助原型模型
- 不确定因素很多,很多东西无法提前计划的情况下,尽量采用增量模型或螺旋模型
- 需求不稳定的情况下,尽量采用增量模型
- 资金和成本无法一次到位的情况下,可采用增量模型
- 对于完成多个独立功能开发的情况,可在需求分析阶段就进行功能并行,每个功能内部都尽量遵循瀑布模型
- 全新系统的开发必须在总体设计完成后再开始增量或并行
- 编码人员经验较少的情况下,尽量不要采用敏捷或迭代模型
- 增量、迭代和原型可以综合使用,但每一次增量或迭代都必须有明确的交付和出口原则
-
瀑布模型
- 需求明确
- 多个独立功能开发
- 例:医疗设备控制软件
-
原型模型
- 用户无系统经验
- 分析人员技能不足
-
螺旋模型
- 不确定因素多
- 无法提前计划
- 例:智能化小区
-
增量模型
- 不确定因素多
- 无法提前计划
- 需求不稳定
- 资金和成本暂时无法到位
- 全新系统的开发,在总体设计完成后
- 例:校园一卡通
第三章 需求分析
3.1 需求分析的概念
- 需求分析定义
- 确定系统必须具有的功能和性能,系统要求的运行环境,并且预测系统发展的前景
- 过程
- 需求获取
- 需求提炼
- 需求描述
- 需求验证
- 需求变更
3.2 需求获取
-
软件需求获取
- 软件需求的来源
- 软件工程师收集这些软件需求的方法
-
需求的类型
- 功能性需求
- 描述系统应该做什么,即为用户和其它系统完成的功能、提供的服务
- 非功能性需求
- 必须遵循的标准,外部界面的细节,实现的约束条件,质量属性等等
- 功能性需求
-
需求来源
- 用户目标
- 领域知识
- 投资者
- 运行环境
- 组织环境
-
需求获取技术
- 采访
- 设定情景(用例)
- 原型
- 会议
- 观察商业过程和工作流
-
需求获取面临的挑战
- 客户说不清楚需求
- 需求易变性
- 问题的复杂性和对问题空间理解的不完备性与不一致性
-
诱导沟通十原则
- 倾听
- 有准备的沟通
- 需要有人推动
- 最好当面沟通
- 记录所有决定
- 保持通力协作
- 聚焦并协调话题
- 采用图形表示
- 继续前进原则
- 谈判双赢原则
3.3 需求提炼(分析)和管理过程
-
核心在于建立分析模型
-
采用多种形式描述需求,通过建立需求的多种视图,揭示出一些更深的问题
-
包括与客户的交流以澄清某些易混淆的问题,并明确哪些需求更为重要,其目的是确保所有风险承担者尽早地对项目达成共识并对将来的产品有个相同而清晰的认识
-
需求分析模型
- 模型图
- 模型图
3.4 需求规格说明书
需求描述
- 软件需求规格说明书(SRS)是软件系统的需求规格说明,是对待开发系统的行为的完整描述。它包含了功能性需求和非功能性需求;
- 需求分析工作完成的一个基本标志是形成了一份完整的、规范的需求规格说明书;
- 需求规格说明书的编制是为了使用户和软件开发者双方对该软件的初始规定有一个共同的理解,使之成为整个开发工作的基础。
3.5 需求验证
需求验证
- 重要性
- 如果在后续的开发或当系统投入使用时才发现需求文档中的错误,就会导致更大代价的返工。
- 检查工作
- 有效性检查
- 检查不同用户使用不同功能的有效性
- 一致性检查
- 文档中的需求不应该冲突
- 完备性检查
- 需求文档应该包括所有用户想要的功能和约束
- 现实性检查
- 检查保证能利用现有技术实现需求
- 有效性检查
- 需求验证技术
- 需求评审
- 利用原型检验系统是否符合用户的真正需要
- 对每个需求编写概念性的测试用例
- 编写用户手册,用浅显易懂的语言描述用户可见的功能
- 自动的一致性分析,可用CASE工具检验需求模型的一致性
3.6 需求分析模型概述
- 五个层次
- 主题层
- 对象类层
- 结构层
- 属性层
- 服务层
- 五个活动
- 标识对象类
- 标识结构
- 定义主题
- 定义属性
- 定义服务
- 需求分析
- 数据模型
- 类图、类关系图
- 功能模型
- 用例图
- 行为模型
- 活动图
- 时序图
- 状态图
- 数据模型
- 分析模型描述工具
3.13 功能模型——用例图
-
图形元素
- 参与者
- 外部用户或外部实体在系统中扮演的角色
- 用例
- 一组动作序列的描述
- 用动宾结构命名
- 执行关联
- 参与者与执行用例之间的关系
- 参与者
-
用例建立顺序
- 确定谁会直接使用该系统。这些都是参与者(Actor)。
- 选取其中一个参与者。
- 定义该参与者希望系统做什么,参与者希望系统做的每件事成为一个用例。
- 对每件事来说,何时参与者会使用系统,通常会发生什么,这就是用例的基本过程。
- 描述该用例的基本过程。
- 考虑一些可变情况,把他们创建为扩展用例。
- 复审不同用例的描述,找出其中的相同点,抽出相同点作为共同的用例。
- 重复步骤2~7找出每一个用例。
-
系统
- 用于界定系统功能范围,描述该系统功能的用例都置于其中,而描述外部实体的参与者都置于其外。
-
关联
- 连接参与者和用例,表示参与者所代表的系统外部实体与该用例所描述的系统需求有关。
3.14 用例间的关系
- 关联
- 表示参与者和用例之间的通信
- 任何一方都可发送或接收消息
- 箭头指向消息接收方
- 泛化
- 就是通常理解的继承关系
- 子用例和父用例相似,但表现出更特别的行为
- 箭头指向父用例
- 包含
- 把一个较复杂用例所表示的功能分解成较小的步骤
- 一个用例可以包含另外一个用例
- 箭头指向分解出来的用例
- 扩展
- 用例功能的延伸,相当于为基础用例提供一个附加功能
- 由一个用例的扩展点可以扩展出另外一个用例
- 箭头指向基础用例
第四章 软件设计
4.1 软件设计相关概念
-
软件设计定义
- 软件系统或组件的架构、构件、接口和其他特性的定义过程及该过程的结果。
- 软件生命周期中的一个活动
- 进行软件编码的基础
- 软件需求分析被转化为软件的内部结构
- 是连接用户需求和软件技术的桥梁
-
优质设计的特点
- 设计必须实现在分析模型中包含的所有明确要求,必须满足客户所期望的所有隐含要求
- 设计必须对编码人员、测试人员及后续的维护人员是可读可理解的
- 设计应提供该软件的完整视图,从实现的角度解决数据、功能及行为等各领域方面的问题
-
设计质量指导原则
- 设计应该是一种架构
- 设计应该是模块化的
- 设计应该包含数据、体系结构、接口和组件各个方面
- 应该设计出系统所用的数据结构
- 应该设计出展现在独立功能特性的各组件
- 应该设计出各组件与外部环境连接的各接口
- 设计由软件需求分析过程中获得信息驱动,采用可重复使用的方法导出
- 设计应该采用正确清楚的表示法
-
设计质量属性
- 功能性
- 易用性
- 可靠性
- 性能
- 可支持性
- 扩展性
- 适应性
- 可维护性
-
设计相关的概念
- 抽象
- 体系结构
- 设计模式
- 模块化
- 信息隐藏
- 功能独立
- 精化
- 重构
- 含义
- 是“忽略具体的信息将不同事物看成相同事物的过程”
- 抽象机制
- 参数化
- 规范化
- 规范化抽象
- 数据抽象
- 过程抽象
- 定义
- 软件的整体结构和这种结构为系统提供概念上完整性的方式
- 模型
- 结构模型
- 框架模型
- 动态模型
- 过程模型
- 功能模型
- 含义
- 给定上下文环境中一类共同问题的共同解决方案
- 微观结构
- 实体模式
- 结构模式
- 行为模式
- 23个精选设计模式
-
含义
- 软件被划分为命名和功能相对独立的多个组件(通常称为模块),通过这些组件的集成来满足问题的需求
-
软件的模块性
- 程序可被智能管理的单一属性
-
模块化的理论依据
- 基于人类解决问题的观测数据
-
模块化设计标准
- 分解性
- 可分解为子问题
- 组合性
- 组装可重用的组件
- 可理解性
- 可作为独立单元理解
- 连续性
- 需求小变化只影响单个模块
- 保护
- 模块内异常只影响自身
- 分解性
- 模块化基本问题
- 如何分解软件系统以达最佳的模块划分
- 信息隐藏的原则
- 模块应该具有彼此相互隐藏的特性
- 模块定义和设计时应当保证模块内的信息(过程和数据)不可以被不需要这些信息的其他模块访问
- 特点
- 信息隐藏原则定义和隐藏了模块内的过程细节和模块内的本地数据结构
- 含义
- 每个模块只负责需求中特定的子功能,并且从程序结构的其他部分看,该模块具有简单的接口
- 优点
- 易于开发
- 功能被划分,接口被简化
- 易于维护和测试
- 次生影响有限,错误传递减少,模块重用
- 易于开发
- 定性衡量标准
- 内聚性
- 模块的功能相对强度
- 耦合性
- 模块之间的相互依赖程度
- 模块独立性强=高内聚低耦合
- 内聚性
- 含义
- 逐步求精的过程
- 与抽象的关系
- 抽象使设计师确定过程和数据,但不局限于底层细节
- 精化有助于设计者在设计过程中揭示底层细节
- 含义
- 不改变组件功能和行为条件下,简化组件设计(或代码)的一种重组技术
- 方法
- 检查现有设计的冗余情况、未使用的设计元素、无效或不必要的算法、较差的构建方式或不恰当的数据结构,或任何其他可被更改从而优化设计的问题
- 含义
- 数据设计(有时也被称为数据架构)构建高层抽象(客户/用户的数据视图)的数据模型、信息模型
- 设计原则
- 应用于功能和行为系统分析的原则也应适用于数据设计
- 所有的数据结构及其对应的操作都应该确定
- 建立数据字典并在数据定义和程序设计中应用
- 低层次的数据设计应该推迟到设计的后期过程
- 数据结构的表示应该只对直接使用数据结构中数据的模块可见
- 开发有用的数据结构及其对应操作的程序库
- 软件设计和编程语言应该支持抽象数据类型的定义与实现
- 含义
- 程序或计算系统的软件体系结构是指系统的一个或多个结构,它包括软件构件、构件的外部可见属性以及它们之间的相互关系
- 风格
- 系统需要执行的函数功能组件集(如数据库、计算模块)
- 组件之间通信、协同和合作的连接器
- 组件集成构成系统的约束
- 设计人员通过分析系统组成部分的已知特性,理解其整体特性的语义模型分析
-
示意图
-
适用场合
- 数据库系统
- 超文本系统
- 黑板系统
-
示意图
-
适用场合
- 图像处理
- 音视频处理
- 程序编译
-
示意图
-
适用场合
- 主程序/子程序
- 分层
-
示意图
-
适用场合
- 操作系统
-
示意图
-
适用场合
- MVC架构
- 三条原则
- 允许用户操作控制
- 减少用户记忆负担
- 保持界面一致
问题分析图(PAD):
4.3 面向对象的设计
- 特点
- 面向对象设计强调定义软件对象,并且使这些软件对象相互协作来满足用户需求
- 面向对象分析和设计的界限是模糊的,从面向对象分析到面向对象设计是一个逐渐扩充模型的过程。分析的结果通过细化直接生成设计结果,在设计过程中逐步加深对需求的理解,从而进一步完善需求分析的结果
- 分析和设计活动是一个反复迭代的过程
- 面向对象方法学在概念和表示方法上的一致性,保证了各个开发阶段之间的平滑性
- 四个层次
- 确定系统的总体结构和风格,构造系统的物理模型,将系统划分成不同的子系统
- 中层设计:对每个用例进行设计,规划实现用例功能的关键类,确定类之间的关系
- 进行底层设计:对每个类进行详细设计,设计类的属性和操作,优化类之间的关系
- 补充实现非功能性需求所需要的类
- 注意点
- 对接口进行设计
- 发现变化并且封装它
- 先考虑聚合然后考虑继承
- 强内聚
- 类内聚——设计类的原则是一个类的属性和操作全部都是完成某个任务所必须的,其中不包括无用的属性和操作
- 低耦合
- 在面向对象设计中,耦合主要指不同对象之间相互关联的程度。
- 对象不可能是完全孤立的,当两个对象必须相互联系时,应该通过类的公共接口实现耦合,不应该依赖于类的具体实现细节。
- 耦合方式
- 交互耦合
- 对象之间的耦合是通过消息连接来实现的
- 继承耦合
- 一般化类与特殊化类之间的一种关联形式
- 交互耦合
- 可重用性
- 软件重用是从设计阶段开始的,所有的设计工作都是为了使系统完成预期的任务,为了提高工作效率、减少错误、降低成本,就要充分考虑软件元素的重用性。
- 设计一个可重用的软件比设计一个普通软件的代价要高,但是随着这些软件被重用次数的增加,分摊到它的设计和实现成本就会降低。
- 框架
- 一组可用于不同应用的类的集合。
- 框架中的类通常是一些抽象类并且相互有联系,可以通过继承的方式使用这些类。
- 开闭原则
- 组件应该对外延具有开放性,对修改具有封闭性
- 类的扩充
- 里氏替换原则
- 从基类导出的类传递给组件时,使用基类的组件应该仍然能够正确完成其功能
- 多态呈现
- 依赖倒置原则
- 依赖于抽象,而非具体实现
- OCP原则
- 接口分离原则
- 多个客户专用接口比一个通用接口好
- 去除不必要的接口方法依赖
- 发布复用等价性原则
- 以包为单位,将可复用的类分组打包成能管理和控制的包并作为一个更新的版本,而不是对每个类分别进行升级
- 共同封装原则/共同复用原则
- 应该将易变的类放在同一个包里,将变化隔离出来
- 根据内聚性进行分组,只有那些一起被复用的类才应该包含在一个包中
- 定义
- 架构设计的目的是要勾画出系统的总体结构,这项工作由经验丰富的架构设计师主持完成
- 输入:用例模型、分析模型
- 输出:物理结构、子系统及其接口、概要的设计类
- 步骤
- 构造系统的物理模型
- 设计子系统
- 非功能需求设计
-
边界类
- 系统内部与系统外部的业务主角之间进行交互建模的类
-
控制类
- 用于对一个或几个用例所特有的控制行为进行建模
-
实体类
- 用来描述具体的实体,通常映射到数据库表格与文件中
-
例图
-
如何找实体类
- 实体类用于对必须存储的信息和相关行为进行建模
- 实体类源于业务模型中的业务实体,但出于对系统结构的优化,可以在后续的过程中被分拆、合并
-
如何找边界类
- 参与者与用例之间应当建立边界类
- 用例与用例之间如果有交互,应当为其建立边界类
- 如果用例与系统边界之外的非人对象有交互,应当为其建立边界类
- 在相关联的业务对象有明显的独立性要求,即它们可能在各自的领域内发展和变化,但又希望互不影响时,也应当为它们建立边界类
-
如何找控制类
- 控制类来源于对用例场景中动词的分析和定义
- 控制类主要起到协调对象的作用,从边界类通过控制类访问实体类,或者实体类通过控制类访问另一个实体类
- 如果用例场景中的行为在执行步骤、执行要求或者执行结果上具有类似的特征,应当合并或抽取超类
- 定义类的属性
- 类的属性反映类的特性,通常属性是被封装在类的内部,不允许外部对象访问
- 定义类的操作
- 一个类可能被应用在多个用例中,由于它在不同用例中担当的角色不同,所以设计时要求详细周到
- 定义类之间的关系
- 设置基数
- 一个类的实例与另一个类的实例之间的联系
- 使用关联类
- 可以放置与关联相关的属性
- 设置基数
-
定义
- 强调消息时间顺序的交互图
- 描述了对象之间传送消息的时间顺序,用来表示用例中的行为顺序
-
图例
-
组成
- 对象
- 生命线
- 消息
- 激活
-
对象
- 对象在顺序图的顶部意味着在交互开始的时候对象就已经存在了
- 对象的位置不在顶部,表示对象是在交互的过程中被创建的
- 从左到右的顺序排列
- 启动用例的参与者往往排在最左边,接收消息的参与者则排在最右端
- 对象从左到右按照重要性排列或按照消息先后顺序排列
-
生命线
- 表示在该用例中一个对象在一段时间内的存在
- 使用垂直的虚线表示
-
激活
- 表示该对象被占用以完成某个任务
- 去激活指的则是对象处于空闲状态、在等待消息
- 激活时将该对象的生命线拓宽成为矩形
-
消息
-
对象间交互信息的主要方式
-
由从一个对象的生命线指向另一个对象的生命线的直线箭头来表示的,箭头上面还可以表明要发送的消息名及序号
-
消息类型
- 简单消息
- 同步消息
- 异步消息
- 反身消息
- 返回消息
-
消息示例
-
第六章 软件质量保证
6.1 软件质量保证相关概念
- 质量保证
- 含义
- 系统监测和评估工程的各个方面,最大限度提高质量最低标准
- 内容
- 原料、文档、产品和组件,以及涉及产品的管理、生产和检测过程等质量管理
- 原则
- 该产品应符合预期的目的
- 错误应该被淘汰
- 含义
6.2 软件测试策略
-
软件测试策略含义
- 为软件开发人员、质量保证组织和客户提供了一个路线图
- 规定了测试的主要步骤
-
软件测试策略要求
- 灵活性
- 有足够的可塑性来应付所有的大软件系统
- 严格性
- 保证对项目进程进行合理的计划和跟踪管理
- 灵活性
-
软件测试策略V模型
- 标明了测试过程中存在的不同级别
- 清楚地描述了这些测试阶段和开发过程期间各阶段对应关系
-
单元测试
- 主要目的是验证软件模块是否按详细设计的规格说明正确运行
-
集成测试
- 主要目的是检查多个模块间是否按概要设计说明的方式协同工作
-
系统测试
- 主要目的是验证整个系统是否满足需求规格说明
-
验收测试
- 从用户的角度检查系统是否满足合同中定义的需求,以及以确认产品是否能符合业务上的需要
-
回归测试
- 指有选择地重新测试系统或其组件,以验证对软件地修改没有导致不希望出现的影响,以及系统或组件仍然符合其指定的需求
- 可以在所有的测试级别执行,并应用于功能和非功能测试中
- 缺陷再测试
- 重新运行所有发现故障的测试,而新的软件版本已经修正了这些故障
- 功能改变的测试
- 测试所有修改或修正过的程序部分
- 新功能测试
- 测试所有新集成的程序
- 完全回归测试
- 测试整个系统
-
软件测试策略注意事项
- 在着手开始测试之前,要对产品的需求进行量化
- 明确指出测试目标
- 为每类用户建立描述交互场景的用例
- 建立一个强调“快速循环测试”的测试计划
- 设计一个能够测试自身是否“强壮”的软件
- 在进行测试之前,对软件进行有效的正式技术审核
- 使用正式技术审核来评估测试策略和测试用例本身
- 为测试过程建立一种持续的改进方法
-
软件测试策略基本步骤
- 计划与准备阶段
- 制定计划
- 编写与评审测试用例
- 编写测试脚本和准备测试环境
- 执行阶段
- 搭建测试环境
- 构造测试数据
- 执行测试并记录问题
- 确认问题
- 撰写测试报告
- 返工与回归测试阶段
- 计划与准备阶段
-
单元测试概念
- 单元测试
- 针对软件设计的最小单位——程序模块,进行正确性检验的测试工作
- 测试方法
- 单元测试需要从程序的内部结构出发设计测试用例。
- 多个模块可以平行地独立进行单元测试
- 单元内涵
- 不同环境含义不同
- 面向过程:函数、过程等
- 面向对象:类、类中成员函数等
- 主要依据
- 详细设计
- 单元测试
-
单元测试主要内容
- 模块接口测试
- 数据流测试
- 内外存交换测试
- 局部数据结构测试
- 路径测试
- 对模块中重要的执行路径进行测试
- 查找由于错误的计算、不正确的比较或不正常的控制流而导致的错误
- 对基本执行路径和循环进行测试可以发现大量的路径错误
- 错误处理测试
- 边界测试
- 流边界
- 关键路径
- 模块接口测试
-
测试用例设计
- 依据详细设计说明书和源程序清单
- 了解该模块的I/O条件和模块的逻辑结构
- 手段
- 主:白盒测试
- 辅:黑盒测试
- 合理和不合理输入的鉴别和相应比较预计和实际结果
-
测试环境搭建
-
演示图
-
驱动模块
- 用来模拟被测试模块的上一级模块,相当于被测模块的主程序
-
桩模块
- 模拟被测试的模块所调用的模块,而不是软件产品的组成的部分
-
- 集成测试概念
- 含义
- 将软件集成起来后进行测试
- 目的
- 检查诸如两个模块单独运行正常,但集成起来运行可能出现问题的情况
- 主要方法
- 自顶向下的集成方法
- 自底向上的集成方法
- SMOKE方法
- 含义
- 自顶向下的集成方法
- 基本思想
- 该集成方式将模块按系统程序结构,沿控制层次自顶向下进行集成
- 方式
- 深度优先
- 广度优先
- 优点
- 可以较早地验证主要的控制和判断点。
- 按深度方向,可首先实现和验证一个完整的软件功能
- 缺点
- 桩模块的开发量大
- 适用场景
- 控制结构清晰稳定
- 高层接口变化较小
- 底层接口未定义或经常可能被修改
- 接口控制组件具有较大的技术风险,需要尽早被验证
- 希望尽早能看到产品的系统功能行为
- 基本思想
- 自底向上的集成方法
- 基本思想
- 从软件结构最底层的模块开始,按照接口依赖关系逐层向上集成以进行测试
- 优点
- 每个模块调用其他底层模块都已经测试,不需要桩模块
- 缺点
- 必须编写驱动模块
- 缺陷的隔离和定位不如自顶向下
- 适用场景
- 底层接口比较稳定
- 高层接口变化比较频繁
- 底层组件较早被完成
- 基本思想
- SMOKE方法
- 基本思想
- 将已经转换为代码的软件构件集成为构造(build)
- 一个构造包括所有的数据文件、库、可复用的模块以及实现一个或多个产品功能所需的工程化构件
- 目标
- 设计暴露影响构造正确地完成其功能的错误的测试,以发现极有可能造成项目延迟的业务阻塞错误
- 方法
- 每天将该构造与其他构造,及整个软件产品集成,冒烟测试。
- 两种方法:自顶向下,自底向上,均可
- 基本思想
- 测试用例的设计
- 通过性测试
- 等价类划分法
- 场景分析法
- 状态图法等
- 失效性
- 边界值法
- 错误猜测法
- 因果图法
- 状态图法等
- 覆盖率
- 接口覆盖率
- 接口路径覆盖率等
- 注意接口
- 显性接口:函数调用(API)接口
- 隐形接口:消息、网络协议等
- 通过性测试
-
系统测试概念
- 含义
- 从用户使用的角度进行测试,将完成了集成测试的系统放在真实的运行环境下进行
- 目的
- 功能确认和验证
- 测试方法
- 黑盒测试
- 含义
-
系统测试必要性
- 系统测试意义
- 软件开发过程必不可少的一环,软件质量保证的最重要环节
- 测试内容方面
- 面向外部输入层测试,如不做,则外部输入层向接口层转换的代码就没有得到测试。
- 面向系统所有组件相互协调,单元、集成测试未做。
- 测试角度方面
- 系统测试依据:需求规格说明
- 单元、集成测试依据:技术规格说明
- 系统测试意义
-
系统测试内容
- 功能测试
- 性能测试
- 压力测试
- 恢复测试
- 安全测试等
-
功能测试
- 含义
- 在规定的一段时间内运行软件系统的所有功能,以验证这个软件系统有无严重错误
- 测试方法
- 黑盒测试
- 错误类型
- 功能错误或遗漏
- 界面错误
- 数据结构或外部数据库访问错误
- 性能错误
- 初始化
- 含义
-
性能测试
- 含义
- 检查系统是否满足在需求说明书中规定的性能
- 结合
- 常常要与压力测试结合进行,硬件和软件检测同时进行
- 内容
- 响应时间
- 吞吐量
- 辅助存储区,如缓冲区、工作区的大小、处理精度等
- 含义
-
压力测试
- 含义
- 在系统运行环境不正常乃至发生故障的情况下,系统可以运行到何种程度的测试
- 测试方法
- 把输入数据速率提高一个数量级,确定输入功能将如何响应
- 设计需要占用最大存储量或其它资源的测试用例进行测试。
- 设计出在虚拟存储管理机制中引起“颠簸”的测试用例进行测试。
- 设计出会对磁盘常驻内存的数据过度访问的测试用例进行测试。
- 含义
-
恢复测试
- 含义
- 是要证实在克服硬件故障后,系统能否正常地继续进行工作,并不对系统造成任何损害
- 手段
- 人工干预等
- 测试方法
- 错误探测功能——系统能否发现硬件失效与故障
- 设备故障时,能否切换或启动备用的硬件
- 故障发生时,能否保护正在运行的作业和系统状态
- 系统恢复后,能否从最后记录下来的无错误状态开始继续执行作业等
- 掉电测试:电源中断时,能否保护当时的状态且不毁坏数据,然后在电源恢复时从保留的断点处重新进行操作
- 含义
-
安全性测试
- 含义
- 是要检验在系统中已经存在的系统安全性、保密性措施是否发挥作用,有无漏洞
- 主要攻击方法
- 正面、侧面或背面攻击系统中易受损坏的那些部分
- 以系统输入为突破口,利用输入的容错性进行正面攻击
- 申请和占用过多的资源压垮系统,以破坏安全措施,从而进入系统
- 故意使系统出错,利用系统恢复的过程,窃取用户口令及其它有用的信息
- 通过浏览残留在计算机各种资源中的垃圾(无用信息),以获取如口令,安全码,译码关键字等信息
- 浏览全局数据,期望从中找到进入系统的关键字
- 浏览逻辑上不存在,但物理上还存在的各种记录和资料等
- 含义
- 验收测试概念
- 含义
- 完成系统测试之后,产品发布之前所进行的软件测试活动
- 部署软件之前的最后一个测试操作
- 技术测试的最后一个阶段
- 目的
- 确保软件准备就绪
- 时间节点
- 系统的有效性测试及软件配置审查通过之后
- 人员组织
- 以用户为主
- 开发人员
- 质量保证人员
- 测试数据
- 实际生产数据
- 测试内容
- 功能和性能外,可移植性、兼容性、可维护性、错误的恢复功能等
- 含义
- 验收测试形式
- 含义
- 用户在开发环境、模拟用户在模拟实际操作环境下的测试
- 目的
- 评价FLURPS特性(功能、局域化、可使用性、可靠性、性能和支持)
- 尤其是界面和特色
- 原因
- 交付后,用户的实际使用程序是无法预测的
- 开始时间
- 编码结束后
- 模块(子系统)测试完成后
- 系统测试过程中产品达到一定的稳定和可靠程度后
- 含义
- 测试组织
- 测试团队
- 开发团队
- 开发团队中配备测试人员
- 项目团队中若干测试团队
- 独立测试专家
- 单独测试部门
- 测试人员
- 测试经理
- 测试设计人员
- 测试自动化人员
- 测试管理员
- 测试人员
- 测试团队
6.3 软件测试技术
- 软件测试的定义
- 在某种指定的条件下对系统或组件操作,观察或记录结果,对系统或组件的某些方面进行评估的过程
- 分析软件各项目以检测现有的结果和应有结果之间的差异,并评估软件各项目的特征的过程
- 软件缺点
- 软件未实现产品说明书要求的功能
- 软件出现了产品说明书指明不能出现的错误
- 软件实现了产品说明书未提到的功能
- 软件未实现产品说明书虽未明确提及但应该实现的目标
- 软件难以理解、不易使用、运行缓慢
- 从测试员的角度看——最终用户会认为不好
- 验证与确认
- 验证
- 保证软件特定开发阶段的输出已经正确完整地实现了规格说明
- 确认
- 对于每个测试级别,都要检查开发活动的输出是否满足具体的需求或与这些特定级别相关的需求
- 验证
- 软件质量保证
- 软件测试
- 找出软件缺陷,并确保修复
- 软件质量保证
- 创建、执行改进过程并防止缺陷的标准和方法
- 软件测试
- 质量与可靠性
- 功能性
- 可靠性
- 可维护性
- 可用性
- 效率
- 可移植性
- 测试与调试
- 软件测试
- 目标是发现软件缺陷的存在
- 软件调试
- 目标是定位与修复缺陷
- 软件测试
- 测试用例
- 含义
- 是测试输入、执行条件以及预期结果的集合,是为特定的目的开发的
- 例如执行特定的程序路径或验证与指定的需求相符合
- 含义
- 目标与原则
- 目标
- 确认系统满足其预期的使用和用户的需要
- 确认解决了所需解决的问题
- 为测试的过程建立责任和可解释性
- 便于及早发现软件和系统的异常
- 及早提供软件和系统的性能的评估
- 为管理提供真实信息,以决定当前状态下发布产品在商业上的风险
- 原则
- 穷尽测试是不可能的
- 测试无法显示潜伏的软件缺陷
- 测试活动应尽早进行
- 软件缺陷具有群聚性
- 注意“杀虫剂”现象
- 尽量由独立的测试团队进行测试
- 目标
- 主要测试方法
- 黑盒测试
- 忽略系统或组件的内部机制,仅关注于那些响应所选择的输入及相应执行条件的输出的测试形式
- 白盒测试
- 考虑系统或组件的内部机制的测试形式
- 灰盒测试
- 介于白盒测试与黑盒测试之间的一种测试
- 多用于集成测试阶段,不仅关注输出、输入的正确性,同时也关注程序内部的情况
- 黑盒测试
-
概念
- 把测试对象看做一个透明盒子,允许利用程序内部逻辑结构及有关信息,进行测试
- 通过在不同点检查程序的状态,确定实际的状态是否与预期的状态一致
- 又称为结构测试或逻辑驱动测试
-
检查范围
- 对程序模块的所有独立的执行路径至少测试一次
- 对所有的逻辑判定,取“真”与取“假”的两种情况都至少测试一次
- 在循环的边界和运行界限内执行循环体
- 测试内部数据结构的有效性等
-
逻辑覆盖
-
概念
- 以程序内部的逻辑结构为基础设计测试用例的技术
-
组成
- 语句覆盖
- 分支覆盖
- 条件覆盖
- 条件组合覆盖
-
例图
-
-
语句覆盖
-
概念
- 就是设计若干个测试用例,运行被测程序,使得每一条可执行语句至少执行一次
-
例子
- 例图中L1(a->c->e)遍历所有可执行语句
- L1 = (A=2)&&(B=0)||(A>1)&&(B=0)&&(X/A>1)
-
-
分支覆盖
- 概念
- 就是设计若干个测试用例,运行被测程序,使得程序中每个判断的取真分支和取假分支至少经历一次
- 分支覆盖又称为判定覆盖
- 例子
- 例图中L1(a->c->e)和L2(a->b->d)
- 或者L3(a->c->d)和L4(a->b->e)
- 概念
-
条件覆盖
- 概念
- 设计若干个测试用例,运行被测程序,使得程序中每个判断的每个条件的可能取值至少执行一次
- 例子
- 例图中L1(a->c->e)和L2(a->b->d)
- 或者L3(a->c->d)和L4(a->b->e)
- 概念
-
条件组合覆盖
- 概念
- 设计足够的测试用例,运行被测程序,使得每个判断的所有可能的条件取值组合至少执行一次
- 将每个判断条件内部进行拆分
- 例子
- 例图中L1[(2, 0, 4), (2, 0, 3)]和L2[(2, 1, 1), (2, 1, 2)]和L3[(1, 0, 3), (1, 0, 4)]和L4[(1, 1, 1), (1, 1, 1)]
- 概念
-
控制流图
- 结点
- 符号○ ,表示一个或多个无分支的PDL语句或源程序语句
- 边
- 箭头,表示控制流的方向
- 汇聚节点
- 在选择或多分支结构中,分支的汇聚处应有一个汇聚结点
- 区域
- 边和结点圈定的区域。
- 对区域计数时,图形外的区域也应记为一个区域
- 结点
-
单条件嵌套
- 概念
- 如果判断中的条件表达式是由一个或多个逻辑运算符 (OR, AND, NAND, NOR) 连接的复合条件表达式,则需要改为一系列只有单个条件的嵌套的判断
- 概念
-
节点覆盖
- 概念
- 对图中的每个节点,至少要有一条测试路径访问该节点
- 显然,节点覆盖=语句覆盖
- 概念
-
边覆盖
- 概念
- 对图中每一个可到达的长度小于(无边图)等于1 的路径,中至少存在一条测试路径覆盖。
- 显然,边覆盖包含节点覆盖,且边覆盖也可以实现分支覆盖
- 概念
-
路径覆盖
- 概念
- 就是设计足够的测试用例,覆盖程序中所有可能的路径
- 概念
-
基本路径覆盖
- 概念
- 将覆盖的路径数压缩到一定限度内,程序中的循环体最多只执行一次
- 复杂性
- 程序基本路径集中的独立路径条数,这是确保程序中每个可执行语句至少执行一次所必需的测试用例数目的上界
- 导出测试用例
- 确保基本路径集的每一条路径的执行
- 选择测试用例
- 根据判断结点给出的条件,选择合适用例以保证某一条路径可以被测试到
- 测试结果比较
- 测试执行后,与预期结果进行比较
- 注意事项
- 非孤立的路径可以是另一条路径测试的一部分
- 概念
-
黑盒测试
- 概念
- 测试对象看做一个黑盒子,测试人员完全不考虑程序内部的逻辑结构和内部特性
- 只依据程序的需求规格说明书,检查程序的功能是否符合它的功能说明
- 又叫做功能测试或数据驱动测试
- 检查范围
- 是否有不正确或遗漏了的功能?
- 在接口上,输入能否正确地接受? 能否输出正确的结果?
- 是否有数据结构错误或外部信息访问错误?
- 性能上是否能够满足要求?
- 是否有初始化或终止性错误?
- 完全测试困难性
- 如果考虑所有可能的输入条件和输出条件中,黑盒测试同样可能是天文数字
- 概念
-
等价类划分
- 基本思想
- 把所有可能的输入数据,即程序的输入域划分成若干部分,然后从每一部分中选取少数有代表性的数据做为测试用例
- 测试步骤
- 划分等价类
- 选取测试用例
- 基本思想
-
等价类分类
- 概念
- 某个输入域的子集合,在该子集合中,各个输入数据对于揭露程序中的错误都是等效的
- 有效等价类
- 对于程序的规格说明来说,是合理的,有意义的输入数据构成的集合
- 无效等价类
- 对于程序的规格说明来说,是不合理的,无意义的输入数据构成的集合
- 原则
- 如果输入条件规定了取值范围,或值的个数,则可以确立一个有效等价类和两个无效等价类
- 如果输入条件规定了输入值的集合,或者规定了“必须如何”的条件,这时可确立一个有效等价类和一个无效等价类
- 如果输入条件是一个布尔量,则可以确定一个有效等价类和一个无效等价类
- 如果规定了输入数据的一组值,而且要对每个输入值分别进行处理,可为每一个输入值确立一个有效等价类,所有不允许的输入值集合为一个无效类
- 如果规定了输入数据必须遵守的规则,则可以确立一个有效等价类(符合规则)和若干个无效等价类(从不同角度违反规则)
- 步骤
- 确定等价类
- 建立等价类表,列出所有划分出的等价类
- 为每一个等价类规定一个唯一编号
- 设计一个新的测试用例,尽可能多地覆盖尚未被覆盖的有效等价类,重复这一步,直到所有的有效等价类都被覆盖为止
- 设计一个新的测试用例,仅覆盖一个尚未被覆盖的无效等价类,重复这一步,直到所有的无效等价类都被覆盖为止
- 例子
输入条件 有效等价类 无效等价类 标识符个数 ≥1个 (1) 0个 (2) 标识符字符数 8个 (3) 0个 (4);>8个 (5) 标识符组成 字母、数字的任意组合(6) 非字母数字字符 (7);保留字(8) 第一个字符 字母 (9) 非字母 (10) 标识符使用 先说明后使用 (11) 未说明已使用 (12) - 概念
-
边界值分析
- 方法
- 确定边界情况
- 选取正好等于,刚刚大于,或刚刚小于边界的值做为测试数据做为测试数据。
- 含义
- 黑盒测试方法
- 对等价类划分方法的补充
- 边界指标
- 相当于输入、输出等价类而言,稍高、低于其边界值的一些特定情况
- 原因
- 大量的错误是发生在输入或输出范围边界上
- 边界测试可以查出更多的错误
- 方法
-
状态测试
-
概念
- 在黑盒测试阶段,通过对状态的测试间接地加以验证功能
-
软件状态
- 软件当前所处的条件或者模式
- 除了极少数简单程序外,均需选择重要的内容进行测试
-
例子
输入代码 输入事件 ip1 输入账号 ip2 输入密码 ip3 点击登录按钮 ip4 单击退出按钮 -
原则
- 每种状态至少访问一次
- 测试看起来是最常见和最普遍的状态转换
- 测试状态之间最不常用的分支
- 测试所有错误状态及其返回值
- 测试状态的随机转换
-
-
静态分析方法
- 含义
- 不运行程序,通过检查和阅读等手段来发现错误并评估代码质量的测试技术
- 作用
- 代码标准、质量监控提高可靠性
- 尽早通过源代码检查发现缺陷
- 代码审核定位易产生错误的模块
- 趋势
- 非常有效的质量保证手段,越来越多地被采用
- 同事审查
- 适用于初次审查,要求最低的正式方法,也称为伙伴审查
- 走查
- 开发组内部进行
- 审查
- 以会议形式,由开发组、测试组和相关人员联合进行
- 含义