软件工程导论-期末复习

6 minute read

Published:

东南大学-软件工程导论-期末复习笔记

软件工程概述

概念

软件⭐:1. 指令的集合(计算机程序),通过执行这些指令可以满足预期的特性、功能和性能需求。2. 数据结构,使得程序可以合理利用信息。3. 软件描述信息,他以硬拷贝和虚拟形式存在,用来描述程序的操作和使用。

  • 软件特性

    软件是逻辑的、知识性的智力产品,是对物理世界的一种抽象

    • developed/engineered
    • deteriorates
    • custom built
    • complex

    具创造性,非标准化,需求可能会不断变化,软件技术日新月异,易修改

  • 软件危机⭐

    软件的可靠性没有保障、维护费用不断上升、进度无法预测、成本增长无法控制、程序员无限度增加等,形成软件开发局面失控的状态。

  • 软件生命周期、阶段⭐

    软件有一个孕育、诞生、成长、成熟、衰亡的生存过程。这个过程即为计算机软件的生命周期(生存周期)

    1. 定义阶段
      1. 计划
      2. 需求分析
    2. 开发阶段
      1. 概要设计
      2. 详细设计
      3. 编码
      4. 集成测试
      5. 试运行和验收
    3. 运行维护
  • 软件工程

    软件工程是计算机科学、工程和管理三个学科的综合。

    应用计算机科学、数学及管理科学等原理,借鉴传统工程的原则和方法,来创建软件,从而达到提高质量、降低成本的目的。

    其中,采用的方法包括:

    计算机科学和数学用于构造模型、分析算法;

    工程科学用于制定规范、明确风险、评估成本和确定权衡;

    管理科学用于进度、资源、质量、成本的管理。

  • 软件过程模型

    • 软件过程

      生产一个最终满足需求且达到工程目标的软件产品所需要的步骤。

    过程框架中定义了若干框架活动和普适性活动

    • 框架活动framework activities

      一般通过完成若干任务来实现,如:分析是一个框架活动,它包括需求获取、需求细化、协商、规格说明和确认等任务,每一个工作任务都有相应的工作产品,比如需求文档、use case图等,同样也有相应的里程碑和质量保证点。

      通用过程框架活动

      • 沟通:需求获取
      • 策划:计划任务、估计风险、资源需求、进度计划
      • 建模:分析、设计
      • 构建:编码、测试
      • 部署:交付、评测、反馈
    • 普适性活动umbrella activities

      适用于各个软件过程的通用活动,和框架活动配套使用。如:该框架活动是否已定量管理

以下模型的特点、优点、缺点、适用于什么项目

过程模型

瀑布模型(waterfall)⭐

传统的生命周期模型,典型的瀑布模型具有顺序性和依赖性

特征:

  • 从上一项活动中接受该项活动的工作成果(工作产品),作为输入
  • 利用这一输入实施该项活动应完成的内容
  • 给出该项活动的工作成果,作为输出传给下一项活动
  • 对该项活动实施的工作进行评审。若其工作得到确认,则继续下一项活动

优点:

  • 强调开发的阶段性
  • 强调早期计划及需求调查
  • 强调产品测试

缺点:

  • 瀑布模型过于依赖早期进行的唯一一次需求调查,不能适应需求的变化
  • 瀑布模型是单一流程,开发中的经验教训不能反馈应用于本产品的过程

适用场景

  • 在开发时间内需求没有或很少变化
  • 分析设计人员应对应用领域很熟悉
  • 低风险项目(对目标、环境很熟悉)
  • 用户使用环境很稳定
  • 用户除提出需求以外,很少参与开发工作

增量模型(incremental)⭐

又称产品改进模型,从给定需求开始,通过构造一系列中间版本来实施开发活动,依次类推,直到系统完成,每一个中间版本都是需求分析、设计、编码和测试的过程。某些中间版本的开发可以并行进行

特征:

  • 融合了线性顺序模型的基本成分和原型的迭代特征
  • 是随着日程时间的进展而交错的线性序列
  • 与原型不一样的地方是强调每个增量均发布一个可操作产品
  • 最典型的应用是同一个产品的不同项目(合同、用户)版本

优点:

  • 将待开发的软件系统模块化,可以分批次地提交软件产品,使用户可以及时了解软件项目的进展。

  • 以组件为单位进行开发降低了软件开发的风险。一个开发周期内的错误不会影响到整个软件系统。

  • 开发顺序灵活。开发人员可以对组件的实现顺序进行优先级排序,先完成需求稳定的核心组件。当组件的优先级发生变化时,还能及时地对实现顺序进行调整。

缺点:

要求待开发的软件系统可以被模块化。如果待开发的软件系统很难被模块化,那么将会给增量开发带来很多麻烦。

适用于:

  • 需求经常变化的软件开发

  • 市场急需而开发人员和资金不能在设定的市场期限之前实现一个完善的产品的软件开发

能有计划地管理技术风险,如早期增量版本中避免采用尚未成熟的技术

原型模型(prototyping)⭐

基本思想:在获取一组基本的需求定义后,利用高级软件工具的可开发环境,快速地建立一个目标系统的最初版本-原型,并把它交给用户试用、补充和修改,再进行新的版本开发。反复进行这个过程,直到得出系统的精确解,即用户满意为止。经过这样一个反复补充和修改的过程,应用系统的最初版本就逐步演变为系统的最终版本

特征:

  • 它是一个可实际运行的系统
  • 它没有固定的生存期,它可能被扔掉,或者作为最终产品的一部分
  • 从需求分析到最终产品都可作原型,即可为不同目标作原型
  • 它必须快速、廉价
  • 它是迭代过程的集成部分,即每次经用户评价后修改、运行,不断重复双方认可

