笔记 | 高级软件工程与导论

在软工系列课程上,老师常提及的一条等式 软件 = 程序 + 软件工程 ( 或 软件 = 程序 + 文档),即一般情况讨论,一款软件产品的诞生之际总是伴随着一系列的软件过程。

那么如何充分理解软件工程 (过程)?从本书作者理念出发,我所理解的即应该时刻对软件产品持有 生命周期 的思维模式,将 需求、建模、设计、实现、测试、维护 等工程阶段联系起来,以自身代入案例环境中,去模拟开展软件过程的一系列活动,而非割裂。而这样的动态过程中,不仅仅是枯燥地学习理论、方法,则更像是问题所需、问题导向的理论应用过程。

当然,软件工程作为一门工程学科,学习过程的最大收获可以说是对 项目思维模式 的掌握。譬如,我们可以抛开软件产品的范畴,谈谈现实生活的实例:假若你需要在一定时限内掌握一门新知识、任务,则我们的做法可以从调研、计划、布局、实施,直至验收,即类似的过程可复用软件工程的方法。

最后,也是想声明的一点:学习软件工程的过程中,无可避免地将反映本人的一些观点、倾向,当然这也反映该学科需要 多沟通 的特点,若有不恰当、错误之处,欢迎大伙出建议、斧正。

  • 参考书目:
    • 《 软件工程 》. Ian Sommerville 著:计算机科学丛书,且是著名软件工程学家 Ian Sommerille 系统介绍软件工程理论的经典教材。
    • 《 构建之法(第二版) 》: 待整理。贴上本书豆瓣的书评,供朋友评判,做出抉择。构建之法(第二版)

更新进程

  • 2018.05.02:完成初稿;
  • 2018.05.04:更新正文:导论部分 (第 4 / 8 章);

零 内容总览

壹 软件过程

  • 学习目标
    • 3个一般的 软件过程模型
    • 了解软件需求工程、开发、测试和进化中所涉及的 基本过程活动
    • 理解为什么软件过程要有效地组织以应对软件需求和设计上的变更;
    • Rational 统一过程 (RUP).
  • 软件过程必须具有的基本活动
    • 软件描述
    • 软件设计和实现
    • 软件有效性验证
    • 软件进化
  • 没有“理想”的软件过程 — 寻找平衡点
    • 计划驱动过程:提前计划好所有的过程活动,再按计划去考核过程的执行。
    • 敏捷过程:计划是增量式的,且容易根据不断变化的客户需求变更过程。更多详细内容见 第叁章

软件过程模型

  • 软件过程:产生一个软件系统的一系列活动。
  • 软件过程的简化表示 (抽象表示)。
  • 每个过程模型都是从一个特定的侧面表现软件过程,所以只提供过程的部分信息。

    如过程活动模型表现了这些活动和他们的顺序,但可能表现不出人们在这些活动中的角色。

瀑布模型

图1-1瀑布模型

图 1-1 瀑布模型
  • 计划驱动模型;
  • 该模型将基本的过程活动、描述、开发、有效性验证和进化,看成是一些界限分明的独立的过程阶段。
    • 需求分析和定义:通过咨询系统用户建立系统的服务、约束和目标,并对其详细定义形成系统描述。
    • 系统和软件设计
      • 系统设计 — 建立系统的总体体系结构,将需求区分为硬件需求和软件需求。
      • 软件设计 — 识别和描述一些基本的软件系统抽象及其之间的关系。
    • 实现和单元测试
      • 软件设计实现 — 实现为一组程序或程序单元。
      • 单元测试 — 验证每个单元是否符合其描述。
    • 集成和系统测试
      • 集成 — 集成单个的程序单元或一组程序。
      • 系统测试 — 评估系统的可靠性;是否满足软件需求。
    • 运行和维护

增量式开发

图1-2增量式开发

图 1-2 增量式开发
  • 即可是计划驱动的,也可是敏捷方法的。
    • 系统增量是提前定义好的,即为 计划驱动方法
    • 最初的增量是定义好的,但往后的增量的开发取决于项目的进展情况及客户的优先选择,即为 敏捷方法
  • 系统的开发是建立一系列的版本 (增量) 每个版本添加部分功能到先前版本中。
  • 增量式开发的特性
    • 降低了适应用户需求变更的成本。
    • 开发过程中及时得到用户已做的开发工作的反馈意见。
    • 更快地交付和部署有用的软件到客户方。