优点:

  • 一开始就能弄清楚所有的产品需求,或者至少可以帮助导引出高质量的产品需求
  • 可在项目早期就获取项目的相关数据,尽早进行风险管理和配置管理
  • 心理上,开发人员早日见到产品的雏形,是一种鼓舞
  • 使用户可以在新的一批功能开发测试后,立即参加验证,以便提供非常有价值的反馈
  • 可使销售工作有可能提前进行,因为可以在产品开发的中后期取得包含了主要功能的产品原型去向各户作展示和试用

缺点:

  • 如果缺乏严格的过程管理的话,这个生命周期模型很可能退化为一种原始的无计划的”试——错——改“的循环模式
  • 心理上,可能产生一种影响尽最大努力的想法,认为虽然不能完成全部功能,但还是造出了一个有部分功能的产品
  • 如果不加控制地让用户接触开发中尚未测试稳定的功能,可能对开发人员及用户都产生负面的影响

适用于那些不能预先确切定义需求的软件系统的开发,更适用于那些项目组成员(包括分析员、设计员、程序员和用户)不能很好的交流或者通信的情况下。

螺旋模型(spiral)⭐

是瀑布模型和演化模型(原型模型)的结合,并增加了风险分析

螺旋模型沿着螺线旋转,在四个象限上分别表达四个方面的活动:

  • 制定计划:确定软件目标,选定实施方案,弄清项目开发的限制条件
  • 风险分析:评价所选的方案,识别风险,消除风险
  • 工程实施:实施软件开发,验证工作产品
  • 客户评估:评价开发工作,提出修正建议

优点:

  • 强调严格的全过程风险管理
  • 强调各开发阶段的质量
  • 提供机会检讨项目是否有价值继续下去

缺点:

必须引入非常严格的风险识别,风险分析和风险控制,这对风险管理的技能水平提出了很高的要求。也需要人员,资金和时间的大量投入

适用于大型的昂贵的系统级的软件应用

喷泉模型(fountain)⭐

喷泉模型认为软件生命周期的各个阶段是相互重叠和多次反复,也是一种线性开发模型,与瀑布模型类似,只是从串行改并行。主要用于面向对象方法中,面向对象的分析和设计重叠,交叉、并行进行

优点:

该模型的各个阶段没有明显的界限,开发人员可以同步进行开发。其优点是可以提高软件项目开发效率,节省开发时间,适应于面向对象的软件开发过程

缺点:

由于喷泉模型在各个开发阶段是重叠的,因此在开发过程中需要大量的开发人员,因此不利于项目的管理。此外这种模型要求严格管理文档,使得审核的难度加大,尤其是面对可能随时加入各种信息、需求与资料的情况

适应于面向对象的软件开发过程。

统一过程(UP)⭐

特征:

  • 用例驱动
  • 以架构为核心
  • 迭代并且增量

RUP的时间轴被分解为四个顺序的阶段

  • 初始阶段 为系统建立业务案例并确定项目的边界
  • 细化阶段 分析问题领域,建立健全的体系结构基础,编制项目计划,淘汰项目中最高风险的元素
  • 构造阶段 所有剩余的构件和应用程序功能被开发并集成为产品,所有的功能被详细测试
  • 交付阶段 确保软件对最终用户是可用的

核心工作流(6个核心过程工作流 3个核心支持工作流)

核心过程工作流

  1. 业务建模工作流 为组织开发一个构想,并基于这个构想在业务用例模型和业务对象模型中定义组织的过程、角色和责任
  2. 需求工作流 的目标是描述系统应该做什么,并使开发人员和用户就这一描述达成共识
  3. 分析和设计工作流 将需求转化成未来系统的设计,为系统开发一个健壮的结构并调整设计使其与实现环境相匹配,优化其性能
  4. 实现工作流 目的包括以层次化的子系统形式定义代码的组织结构;以组件的形式(源文件、二进制文件、可执行文件)实现类和对象;将开发出的组件作为单元进行测试以及集成由单个开发者(或小组)所产生的结果,使其成为可执行的系统
  5. 测试工作流 验证对象间的交互作用,验证软件中所有组件的正确集成,检验所有的需求已被正确的实现,识别、提出缺陷并确认缺陷在软件部署之前被处理
  6. 部署工作流 成功的生成版本并将软件分发给最终用户

核心支持工作流

  1. 配置和变更管理工作流 描绘了如何在多个成员组成的项目中控制大量的产物,管理演化系统中的多个变体,跟踪软件创建过程中的版本
  2. 软件项目管理工作流 平衡各种可能产生冲突的目标,管理风险,克服各种约束并成功交付使用户满意的产品
  3. 环境工作流的目的是向软件开发组织提供软件开发环境,包括过程和工具

优点:

提高了团队生产力,在迭代的开发过程、需求管理、基于组件的体系结构、可视化软件建模、验证软件质量及控制软件变更等方面,针对所有关键的开发活动为每个开发成员提供了必要的准则、模板和工具指导,并确保全体成员共享相同的知识基础。它建立了简洁和清晰的过程结构,为开发过程提供较大的通用性。

缺点:

RUP在理论上,是比较理想的,但在实际应用上,还需要更多的工具的支持和普及推广工作。

适用于大型软件团队开发大型项目

敏捷视角下的过程

敏捷开发,XP⭐

有效的响应变化、有效的沟通、软件工程师和其他stakeholders一起构成团队、团队组织

快速、持续交付有价值的软件增量

使用面向对象方法作为推荐的开发范型

包含了四个框架活动的规则和实践

  • 策划
  • 设计
  • 编码
  • 测试

XP planning

从创建用户故事开始

敏捷团队评估每个故事并分配成本

将故事分组以获得可交付的增量

承诺在交付日期做出

在第一次增量项目速度(速度)是用来帮助定义为其他增加后续的交付日期

•Begins with the creation of user stories

•Agile team assesses each story and assigns a cost

•Stories are grouped for a deliverable increment

•A commitment is made on delivery date

•After the first increment project velocity (速度) is used to help define subsequent delivery dates for other increments

XP designing 遵循KIS原则(保持简单)