面向复用的软件工程

基于复用开发的一般过程模型如图 1-3 所示。初始需求描述阶段、有效性验证阶段与其他过程差不多,面向复用过程的中间阶段是不同的。

图1-3面向复用的软件工程

图 1-3 面向复用的软件工程
  • 中间阶段:即组件分析、需求修改、使用复用的系统设计、开发和集成阶段。
    • 组件分析:需求描述 -> 搜组件 (往往只提供所需的部分功能)。
    • 需求修改:根据得到组件信息分析需求,再修改需求以反映可得到的组件。
    • 使用复用的系统设计:设计系统的框架或者重复使用一个已存在的框架。
    • 开发和集成

过程活动

软件描述

  • 软件描述或需求工程是理解和定义系统需要提供什么样的服务,以及找出开发和运行中受到哪些约束。
  • 需求工程过程的主要阶段,如图 1-4 所示。
    • 可行性研究
    • 需求导出和分析
    • 需求描述
    • 需求有效性验证

图1-4需求工程过程

图 1-4 需求工程过程

软件设计和实现

  • 软件设计和实现阶段是把系统描述转换成一个可运行的系统的过程。
  • 软件设计是对实现软件的结构、系统的数据、系统组件间的接口以及所用的算法的描述。这是一反复、迭代的过程。

软件有效性验证

  • 程序测试:用模拟测试数据运行系统。
  • 测试过程各阶段
    • 组件 (单元) 测试:每个组件单独测试;组件可是简单实体,如函数、对象类或这些实体的集合。
    • 系统测试:集成组件形成完整系统,对组件组成的子系统测试。
    • 接收测试:客户提供真实数据测试系统。

软件进化/软件维护

软件工程不再是开发和维护两个独立的过程,而是一个进化过程。即软件在其生命内不断随着需求的变更而变更的进化式过程。

图1-5系统进化

图 1-5 系统进化

应对变更

  • 有效降低变更成本
    • 变更避免:预测变更,如 原型系统 的开发,客户试用原型,在花费高额的软件生产成本之前重新定义需求。
    • 变更容忍:增量开发,即使单个增量(系统一小部分)的修改来适应变更,以较低成本处理变更。
  • 应对变更系统需求的方法
    • 系统原型:快速开发一个系统版本或系统一部分,以检验客户需求和某些设计决定的可行性,即它支持 变更避免
    • 增量交付:系统增量地交付给用户,给用户评审和试用。即它支持 变更避免变更容忍

原型构造

  • 原型是一个软件系统的最初版本,用于验证概念、试用设计选项、发现更多的问题和可能的解决方法。
  • 原型开发的过程模型如图 1-6 所示。

    图1-6原型开发的过程

    图 1-6 原型开发的过程

    最后一阶段:原型评估,则必须安排用户培训,应根据原型的目标制定一个评估计划。即用户需习惯并适用新系统,一旦他们自然地使用了系统,将可能发现错误和被遗漏的需求。

  • 不强求原型是可执行的。

    基于纸质的模型系统的用户界面,用户和这个界面交互,但他们的请求被传递给一个人,该人员解释此请求并输出相应的响应。

增量式交付

  • 增量式开发是软件开发的一种方法,如图 1-7 所示。

    图1-7增量式交付

    图 1-7 增量式交付
  • 增量式开发过程的好处

    • 早期的增量作为原型,从中获得对后面系统增量的需求经验。
    • 每一增量会满足他们大多数需求,即软件马上就能使用。
    • 具有高优先权的服务被首先交付,而后继有增量不断被集成进来,使得最重要的系统服务接受了多次测试。
  • 增量式交付存在的问题
    • 软件描述和软件本身一起开发是迭代过程的本质。在增量方法中,直到最后的增量描述完成,才会有完整的系统描述。而许多机构 (如政府) 的采购模型是,系统开发合同中附带完整的系统描述,即相互冲突。
    • 旧系统的所有功能与新系统的部分功能,多数用户宁可选前者,即获取反馈较困难。