鼓励使用CRC卡(标准索引卡集合)

对于困难的设计问题,建议创建spike(探针)解决方案——一个设计原型

鼓励重构——对内部程序设计的迭代改进

Follows the KIS principle(Keep It Simple)

Encourage the use of CRC cards

For difficult design problems, suggests the creation of spike solutions — a design prototype

Encourages refactoring — an iterative refinement of the internal program design

XP coding

  • 测试驱动编程
  • 结对编程

XP testing

  • 强调daily building,冒烟测试
  • 强调验收测试,回归测试

适合

  • 小团队(2-10个programmers)
  • “高风险”
  • 快速变化或不稳定的需求
  • 强调可测试性

格言:

沟通、简化、反馈、激励

软件工程技术

系统工程

系统工程中的概念⭐

  • 系统

    一组或一系列相关的元素[人、产品(硬件和软件)及过程(设备、装备、材料和规程)],其行为满足运转需要并且为产品生存周期的维持提供支撑

  • 基于计算机的系统

    通过处理信息来完成某些预定义目标而组织在一起的元素的组合

    对于用户而言有意义的是可以达到预期目标的系统(完整的软硬件解决方案)而不是单一软件

    组成基于计算机系统的元素主要有:软件、硬件、人员、数据库(及其它系统软件)、文档和规程

  • 系统的层次结构

    任何系统都处在一个更大的系统之中,形成系统的层次结构

  • 基于计算机的系统中软件与系统的关系

    计算机软件通常位于整个系统的核心位置

    不同的计算机信息系统具有不同的特点

    随着技术发展,软硬件的边界不断变化

  • 系统工程⭐

    • 关注目标系统各种相关要素的分析、设计,并将其组织成有机的系统
    • 有机:像生命体一样,各个部分密切配合、有序演化,达到系统的总体目标
  • 系统工程 VS 软件工程⭐

    • 系统工程更加广泛,软件工程源于系统工程
    • 任何软件的开发都处于一个更大的系统之中,因此软件开发必须先了解软件所处的系统全局视图
  • 计算机系统工程

    是一个问题求解的活动,其目的是分析基于计算机的系统的功能、性能等要求,并把它们分配到基于计算机系统的各个系统元素中,确定它们的约束条件和接口。

  • 计算机系统工程的任务

    1. 识别用户的要求(了解问题)

      标识系统的功能和性能范围,确定系统的功能、性能、约束和接口

    2. 系统建模和模拟(提出完整的解决方案)

      • 硬件系统模型
      • 软件系统模型
      • 人机接口模型
      • 数据模型
    3. 成本估算及进度安排(给出实施计划)

    4. 可行性分析(系统及实施方案的现实可行性)

      从经济、技术、法律等方面分析所给出的解决方案是否可行

    5. 生成系统规格说明

系统建模

deployment diagrams

activity diagrams

class diagrams

系统模型分类

需求工程

需求工程任务

需求工程提供一种适当的机制,以了解用户想要什么、分析需求、评估可行性、协商合理的解决方案、无歧义地规约解决方案、确认规约以及在开发过程中管理这些被确认的需求规约的过程。

需求工程工作产品

必要性和可行性陈述;系统或产品范围的界限说明;参与需求导出的客户,用户和其他共利益者的列表;系统技术环境的说明;需求列表(推荐按照功能加以组织)以及每个需求使用的领域限制;一系列使用场景,有助于深入了解系统或产品在不同运行环境下的使用;任何能够更好的定义需求的原型

需求开发的方法⭐

  • 需求获取:

    1. 起始过程:与客户建立初步交流。
    2. 导出过程:通过各种途径获取用户的需求信息(原始材料)
  • 需求分析:

    精化过程:分析建模,建立精确的技术模型,用以说明软件的功能、特征和约束

  • 需求处理:

    1. 协商过程:开发者与客户之间就所要交付的系统的功能、性能、交付时间等问题进行估算和协商。
    2. 形成规格说明:根据需求调查和需求分析的结果,进一步定义准确无误的产品需求,产生《产品需求规格说明书》这是后续所有工作的基础
  • 需求确认

    评审:开发方和客户共同对需求文档进行评审,双方对需求达成共识后作出书面承诺,使需求文档具有商业合同效果

需求获取方法
  • 需求获取步骤

    1. 确定stakeholders

    2. 从不同视角,不同角度收集信息

      多角度收集,需求很可能不一致甚至矛盾。需求工程师的工作就是将这些信息分类,以便于决策者从中选取一致的需求集合

    3. stakeholders协同合作收集需求(会议、问卷、原型)

      方法:访谈和调查

      访谈与调查的原则

      • 所提问的问题应该循序渐进,从整体的方面开始提问,接下来的问题应有助于对前面的问题更好的理解和细化
      • 不要限制用户对问题的回答,这有可能会引出原先没有注意的问题
      • 提问和回答在汇总后应能够反映用户需求的全貌——不断汇总-反馈-汇总

      方法:会议讨论法

      • 适用于需求调研早期
      • 特点:需求获取的信息量大,但有时全面性和深入性不足
      • 做好调研计划,同时掌握好计划与灵活性的平衡

      方法:调查问卷

      • 由分析人员拟定问卷(选择、判断居多)请客户方代表回答
      • 适用于需求调研的中后期,往往用于对前期发现的一些不明确或不一致的地方进行确认
      • 特点:信息量较小,但能够引导客户对某些关键问题进行思考,给出明确、严谨的回答和判断

      方法:原型系统

      • 由开发小组快速开发一个近似的功能原型(往往以操作界面为主),分析人员与客户围绕着原型系统的演示进行需求讨论
      • 适用于客户仅有一些宏观的设想而自身需求还不明确的情况
      • 特点:能够帮助客户将自己的设想落实为具体需求,能够有效激发客户的思维,但需要额外的原型开发开销
      • 要求分析人员自身对需要有较强的认识,基本能够把握客户的潜在想法或者开发方有类似的成品软件
    4. 创建用户场景,构建用况

      • 收集需求时,系统功能和特点开始具体化。此时,容易弄不清不同类型的最终用户如何使用这些系统功能和特点
      • 场景描述了系统将如何被使用
      • 场景描述被称为用况(或用例,use case)