Boehm 的螺旋模型

  • 风险驱动的软件过程框架 (螺旋模型)
    • 在螺旋线中每个回路表示软件过程的一个阶段,如最里的回路可能与系统可行性研究有关,下一回路与系统需求定义有关等。
    • 螺旋线中每个回路被分成4部分:
      1) 目标设置
      2) 风险评估和规避
      3) 开发和有效性验证
      4) 规划

Rational 统一过程

  • RUP 一般从3个视角描述过程
    • 动态视角:给出模型中随时间所经历的各个阶段。
    • 静态视角:给出所进行的过程活动。
    • 实践视角:提出在过程中可采用的良好实践建议。
  • RUP 是一阶段化模型,如图 1-8 所示。

    • 开端
      • 目标是建立系统的一个业务案例。
      • 识别所有与系统交互的外部实体 (人和系统) 并定义这些交互。
      • 适用这些信息评估系统对业务的贡献,若贡献微小,那么项目在此阶段结束。
    • 细化
      • 目标是增进对问题域的理解,建立系统的体系框架,给出项目计划并识别关键项目风险。
      • 输出系统的需求模型 (描述的用例、体系结构描述及开发计划)。
    • 构造:系统设计、编程和测试。
    • 转换:将系统从开发单位转移到用户单位,并使之在真实环境中工作。

      1) RUP 中的阶段是紧密与业务关联,而不是与技术层面关联。
      2) RUP 把 阶段 (开端、细化、构造、转换) 和 工作流 (需求、分析、设计…) 分离,即各种 RUP 工作流在整个过程的所有阶段都是可能存放的。

      图1-8Rational统一过程的各阶段

      图 1-8 Rational 统一过程的各阶段
  • 实践视角

    • 迭代地开发软件;
    • 对需求的管理:记录并跟踪客户的需求;
    • 使用基于组件的体系结构,将系统体系结构组织成组件形态;
    • 可视化地建模软件:UML 模型表现软件的静态、动态视图;
    • 检验软件质量;
    • 控制对软件的变更:变更管理系统、配置管理程序和工具来管理软件的变更。
  • 静态视角

    • 聚焦在开发过程中所发生的活动上,这些在 RUP 描述中被称为工作流。
    • 此过程中包含6个核心过程工作流,3个核心支持工作流,见图 1-9 所示。

      图1-9RUP中的静态工作流

      图 1-9 RUP 中的静态工作流

贰 敏捷软件开发

开始敏捷开发篇章前,引入一有趣的例子。Jazz Band 模式,跟 “敏捷的开发模式” 类似,同样也可以产生优秀的作品。( 演奏中,Miles Davis 先用小号吹出主题 ( 类比为架构师 ),然之后到一旁抽烟。曲目交由其他人员即兴发挥。最后, Miles Davis 加入演奏,回应主题 )。

感兴趣的可以观看视频:Miles Davis So What

  • 学习目标
    • 理解敏捷软件开发方法的基本原理、核心内涵,以及它与计划驱动软件开发方法的差别;
    • 极限编程;
    • 理解敏捷项目管理的 Scrum 方法;
    • 应用伸缩的敏捷方法时的事项和问题 -> 大型软件系统开发过程.

敏捷方法

  • 敏捷方法是一种专注于快速开发的 增量式开发频繁地发布软件降低过程开销、生产高质量代码。他们使用户直接参与到开发过程中。
  • 敏捷方法的基本原理体现在 敏捷宣言 中:

    • 个体和交互胜过工具和过程;
    • 编写软件胜过书写详尽文档;
    • 用户合作胜过合同谈判;
    • 响应变更更胜过遵循计划.

      即我们更重视左边的项的价值,虽左右两边的项都有价值。

  • 大量的软件工程努力维护和进化现有的软件系统,而由敏捷方法的特性可知,敏捷方法维护的问题有:

    • 软件交付后的主要困难可能是继续让用户参与到过程中。
    • 保持开发团队的持续性,因没有参考文档可循,若一个敏捷开发团队解散了,则 依赖于团队成员理解系统隐式知识 旧丢失了。
  • 混成方法:敏捷方法嵌入来自计划计划驱动式开发的某些技术。

计划驱动开发和敏捷开发

计划驱动和敏捷描述如图 2-1 所示。

图2-1计划驱动和敏捷描述

图 2-1 计划驱动和敏捷描述
  • 敏捷方法:
    • 迭代发生在所有活动间。
  • 计划驱动方法:

    • 迭代发生在各个活动中,用 正式文件 在软件过程中各阶段间沟通。

      正式文件:可视化作为各阶段的输出产物。

  • 在计划驱动和敏捷方法之间得到平衡,必须回答以下一些技术的、人员的和机构方面的问题。
    • 详尽的描述和设计 -> 计划驱动开发
    • 交互用户并快速取得反馈 -> 敏捷开发
    • 开发系统的规模;
    • 开发的系统类型,如有复杂时序需求的实时系统,通常需要相当详细的设计来实现分析 -> 计划驱动开发
    • 预想的系统寿命有多长;
    • 什么样的技术支持系统开发 (敏捷方法通常依赖于工具,以跟踪设计进化);
    • 开发团队的组织情况;
    • 影响系统开发的文化问题 (传统的工程机构有计划驱动的文化);
    • 开发团队的成员专业水平;
    • 系统是否受制于外部法规 (如联邦的航空管理局 FAA 核准一个安全性要求极高的航空操作软件);

极限编程 (XP)

  • 极限编程所属敏捷方法,它集成了一系列好的编程经验。例如,频繁地软件发布、连续软件改善和客户参与到软件开发团队。
  • XP 中,所有的需求都表示为脚本 (称为用户故事情节),它将直接实现为一系列任务。
  • 一个 XP 过程,产生了正在开发的系统的一个增量,具体如图 2-2 所示。

图2-2极限编程的版本循环

图 2-2 极限编程的版本循环
  • 脚本卡是 XP 规划过程的主要输入。
    • 开发团队把每个 脚本 拆分成 任务,并估计实现所需人力资源。
    • 与客户交谈,定义需求,对脚本进行优先权排序。

极限编程中的测试

  • 很多增量开发方法的测试过程是很不规范的。
  • 为避免一些测试和系统验证方面的问题,XP 方法更加强调测试过程。
  • XP 当中测试的关键特性:
    • 测试优先的开发 (先写测试程序再写代码);
    • 来自脚本的增量式测试开发;
    • 用户参与测试开发和有效性验证;
    • 自动测试系统的使用。将测试写成了可执行的组件,该测试组件是独立的。自动测试框架即是这样的一个系统。譬如 Eclipse 的 JUnit,JUnit 用于单元测试。

结对编程

结对编程是有一些质量效益,但却不足以抵消它的开销。但信息共享在结对编程是很重要的,因为当有团队成员离开时,它降低了项目风险。

敏捷项目管理

  • 项目管理的标准:计划驱动。
  • 适合增量开发 (敏捷方法) 的管理方法 (框架):Scrum

    • Scrum 的管理过程如图 2-3 所示。

      图2-3Scrum的管理过程

      图 2-3 Scrum 的管理过程
    • Scrum 的 3 个阶段

      • 规划纲要阶段:建立大致的项目目标和设计软件体系结构。
      • 冲刺循环阶段:
        • 每个循环开发出一个系统增量;
        • 每个循环为一个计划单元,其中的工作有评估、特征选择和开发、软件实现;
      • 项目结束阶段:完善文档,如系统帮助和用户手册。
      • 冲刺循环阶段的特征:

        • 冲刺有固定长度,一般是 2-4 周,在 XP 过程中对对应与一个系统版本的开发。
        • 规划的起点,即积压的任务 (Backlog),也是项目中要完成的工作清单。
        • 评估阶段:Backlog 需经过审查,并对它们进行优先级排序和风险指派。
        • 选择阶段:项目所有成员都要参加,和用户一起选择冲刺循环中要开发的特性和功能。
        • 开发阶段:达成共识将组织进行软件开发,每一天团队开发成员参与段时间会议,回顾开发过程,若有必要重新安排工作。且在此阶段开发团队是隔离于客户和机构的。
        • 冲刺循环阶段结束,对已做工作复查并交付给用户。

          所有交流都是通过 Scrum Master 进行,SM 可理解为调解人。体现了 Scrum 的思想,即整个团队被赋予决定的权利。

    • Scrum 适合分布式的开发环境。