需求分析方法
  • 需求分析的步骤

    1. 进行系统分析,确定对系统的综合要求

      • 功能要求:从整个系统的角度提出系统整体功能要求;

      • 性能要求:包括系统的相应时间、资源限制、数据精确性、系统适应性等;

      • 运行要求:包括系统硬件环境、网络环境、系统软件、接口等的具体要求;

      • 其他要求:安全保密、可靠性、可维护性、可移植性、可扩展性等等。

    2. 分析系统的功能要求

      主要思想:抽象与自顶向下的逐层分解(控制复杂性的两个基本手段)

      抽象:在每个抽象层次上忽略问题的内部复杂性,只关注整个问题与外界的联系

      分解:将问题不断分解为较小的问题,直到每个最底层的问题都足够简单为止

    3. 分析系统的数据要求

      主要指系统分析师根据用户的信息流抽象、归纳出系统所要求的数据定义、数据逻辑关系、输入/出数据定义、数据采集方式等

    4. 抽象出并确立目标系统的逻辑模型

      • 模型的作用

        • 整个系统太复杂,难以一下子抓住,通过模型简洁地描述系统某个方面
        • 交流(项目组成员之间,与客户)
        • 将系统体系结构归档
      • 模型建立的思路

        • 自顶向下、逐步求精
        • 自底向上、综合集成
      • 模型的表述:模型语言

      • 模型语言=模型Model+表示法Notation

        • Model: 表示系统的结构

          设计系统时可以在高层进行讨论,而不用太早进入代码的细节

        • Notation: 以图、表、文字等将模型文档化

      • 描述模型的方式:形式化描述和图示化描述。

        • 形式化描述方法非常精确、严谨,易于系统以后的实现,但难以掌握和理解,模型可读性差,往往只有专业人员才会使用,因而难于推广。
        • 图示化方法直观、自然,易于描述系统的层次结构、功能组成,且简单易学,通常还有工具软件支持,因而成为信息系统的主要描述工具,但这种方法的精确性和严谨性不够。

构建分析模型

分析模型的作用

分析模型的构建原则

面向对象的需求工程方法⭐

  1. 需求获取

    • 起始过程(Inception)和导出过程(Elicitation)

      可通过用例图、活动图获得对场景的描述

  2. 需求分析

    • 精化过程(Elaboration)

      通过类图、包图、对象图对实体建模

      通过状态图、顺序图、协作图、活动图等对行为建模

  3. 需求处理

    • 协商过程(Negotiation)
    • 形成规格说明(Specification)
  4. 需求确认

场景建模⭐:用例use-case⭐,部署图
类建模⭐:class图⭐,协作图
行为建模:状态转换图、活动图、顺序图

设计工程

概念

  • 抽象abstraction⭐

    就是抽出事物的本质特性而暂时不考虑它们的细节。是控制复杂性的基本策略之一

    抽象过程:从特殊到一般的过程,上层概念是下层概念的抽象,下层概念是上层概念的精化和细化

    数据抽象

    • 定义数据类型和施加于该类型对象的操作

    • 限定了对象的取值范围,只能通过这些操作修改和观察数据

    过程抽象:功能角度的抽象

    • 将功能体作为单个功能看待

    • 该功能体实际上是由一系列更低级的功能或代码来实现的

  • 体系结构architecture⭐

    软件体系结构关注系统的一个或多个结构,包含软件部件、部件对外可见的属性以及部件间的关系

    体系结构的作用

    • 方便利益相关人员的交流
    • 有利于系统设计的前期决策
    • 可传递、易于理解的系统级抽象

    体系结构反映了软件系统实现的高层方案

    • 软件系统越来越复杂,需要将其划分为若干部分分而治之—模块化

      • 不同的小组或开发者负责不同的部分
      • 然后在系统层面上进行集成
    • 负责不同部分的开发者对于其它模块需要了解的信息越少越好—抽象与信息隐藏

    • 这些部分之间还需要定义清晰、明确的接口—接口设计

  • 模式patterns⭐

    每个模式都描述了一个在我们所处环境内反复发生的问题,描述了该问题的核心解决方案。

    模式的定义便于复用。

    模式的类型

    • 结构模式 (Architecture Pattern)

      • 表达了软件系统的基本结构组织形式或者结构方案

      • 它包含一组预定义的子系统,规定了这些子系统的责任,同时还提供了用于组织和管理这些子系统的规则和向导

    • 设计模式 (Design Pattern)

      • 为软件系统的子系统、组件或者组件之间的关系提供一个精炼之后的解决方案

      • 它描述了在特定环境下,用于解决通用软件设计问题的组件以及这些组件相互通信时的可重现结构

    • 编码模式 (Idiom)

  • 逐步求精refinement⭐

    • 把问题的求解过程分解成若干步骤或阶段,每步都比上步更精化,更接近问题的解法

    • 常与分层抽象的思想相结合

      • 抽象使得设计者能够描述过程和数据而忽略低层的细节
      • 求精有助于设计者在设计过程中揭示低层的细节
      • 高层抽象将在下层不断精化,最终得到软件实现
  • 模块化modularity⭐

    按照设计原则将系统划分为若干个较小的模块(构件)

    • 相互独立但又相互关联

    • 实际上是系统分解和抽象的过程

    模块是相对独立的程序体

    • 独立命名的,并且可以通过名字来访问

      例如:过程、函数、子程序、宏等

    可通过模块化降低开发复杂度

    • C(x):问题x的复杂性

    • E(x):解决问题x所需工作量

    • 对于两个问题p1 和p2:

      1. 如果C(p1)>C(p2) 那么 E(p1)>E(p2)

        问题越复杂解决问题所需要的花费更多

      2. C(p1+p2)>C(p1)+C(p2)因此E(p1+p2)>E(p1)+E(p2)

        将复杂问题分解成可以多个子问题分别解决会更加容易(模块化思想的依据)

    集成和沟通的开销到了一定程度就会成为开发工作量的主要部分

    模块数增加时,模块间的关系也随之增加,接口和集成的工作量也随之增加

    结论:寻找最佳模块化程度平衡点

  • 信息隐藏information hiding⭐

    每个模块都尽量对其他模块隐藏自己的内部实现细节

    • 模块内部的数据和过程不允许其它不需要这些信息的模块使用

    • 定义和实施对模块的过程细节和局部数据结构的存取限制

    信息隐藏是实现抽象/模块化机制的基本支撑

  • 模块独立functional independence⭐

    1. 功能独立(模块独立)是模块化的根本要求

      • 模块完成独立的功能:明确可辨识
      • 高内聚:内部结构紧密
      • 低耦合:模块间关联和依赖程度尽可能小,与其他模块的接口简单
      • 符合信息隐蔽和信息局部化原则
    2. 模块独立的重要性

      • 模块的开发者专注于某一个相对独立的部分
      • 不用过多关心其他模块
      • 修改和bug所影响的范围被局部化
      • 单个模块更容易复用
      • 独立的模块更易于维护和测试
    3. 模块独立性的指标

      • 内聚度与耦合度
      • 内聚(cohesion):一个模块内部各个元素彼此结合的紧密程度——尽量高
      • 耦合(coupling):模块之间相互关联的程度——尽量低

      内聚度(由高到低排列)

      1

      • 功能内聚

        指一个模块中各个部分都是为完成一项具体功能而协同工作,紧密联系,不可分割的(单个功能)

        判断一个模块是不是功能内聚:若需要完成的功能中含“和”,“或”等词,它一定不够功能内聚

      • 分层内聚

        层是一种弱耦合结构,层与层之间的依赖是向下的,底层对于上层而言是“无知”的,改变上层的设计对于其调用的底层而言没有任何影响

      • 顺序内聚

        一个模块内部各个组成部分必须顺序执行,前一个动作的输出是后一个动作的输入

      • 通信内聚

        模块内各组成部分的处理动作都使用相同的输入数据或者具有相同的输出数据

      • 过程内聚

        模块内的多个任务,即使动作各不相同,也没有相互联系,但它们都受一个控制流支配,必须按指定的过程执行

      • 暂时内聚(时间内聚)

        模块内各部分的处理与时间相关

        时间内聚模块中的各项处理必须在一定时间内完成

        如:启动时要进行的全部操作

      • 实用内聚

        在一个模块中,但是其他方面都不相关的构件、类或操作被分为一组。

        如:Statistics类中包含计算6个简单统计所需的所有属性和操作

      2

      • 内容耦合

        一个模块可以直接访问另一个模块的内部数据或内部功能

      • 共用耦合(公共耦合)

        多个模块共同访问某些公共数据环境

        好处:便利性(如可设公共缺省值)

        缺点:当这种耦合需要变更时,无法判定有多少模块属于共用耦合,从而造成错误蔓延

      • 外部耦合

        一组模块都访问同一全局简单变量而不是同一全局数据结构,而且不是通过参数表传递该全局变量的信息

      • 控制耦合

        模块间的交互参数包含控制信息,可影响另一个模块的执行逻辑

        控制信息不同于数据信息

      • 标记耦合

        模块间传递特定的数据结构

        如高级语言的数组名,记录名,文件名等这些名字(标记),其实传递的是该数据结构的地址

        缺点:各模块都必须清楚该记录的结构,并按结构要求对该记录进行操作。

      • 数据耦合

        模块间仅通过参数表传递简单数据

        但是要注意若参数列表过长则会带来测试和维护困难

      • 非直接耦合:两个模块可以相对独立工作

        • 例程调用耦合(Routine call coupling)

          • 一个操作调用另外一个操作
          • 通过减少例程总量来减少此种耦合
        • 类型使用耦合(Type use coupling)

          • 构件A使用了在构件B中定义的一个数据类型
          • 如:一个类将其某变量声明为另一个类的类型
        • 包含或导入耦合(Inclusion or import)

          构件A导入或者包含构件B的包或者内容

    具有模块独立性的模块:高内聚低耦合的模块

    • 一个模块内部各个元素之间的联系越紧密,则它的内聚性就越高,模块独立性也越强

    • 模块之间的连接越紧密,联系越多,耦合性就越高,而其模块独立性就越弱

  • 重构refactoring⭐

    重构的目的是去发现和修改

    • 冗余

    • 未使用的设计元素

    • 低效或不必要的算法

    • 构造不良或不适当的数据结构

    • 或任何其他可以纠正以产生一个更好的设计的设计失败。

体系结构设计

为何进行体系结构设计

体系结构是一种表述。使得软件工程师可以:

  1. 分析设计在满足规定需求方面的有效性

  2. 在设计变更相对容易的阶段,考虑体系结构可能的选择方案

  3. 降低与软件构造相关的风险。