可扩展的敏捷方法

  • 敏捷方法的开发是为同一房间办公与交流的小团队开发使用,因此常被用于小型系统开发。
  • 可伸缩的敏捷方法也可适用于开发大型系统。
  • 大型、小型系统开发的区别 (可理解为可扩展的敏捷方法应用于大型系统的挑战)。
    • 大型系统经常由独立的、交互的子系统组成。不同团队独立开发不同子系统,且团队可能在不同地点或不同时区工作。
    • 大型系统包含了一系列的已存在的系统并与它们进行交互,许多系统需求关注这种交互。
    • 当一个系统由多个系统集成产生时,开发工作中重要部分是系统配置而不是原始代码开发。这不一定与增量式开发和频繁的系统集成兼容。
    • 大型系统通常具有不同的信息持有者,将不同的信息持有者加入开发流程中是必要的。
  • 伸缩的敏捷方法的两个观点
    • 照搬放大,即关注如何将这些方法应用到哪些 小团队 无法开发的 大型项目 中。
    • 渗透,即关注如何将敏捷方法介绍 推广 到拥有多年开发经验的 大机构 中。

叁 需求工程

  • 学习目标

    • 了解用户需求、系统需求;
    • 了解功能需求、非功能需求;
    • 如何在软件需求文档中 机构需求
    • 了解需求工程活动的内容及他们之间的关系;
    • 了解需求管理.
  • 一些概念

    • 用户需求:用自然语言加图的形式给出的关于系统 需要提供 哪些服务及系统操作受到哪些 声明的约束

      高层 (抽象) 的概要需求。

    • 系统需求:详细给出系统 将要提供 的服务及系统所受到的约束。系统的需求文档也称功能描述。

      系统应提供哪些服务的详细描述。

功能需求与非功能需求

  • 功能需求
    • 描述系统所提供的功能或服务。
    • 若是用户需求,就要用可以被系统用户理解的一种抽象方法描述功能需求。
    • 更具体的功能性系统需求则需要详细地描述系统功能、异常、输入和输出。
  • 非功能需求

    • 指那些不直接关系到系统向用户提供的具体服务的一类需求。简言之,他们对 系统实现 定义了 约束,如 I/O 设备的能力、与其他系统接口的数据的表示。
    • 非功能性系统需求:通常会从总体上规范或约束系统的特性。

      若一个非功能系统需求没有满足则可能使整个系统无法使用。

    • 非功能需求分类:表明非功能需求或是来源于所要求的软件特性 (产品需求),或是来源于开发软件的机构 (机构需求),或是来源于外部来源。如图 3-1 所示。

      图3-1非功能需求的类型

      图 3-1 非功能需求的类型

软件需求文档

  • 如表 3-1 所示,是基于 IEEE 标准的需求文档的结构。
    • 需求文档中内容的详细程序,取决于所要开发的系统的类型及所使用的开发过程。