体系结构风格(style)⭐

  1. 定义

    • 模式:每个模式是一个规则,表达了特定环境、问题和解决方式(solution)之间的关系

    • 体系结构风格:定义了一系列系统的结构组织的模式,它是对一类具有相似结构的系统体系结构的抽象

    • 同一个问题,可以有不同的解决问题的模式,但我们根据经验,通常会采用特定的模式,这就是风格

    • 软件风格是对软件构成带有整体性、普遍性、一般性的结构和结构关系的定义方法

    • 因此,软件风格是一种特定的基本结构。

  2. 每种风格描述一种系统类别,其中包括下列元素:

    • 一些实现系统所需的功能的构件

    • 连接各个构件,负责构件间通信和协作的连接器

    • 定义构件之间怎样整合集成的系统约束

    • 使设计者能够理解整个系统属性并分析已知属性的语义模型

  3. 典型的体系结构风格

    • 以数据为中心的体系结构

      一些数据(比如一个文件或者数据库)保存在整个结构的中心,并且被其他部件(构件)频繁地使用、添加、删除、或者修改

    • 数据流体系结构

      又称管道/过滤器体系结构风格

      这种结构适用于输入数据被一系列的计算或者处理构件变换成输出数据。

      优点:

      • 软件构件具有良好的隐蔽性和高内聚、低耦合的特点;

      • 合成简单;

      • 支持软件复用。只要提供适合在两个过滤器之间传送的数据,即可连接;

      • 系统维护和增强系统性能简单。支持新过滤器的添加和旧过滤器的替换;

      • 支持并行执行。每个过滤器是作为一个单独的任务完成,因此可与其它任务并行执行。

      缺点:

      • 每个过滤器都是一个完整的从输入到输出的转换,不适合处理交互的应用。
      • 系统的多个处理流之间的共同特性无法提取、多个过滤器之间的共同特性也无法提取,所以增加了设计的复杂性。
    • 调用返回体系结构

      这种风格使一个软件设计者设计出非常容易修改和扩充的体系结构

      • 主程序/子程序风格体系结构

        传统程序结构,功能分解为控制层次

      • 远程过程调用风格的体系结构

        该体系结构的构件分布在网络的多个计算机上

      • 程序结构的深度:程序结构的层次数称为结构的深度。结构的深度在一定意义上反映了程序结构的规模和复杂程度。

      • 程序结构的宽度:层次结构中同一层模块的最大模块个数称为结构的宽度。

      • 模块的扇出:扇出表示一个模块直接调用(或控制)的其它模块数目。

        • 多扇出意味着需要控制和协调许多下属模块
      • 模块的扇入:扇入则定义为调用(或控制)一个给定模块的模块个数。

        • 多扇入的模块通常是公用模块

      优点:

      • 可以使用自顶向下、逐层分解的方法得到体系结构图。

      • 采用程序设计语言支持的单线程控制。

      缺点:

      • 程序的正确性层级关联。

      • 函数和过程的调用必须明确知道函数名,过程名,正确的参数传递,降低了系统的灵活性。

    • 面向对象体系结构

      系统部件是对象,封装了数据和操作数据的方法

      部件之间的连接通过函数和过程调用进行。

      优点

      • 由于封装,实现了灵活性和扩充性,隐藏了实现的细节,提高代码的质量;

      • 使用继承和多态、提高了软件的可重用性。

      缺点:

      • 对象函数调用必须明确知道该对象的标识,降低了系统的灵活性。

      • 级联修改。只要一个对象的标识改变了,就必须修改所有其他明确调用它的对象,并消除由此带来的一些副作用。

      • 副作用。如果A使用了对象B,C也使用了对象B,那么,C对B的使用所造成的对A的影响可能是料想不到的。

    • 层次体系结构

      在这种结构中,定义不同的层次,每层都完成了相对外层更靠近机器指令的操作

      层次结构中每一层为上层服务,并作为下层的客户。

      最外层是用户可见,通常内部的层只对相邻的层可见。

      连接件通过决定层间如何交互的协议来定义,拓扑约束包括对相邻层间交互的约束。

      实例

      • TCP/IP的四层结构

      • OSI的七层结构(开放系统互连参考模型 )

      优点:

      • 支持基于可增加抽象层的设计。系统的开发和设计可以逐步的分层次的进行,从底层的简单的功能逐步建立高层的复杂和抽象的功能。

      • 灵活性和扩展性,由于相邻层次之间通过清晰的接口交互,所以特定的层次可以被替换和增强,甚至可以增加新的层次。

      • 支持复用。只要提供的服务接口定义不变(如定义一组标准接口),同一层的不同实现可以交换使用。

      缺点:

      • 不是所有的系统都可以分解成为清楚的层次。划分清晰、逻辑上一致的层次是非常困难的

      • 严格的层次调用结构会降低系统的性能。

        例如:如果不采用分层式结构,很多业务可以直接造访底层,如今却必须通过中间层来完成。

  4. 体系结构风格的组合和选择

    • 上述风格仅是软件体系结构风格中的一部分
    • 系统设计并不拘泥于仅一种风格
    • 具体风格或风格的组合应根据需求工程所揭示的系统的特征和约束来选择
    • 多数情况下会有多种风格适合
    • 需对可选的体系结构风格进行设计和评估

构件级建模

什么是构件

构件的设计原则:开关、替换、依赖倒置、接口分离⭐

  • 开关原则

    无需对构件内部逻辑进行修改就可以对构件的功能扩展。模块应该对外延具有开放性,对修改具有封闭性。

  • 替换原则

    继承必须确保超类所拥有的性质在子类中仍然成立。

    当一个子类的实例应该能够替换任何其超类的实例时,它们之间才具有is-a关系

    可度量继承关系的质量

    子类可以替换它们的基类。

    此原则要求源自基类的任何子类必须遵守基类与使用基类的构件之间的隐含约定。

  • 依赖倒置

    • 面向过程的开发

      上层调用下层,上层依赖于下层,当下层剧烈变动时上层也要跟着变动

      导致模块的复用性降低,提高了开发的成本

    • 面向对象的开发

      通过抽象解决这个问题

      让用户程序依赖于抽象,实现的细节也依赖于抽象

      即使实现细节不断变动,只要抽象不变,客户程序就不需要变化降低了客户程序与实现细节的耦合度

    依赖于抽象,而非具体实现。

    抽象可以比较容易扩展。

    构件依赖的具体构件越多,其扩展起来就越困难

  • 接口分离

    若多用户依赖同一个接口,则一旦接口发生改变,依赖该接口的所有用户都将受到影响

    多个用户专用接口比一个通用接口要好。

    安全接口:

    监视接口:

    分别对应于不同的客户端,一个是配置功能,一个是监督功能

    接口分离的实现

    • 接口的设计原则:最小接口原则

      不要把用户不使用的方法塞进同一个接口里。

    • 接口的依赖(继承)原则:同上

      接口继承时,也需注意不要包含该用户不使用的方法。

    • 若接口过胖,应将其分割成几个功能专一的接口。