表 3-1 需求文档结构
章节 描述
绪言 定义文档的读者对象,说明版本的修正历史,包括新版本为什么要创建,每个版本间的变更内容的概要
引言 描述为什么需要该系统,简要描述系统的功能,解释系统是如何与其他系统协同工作的。描述该系统在机构总体业务目标和战略目标中的位置和作用
术语 定义文档中的技术术语和词汇。假设文档读者是不具有专业知识和经验的人
用户需求定义 这一部分要描述系统应该提供的服务以及非功能系统需求,该描述可以使用自然语言、图表或者其他各种客户能理解的标记系统。产品和过程必须遵循的标准也要在此定义
系统体系结构 这一部分要对待建系统给出体系结构框架,该体系结构要给出功能在各个模块中的分布。能被复用的结构中组件要用醒目方式示意出来
系统需求描述 这一部分要对功能和非功能需求进行详细描述。如有必要,对非功能需求要再进一步描述,例如定义与其他系统间的接口
系统模型 这一部分要提出一个或多个系统模型,以表达系统组件、系统以及系统环境之间的关系。这些模型可以是对象模型、数据流模型和语义数据模型
系统进化 这一部分要描述系统基于的基本设想和定位以及硬件和用户需求改变时所要做的改变。这部分对系统设计人员来说是有用的,因为这有助于他们避免一些设计决策,这些决策可能会限制未来系统的变更
附录 这一部分要提供与开发的应用有关的详细、专门的信息。该附录的例子是硬件和数据库的描述,硬件需求定义了系统最小和最优配置,数据库需求定义了系统所用的数据的逻辑结构和数据之间的关系
索引 可以包括文档的几个索引。除了标准的字母顺序索引外,还可以有图标索引、功能索引等

需求描述

  • 即在需求文档中写下用户需求和系统需求。
    • 用户需求:从用户角度来描述系统功能需求和非功能需求,一般用自然语言、图形叙述。
    • 系统需求:
      • 用户需求的扩展;
      • 软件工程师开始系统设计的起点;
      • 解释如何能让系统提供用户需求.
  • 原则上系统需求应 反描述 系统的 外部行为 和对它的 操作限制,而不是描述系统如何设计、实现。

    当然,并不是不提及任何设计信息,这也是不可能的,例如系统初始的体系结构设计。

自然语言描述

  • 在使用自然语言书写需求时,为了尽力 减少误解,应有一些简单的指导原则:
    • 设计一个 标准格式,并保证所用的需求定义都遵循此格式书写。
    • 使用一致性的语言来区分强制性需求和可选性需求。
      • 强制性需求:必须支持的,定义时使用 必须
      • 可选性需求:不是必要的,定义时使用 应该
    • 对文本加亮 (粗体、斜体、颜色) 来突出显示关键性需求。
    • 避免使用专业术语和缩写语 (无法避免时应该在有标注说明)。
    • 任何情况下,都应尝试把需求原理和每一个用户需求联系起来。

结构化描述

  • 使用结构化方法来描述系统需求,则先为需求定义一个或多个的 标准模板,并将模板表示成结构化的表格形式。如表 3-2 所示,是胰岛素泵需求的结构化描述。
表 3-2 胰岛素泵需求的结构化描述
项目名称 胰岛素泵/控制软件/SRS/3.3.2
功能 计算胰岛素剂量;安全的胰岛素水平
描述 计算所要传输的胰岛素剂量,这是在当前度量的血糖水平处于 3-7 个单位之间这样正常范围之内时的胰岛素计算
输入 当前血糖读数 (r2),先前的两个读数 (r0, r1)
来源 来自传感器的当前血糖读数。其他读数来自内存
输出 CompDose:所要传输的胰岛素剂量
目的地 主控制循环
行动 如果血糖水平是稳定的或往下掉或是上升但速率下降,则 CompDose 为 0。若血糖的水平是在上升且上升速率也上升,那么 CompDose 的计算方法是求当前血糖水平和先前血糖水平,再除以 4 并取整。若取整的结果为 0,那么 CompDose 就被设置成可以传输的最小剂量
需求 两个先前的读数,这样血糖变化速率就可以计算出来了
前置条件 胰岛素池容纳至少是单个传输剂量的最大值
后置条件 r0 被 r1 替换,然后 r1 被 r2 替换
副作用
  • 标准格式描述功能需求时,应包括下列信息:
    • 关于所定义的功能或实体的描述;
    • 关于输入及输入来源的描述;
    • 关于输出及输出去向的描述;
    • 关于计算所需要的信息及系统中所使用的其他实体信息;
    • 关于所采取的行动的描述;
    • 如果使用一个功能方法,前置条件、后置条件的设定描述;
    • 关于操作的副作用,没有则填写无.

需求工程过程

  • 需求工程过程包括4个高层活动:
    • 系统可行性研究:评估系统是否对业务有用。
    • 需求导出和分析:需求发现。
    • 需求描述:将需求转变为某种标准格式描述。
    • 需求有效性验证:检验需求是否正确地定义了客户所希望的系统。
  • 在实际需求工程是一个活动相互交错的迭代过程,如图 3-2 体现了这种交错性。

图3-2需求工程过程的螺旋模型

图 3-2 需求工程过程的螺旋模型

需求导出和分析过程

  • 反复的过程,也可看做是一种 螺旋式活动
  • 需求发现 (需求导出)
    • 对准备建立的系统和正使用的系统进行信收集,并从中提取用户需求和系统需求的过程。
    • 信息持有者 通过交谈和观察进行交互,即可使用 用例原型 来帮助对方理解系统。
  • 采访
    • 封闭式采访:即信息持有者回答一组 锁定的问题
    • 开放式采访:需求工程团队 即兴访问,更深层次了解对方需求是什么。
  • 脚本
    • 脚本是对 交互实例片段 的描述。
    • 脚本开始于一个 交互框架,在导出过程中细节增加,直至产生一完整的交互描述。
    • 脚本的内容
      • 开始部分有一系统和用户期望的描述;
      • 标准事件流的描述;
      • 处理错误的描述;
      • 完成后系统状态的描述.
  • 用例
    • 统一建模语言 (UML) 的基本特征。
    • 用例的集合代表所有将会在系统需求中出现的交互。过程中的角色可为人、其他系统等。
    • UML 对于面向对象模型来说,是一约定俗成的标准,因此基于用例的导出被广泛应用于需求导出中。
  • 深入实际:如图 3-3 所示的需求分析的深入实际方法和原型法。

图3-3需求分析的深入实际方法和原型法

图 3-3 需求分析的深入实际方法和原型法

需求有效性验证

  • 有效性检查:任何一组需求都不可避免地要在不同用户之间协商。
  • 一致性检查:需求不应该彼此冲突。
  • 完备性检查:需求文档应包括所有系统用户想要的功能和约束。
  • 真实性检查:检查需求以保证需求能真正实现。
  • 可检验性检查:检查方法 -> 验证需交付的系统 -> 满足定义的需求。
    • 需求评审:主要是错误检查和不一致检查。
    • 原型建立:提供一可执行的系统模型,客户和最终用户在此基础检查系统。
    • 测试用例生成。

需求管理

  • 大型软件系统的需求总是在变化的,即开发这些系统需满足某些棘手问题,则这些问题不可能被完全定义。如图 3-4 所示为需求进化的过程。

图3-4需求进化过程

图 3-4 需求进化过程

需求管理规划

  • 需求识别:每一需求有 唯一标识码
  • 变更管理过程:变更带来的影响和成本的评估活动。
  • 可追溯策略:策略 定义了需求间和需求与系统设计间的 关系;关系是要记录的,并附有记录的 维护方法
  • 工具支持

    • 需求存储
    • 变更管理:如图 3-5 所示,即变更过程由有效工具来支持。
    • 可追溯性 管理:需求间的 关联 <- 自然语言处理技术 (NLP)

      图3-5需求变更管理

      图 3-5 需求变更管理

需求变更管理

  • 问题分析和变更描述:问题或变更 -> 检验有效性 -> 反馈变更请求者 -> 导致两种结果:
    • 更加详尽的需求变更、提议;
    • 取消本次变更.
  • 变更分析和成本计算:需求文档修改、系统设计和实现的成本估算。
  • 变更实现:与编写程序类似,文档的 可追溯性关联性 是通过最小化外部引用和尽量使之模块化来实现的。

肆 系统建模

  • 学习目标
    • 如何用图形模型表示软件系统;
    • 基本的建模角度 (如上下文、交互、结构、行为等);
    • 统一建模语言 (UML);
    • 模型驱动工程.
  • 系统建模:建立系统抽象模型的过程
    • 图形建模;
    • 形式化建模 (数学模型).
  • 不同角度表述系统 与 第陆章 中的「4+1」视图相仿
    • 外部 — 上下文模型:系统上下文;系统环境;
    • 交互 — 交互模型:系统与环境之间;系统各组成部分之间;
    • 结构 — 结构模型:系统的体系结构;
    • 行为 — 行为模型:系统的动态行为和它对事件响应方式.