内聚性、耦合性⭐

构件设计方法:PDL、程序流程图、决策表

测试

测试策略

单元测试⭐

针对程序中的模块或构件,主要揭露编码阶段产生的错误。

  1. 单元测试侧重于对软件设计的最小单元的验证工作。

  2. 单元测试的目的

    在开发环境中检查单元程序模块内部的逻辑、算法和数据处理结果的正确性等。

  3. 单元测试的内容主要是:

    算法逻辑、数据定义的理解和使用、接口、各种控制路径、边界条件、错误处理等。

  4. 面向对象环境中的单元测试

    • 软件设计的最小单元的变化

      最小可测试单元:类中的操作(方法)

      然而,由于类的继承、多态等特性,独立去测试某操作往往是无效的。

    • 面向对象环境中的单元测试主要是对类的测试

      类测试是由封装在该类中的操作和类的状态行为驱动的

      对操作的孤立测试不可取

集成测试⭐big bang、top down、bottom up

针对集成的软件系统,主要揭露设计阶段产生的错误。

是构造软件体系结构的系统化技术,同时也是进行一些旨在发现与接口相关的错误的测试。

  1. 为什么要进行集成测试?

    • 数据可能在通过接口时丢失;
    • 一个模块可能对另一个模块产生非故意的、有害的影响(即副作用);
    • 当子功能被组合起来时,可能不能达到期望的主功能;
    • 单个模块可以接受的不精确性(如误差),连接起来后可能会扩大到无法接受的程度;
    • 全局数据结构可能会存在问题。
  2. 传统的集成测试策略

    • 一步到位的集成方法(the “big bang” approach)

    • 增量式集成(an incremental construction strategy)

      • 自顶向下集成

        从主控模块(主程序)开始,然后按照程序结构图的控制层次,将直接或间接从属于主控模块的模块按深度优先或广度优先的方式逐个集成到整个结构中,并对其进行测试。

      • 自底向上集成

        从程序结构的最底层模块(即原子模块)开始,然后按照程序结构图的控制层次将上层模块集成到整个结构中,并对其进行测试。

    • 面向对象的集成测试策略

      • 面向对象软件无明显的层次控制结构,所以无法自顶向下集成或者自底向上集成;

      • 由于类的成分之间直接或间接的相互作用,往往无法每次仅集成一个操作。

      • 通常,面向对象系统集成测试有两种策略

        • 基于线程的测试(thread based testing)

          集成响应系统的一个输入或事件所需的一组类,每个线程单独地集成和测试。

        • 基于使用的测试(use based testing)

          先测试独立类,然后测试依赖类,直到整个系统集成成功

    • 回归测试

      对已经进行过的测试的子集的重新执行,以确保对程序的改变和修改,没有传播非故意的副作用

    • 冒烟测试

      daily building

      尽早发现可能造成项目延迟的业务阻塞错误

确认测试⭐

根据需求规约对软件进行确认,主要揭露不符合需求规约的错误。

主要检查:

  • 软件是否实现了规约规定的全部功能要求

  • 文档资料是否完整、正确、合理

  • 其他的需求,如可移植性、可维护性、兼容性、错误恢复能力等是否满足

系统测试⭐

对于基于计算机系统中的软件,还需将它集成到基于计算机系统中进行测试,以揭露不符合系统工程中对软件要求的错误。

对完整集成后的产品和解决方案进行测试,用来评价系统对具体需求规格说明的功能和非功能的符合性的测试

  • 系统测试的目的/作用:

    • 发现可能难以直接与模块或接口关联的缺陷
    • 发现产品设计、体系和代码的基础问题(产品级缺陷)
  • 系统测试=功能测试+非功能测试

    • 功能测试

      设计/体系结构测试、业务垂直测试、部署测试,等等

    • 非功能测试

      可伸缩性测试/容量测试、可靠性测试、压力测试、国际化测试、性能测试、安全性测试,等等

测试用例

测试技术

白盒、黑盒⭐
  • 黑盒

    也称为行为测试,把程序看作一个不能打开的黑盒子,不考虑程序内部结构和内部特性

    考察数据的输入、条件限制和数据输出,以完成测试

    测试方法:

    • 等价类划分
    • 边界值分析
    • 因果图
    • 错误推测法
    • 决策表方法
    • 正交试验法
  • 白盒

    也称结构测试或逻辑驱动测试

    基于内部逻辑结构,针对程序语句、路径、变量状态等来进行测试

    检验程序中的各个分支条件是否得到满足、每条执行路径是否按预定要求正确的工作

    测试方法:

    • 桌面检查
    • 代码走查
    • 代码审查
    • 逻辑覆盖
    • 基本路径测试
手工测试、自动化测试⭐
  • 静态分析通常只能进行手工测试,虽然也有辅助工具帮助,但仍以人为主体

  • 动态测试往往可以部分地或者全部自动化进行

    提供有效的测试用例集,通过测试平台对被测程序进行测试,跟踪并分析测试结果

  • 自动化测试的特点

    • 自动运行的速度快

    • 测试结果准确

      例如搜索用时是0.33秒或0.24秒,系统都会发现问题,不会忽视任何差异

    • 高复用性

      一旦完成所用的测试脚本,可以一劳永逸运行很多遍

    • 永不疲劳

    • 可靠

    • 独特的能力

  • 3

  • 手工测试和自动化测试

    • 两者互相补充
      • 在系统功能逻辑测试、验收测试、适用性测试、涉及交互性测试时,多采用手工测试方法;
      • 单元测试、集成测试、系统负载或性能、可靠性测试等比较适合采用自动化;
      • 由于工具本身缺乏想象力和创造性,自动测试只能发现15%的缺陷,而手工测试可以发现85%的缺陷