上下文模型

  • 定义系统边界:定义系统上下文和系统与环境之间的依赖关系。
  • 上下文模型表示某一环境包括几个其他的自动系统 (忽略子系统之间及待描述的系统与它们之间的关联关系的类型)。
  • 结合业务过程模型

    • 活动图:如图 4-1 所示。

      图4-1活动图

      图 4-1 活动图

交互模型

  • 为用户交互建模 -> 识别用户需求。
  • 为系统各部分之间的交互建模 -> 系统结构能否实现系统所需的功能及其可靠性。

用例建模

  • 用例图:如图 4-2 所示。

图4-2用例图

图 4-2 用例图

  • 时序图:表示在特定用例中的交互发生顺序。如图 4-3 所示。

图4-3时序图

图 4-3 时序图

结构模型

课本第 6、18、19 章讲述软件体系结构的不同方面和软件体系结构建模。

  • 静态模型:表示系统设计的结构。
  • 动态模型:表示系统执行时的构成。

类图

  • 类图可表示系统中的类和这些类之间的关联。

    类与类之间的链接,表示类与类之间具有某种关系。

    • 简单类图:如图 4-4 所示。其中一对多关系的类图,类似于语义数据模型,即数据实体、与他们相关的属性。

      图4-4简单类图

      图 4-4 简单类图
    • 扩展类图:如图 4-5 所示。

      图4-5扩展类图

      图 4-5 扩展类图

泛化

  • 推断一些类的成员具有的某些共同特征,针对类的所有成员给出一般性的描述。如图 4-6 所示。

图4-6泛化关系

图 4-6 泛化关系

聚合

  • 一个对象 (全体) 可有由其他对象 (部分) 组成。如表示一条病人记录由 Patient 和一个不确定的 Consulation 组成。如图 4-7 所示,表示了一条病人记录由 Patient 和一个不确定的 Consulation 组成。

图4-7聚合关系

图 4-7 聚合关系

依赖

如图 4-8 所示,展示了依赖关系。

图4-8依赖关系

图 4-8 依赖关系

行为模型

  • 描述系统运行时的动态行为的模型,表示系统响应于所处环境的刺激所发生或可能发生的事情。
  • 刺激:数据事件
    • 数据:一些数据到达必须由系统处理。
    • 事件:某些触发系统处理的事件的发生。

数据驱动的建模

  • 数据驱动模型描述一个 动作序列,该动作序列涉及输入数据的处理和相关 输出的产生

    输出的产生:指系统的响应。

  • 处理序列的方法:

    • 时序图:强调系统中的对象。
    • 数据流图 (DFD):关注于功能。

事件驱动模型

  • 事件驱动模型表示系统对内、外部事件的响应方式。
  • 基于事件的模型表示方法:状态图,表示系统状态和引起状态和引起状态改变的事件。其中状态图的表示如图 4-9 所示。

图4-9状态图

图 4-9 状态图

模型驱动工程

  • 模型驱动工程 (MDE) 起源于模型驱动体系结构 (MDA),该体系由对象管理组织 (OMG) 提出。
  • 支持者与反对方:
    • 支持者:更高的抽象水平上考虑系统,不用关心实现细节,减少出错可能性,加速设计和实现过程,且可复用。
    • 反对方:并不是模型所支持的抽象都是正确的、可实现的。

模型驱动体系结构

  • 计算独立模型 (CIM) — 领域建模 — 不同的 CIM 反映系统的不同方面。
  • 平台独立模型 (PIM) — 表示静态系统结构和系统对内外事件的响应。
  • 平台特定模型 (PSM) — PIM -> PSM。如图 4-10 所示,为一个复合平台特定模型实例。

图4-10复合平台特定模型

图 4-10 复合平台特定模型

可执行 UML:xUML

  • 为建立一 UML 可执行子集,模型类型可分为:
    • 领域模型:识别出系统的主要关注点,由 UML 的类图定义,包括对象、属性和关联。
    • 类模型:定义类及它们的属性和操作。
    • 状态模型:每一状态与一个类相关联,并且用来描述类的生命周期。