软件项目管理

项目管理概述

4 P‘s⭐

人员(people)产品(product)过程(process)项目(project)

W5HH⭐

why is the system being developed

what will be done

when will it be accomplished

who is responsible

where are they organizationally located

How will the job be done technically and managerially

how much of each resource(e.g.,people,software,tools,database)will be needed

度量

度量的作用⭐

度量的作用是为了有效地采用定量的方式来进行管理

管理人员利用度量来了解软件工程过程的执行情况和产品质量

过程度量作用:提供能够引导长期的软件过程改进的一组过程指标。

项目度量作用:使得软件管理者能够(1)评估正在进行中的项目的状态(2)跟踪潜在的风险(3)在问题造成不良影响之前发现它们(4)调整工作流程或任务(5)评估项目团队控制软件工作产品质量的能力

产品度量作用:为分析,设计,编码和测试能更客观地执行和更定量的评估提供基础

面向规模的度量

软件规模通常是指软件的大小(size),一般用代码行度量

  • 优点:方便、直观

  • 缺点:很大程度上取决于程序设计语言以及软件设计的质量

面向功能的度量

估算

WBS⭐

work breakdown structure

其分解方式为

  • 产品分解:将一个复杂问题分解成若干个小问题

  • 过程分解:根据软件开发过程中的活动(分析、设计、编码、测试等)进行分解

常用估算方法(名字)⭐

  • 基于已经完成的类似项目进行估算,这是一种常用的也是有效的估算方法

  • 基于规模的估算

    • 基于LOC的估算
    • 基于FP的估算
  • 基于经验估算模型的估算

    COCOMO模型等

进度

任务网络、关键路径的作用

甘特图的作用⭐

甘特图(Gantt Chart)也称时间表(Timeline chart),用来建立项目进度表

为监控软件项目的进度计划和工作的实际进展情况,表现各项任务之间进度的相互依赖关系

需要采用图示的方法明确标识:

  • 各个任务的计划开始时间和完成时间

  • 各个任务的完成标志

  • 各个任务与参与工作的人数,各个任务与工作量之间的衔接情况

  • 完成各个任务所需的物理资源和数据资源

里程碑⭐

在甘特图中,每项任务的完成以必须交付的文档和通过评审为标准,因此它们往往作为项目里程碑 (一般情况下是评审活动)

作用:敏捷、详细、可度量、可分配、现实性、期间时限

风险

被动和主动风险管理

risk management paradigm(主动风险管理过程)⭐

  • 风险识别
  • 风险分析
    • 风险预测
    • 建立风险表
    • 风险评估
  • 风险规划(RMMM)
    • 风险避免
    • 风险监测
    • 风险管理及应急计划
  • 风险监控

RMMM⭐

对于每个中截线以上的风险,都应制定RMMM,RMMM的实施会导致额外的项目开销

质量

McCall软件质量模型⭐

McCall的质量因素:侧重于三个方面:操作特性(正确性、可用性、效率、可靠性、完整性),修正(可维护性、灵活性、可测试性),转移(可移植性、可复用性、互用性)

4

软件质量保证活动

质量保证由管理层的审计和报告构成,目标是为管理层提供获知产品质量信息所需的数据,从而获得产品质量是否符合预定目标的认识和信心

由两类不同的角色承担

  • 负责技术工作的软件工程师:通过采用可靠的技术方法和措施、进行正式的技术评审、计划周密的软件测试来考虑质量问题,并完成软件质量保证和质量控制活动

  • 负责质量保证工作的SQA (Software Quality Assurance)小组:辅助软件工程小组得到高质量的最终产品

正式技术评审⭐

通常在软件工程过程的每个活动的后期进行

采用正式的会议评审方式

通过正式评审意味着里程碑和基线

5

  • 评审记录

    指派专人记录会上提出的所有问题

    会议结束后将其整理成一份”评审问题列表”并存档

  • 评审报告

    评审结束后形成报告,报告应指明被评审的制品,参加评审的人员,评审中发现的问题以及评审的结论

    “评审问题列表”可作为评审总结报告的附件

软件质量的成本

变更

软件配置项、版本、基线等概念⭐

  • 软件配置项(Software Configuration item,SCI)

    为配置管理设计的软件工作产品的集合,它在配置管理过程中作为单个实体对待。

  • 配置管理(Configuration management):应用技术的和管理的指导和监控方法以

    • 标识和说明配置项的功能和物理特征

    • 控制这些特征的变更

    • 记录和报告变更处理和实现状态

    • 验证与规定的需求的遵循性

  • 版本(Version):与计算机软件配置项的完全编篡或重编篡相关的计算机软件配置项的初始发布或再发布。

  • 发布(Release):一项配置管理行为,它说明某配置项的一个特定版本已准备好用于特定的目的(例如发布测试产品)

  • 基线(baseline):业已经过正式审核与同意,可用作下一步开发的基础,并且只有通过正式的修改管理过程方能加以修改的规格说明或产品

软件配置管理流程⭐

  • 标识:为控制和管理软件配置项,必须对每个配置项单独命名,然后用面向对象方法进行组织。可以进行标识的对象:基本对象和聚合对象。
  • 变更控制:6
  • 版本控制:结合规程和工具,用来管理在软件过程中所创建的配置对象的不同版本。
  • 配置审核:通过正式技术评审或软件配置审核来保证变更的有效性。是正式技术评审的补充。
  • 报告:配置状态报告CSR(状态记录),解答了问题,发生什么事,是谁做的,什么时候发生的,会影响到别的什么。可使管理者和开发人员可以评估重要的变更。

识别可能发生变更的工作产品,制定管理这些工作产品的不同版本的机制,控制所施加的变更,审核和报告所发生的变更m