# 软件生产两大模式

  • 不可见过程

    用户需求→不可见的软件制作流程→软件成品

  • 可见的过程

    用户需求→软件制作的每个阶段都有及时的用户反馈(制作流程可见)→软件成品

# 软件过程

  1. 软件制作过程中
  2. 产生的相关活动

一个过程有多种活动, 本质是活动的集合体, 这意味着一个软件可以有很多不同的软件过程, 一个软件过程里面的活动又有统筹规划

# 软件过程基本活动

  1. 软件规格说明

    软件的功能和规范

  2. 软件开发

    必须开发符合规定要求的软件

  3. 软件确认

    确认软件满足用户需求

  4. 软件演化

    软件系统随客户需求及时变化

# 软件过程描述

  • 产品

    软件过程的结果

  • 角色

    参与软件过程者在软件过程中的职责

  • 前置和后置条件

    在一个软件过程的前后需要的预定条件

# 软件过程类型

  • 计划驱动过程

    提前计划好所有过程活动, 按计划去衡量进度(吐槽两句, 现在的开发者越来越认识到"计划赶不上变化这个道理了")

  • 敏捷过程

    增量式计划, 需求随客户需求灵活变化, 渐进式开发方案

实际开发中, 大多数过程是计划驱动型和敏捷型混用的方法, 稳中求进步

# 软件过程模型

  1. 从某些特别的角度
  2. 描述一个软件过程
  3. 是一个抽象的概念

软件过程模型 === 对所有软件过程的统筹规划: 软件规格说明, 软件开发, 软件确认和软件演化的顺序安排(软件过程基本活动); 产品预估, 角色设计, 前后条件的详细设计(软件过程描述).

# 软件过程模型类型

  • 瀑布模型

    计划驱动型模型, 软件规范和开发在不同的阶段进行

    graph LR
    	a(需求定义) --> b(系统和软件设计) --> c(实现与单元测试) --> d(集成与系统测试) --> e(运行与维护)
    	a --- b --- c --- d --- e
       
    

    瀑布模型的不同阶段:

    • 需求分析和定义
    • 系统和软件设计
    • 实现和单元测试
    • 集成和系统测试
    • 运行和维护

    瀑布模型缺点:

    • 严苛

      过程开始后环环相扣, 难以适应变化

    • 死板

      不能灵活划分软件过程模型的各个阶段, 难以应对变化的需求

      • 全面了解需求, 系统开发过程中变化不大的前提下, 可以采用瀑布模型
      • 很少有业务系统由稳定的需求(所以答应我别用瀑布了好吗)

    适用范围:

    大型系统工程项目, 一个系统在几个地点开发, 死板的模型有助于协调工作

  • 增量式开发

    规范, 开发, 确认三者穿插进行. 软件过程可以是计划驱动型也可以是敏捷型

    思路:

    先开发一个预览版, 然后获取客户反馈, 不断演化成为最终版本

    graph LR
    	a[概要描述] --> b(规格说明) --> c[初始版本]
    	
    	b --> d(开发)
    	d --> b
    	d --> e(确认)
    	e --> d
    	
    	c --> b
    	f[中间版本] --> d
    	d --> f
    	
    	e --> g[最终版本]
    

    增量开发优点:

    • 适应用户需求的成本降低
    • 更容易得到用户对于已做开发工作的反馈意见
    • 更快地交付和部署

    增量开发的问题:

    • 软件过程不可见:

      管理者需要审阅每一次增量式开发的中间产物, 但是增量式开发本来就又小又快, 专门为了一点小变化写文档很不划算, 没有能拿开评价开发进度的文档, 整体过程就会看的不清楚甚至看不见

    • 系统结构的退化

      熵增理论, 增量更新积累会导致系统整体上变得臃肿, 除非投入时间和金钱用在重构系统结构上以改善软件, 否则定期的变更会损坏系统的结构. 随着时间的推移, 越往后变更系统越困难, 而且成本也将逐渐上升

  • 面向复用的软件工程(用轮子!)

    系统由现有组件或COTS(商用现成品或技术)组装而成. 软件过程可以是计划驱动型也可以是敏捷型

    graph LR
    	a(需求描述) --> b(组件分析) --> c(需求更改) --> d(使用复用的系统设计) --> e(开发和集成) --> f(系统有效性验证)
    

    过程阶段:

    • 组件分析(用什么轮子)
    • 需求修改(修修补补)
    • 使用复用的系统设计
    • 开发和集成

实际开发中, 三种模型互不排斥, 且经常混合使用, 稳中求进步

# 软件组件类型

  • Web服务

    1. 通过标准服务开发
    2. 可用于远程调用的Web服务
  • 对象的集合

    打成包(packages)拿来用的

  • 独立软件系统

    1. 配置运行环境
    2. 开始使用

# 软件过程活动

# 基本活动

  1. 软件规格说明

    软件的功能和规范

    需求工程过程:

    graph LR
    	a(可行性研究) --> b(需求导出和分析) --> c(需求描述) --> d(需求有效性验证) --> e[需求文档]
    	a --> f[可行性报告]
    	b --> g[系统模型] --> e
    	c --> h[用户需求和系统需求] --> e
    	c --> b
    	d --> c
    
    • 主要活动:
      • 可行性研究
      • 需求抽取和分析
      • 需求规格说明
      • 需求确认
  2. 软件开发

    必须开发符合规定要求的软件

    软件设计与实现:

    把系统描述转换成一个可运行的系统的过程

    graph TB
    	a[平台信息]
    	b[需求描述]
    	c[数据描述]
    
    ↓↓↓
    
    graph LR
    	a(体系结构设计) --> b(接口设计) --> c(组件设计)
    	a --> d(数据库设计)
    	c --> d
    
    • 体系结构设计(Architectural design)

      识别系统总体结构, 基本构件(有时候也叫子系统或模块), 它们之间的关系以及它们是怎样分布的

    • 接口设计(Interface design)

      定义系统构件间的接口

    • 数据库设计(Dataase design)

      设计系统数据结构以及如何在数据库中表示这些数据结构

    • 组件设计(Component design)

      设计系统组件的运行方式

    ↓↓↓
    
    graph TB
    	系统体系结构
    	数据库描述
    	接口描述
    	组件描述
    
    • 主要活动:

      1. 设计符合描述的软件结构
      2. 将该结构转换为可执行程序

      设计和实现的活动是密切相关的, 可以相互穿插的

  3. 软件确认(verification & validation)

    确认软件满足用户需求

    软件测试:

    graph LR
    	a(组件测试) --> b(系统测试) --> c(客户测试)
    	a --> c
    	c --> a
    
    • 组件测试(单元测试)

      • 范围: 每个组件都要单独测试
      • 对象: 组件可能是单个函数, 对象, (统称实体)也有可能是他们的集合(实体集)等
    • 系统测试

      把系统作为一个整体进行测试, 其中测试系统的应急功能尤为重要

    • 客户测试

      使用客户数据进行测试(打破既定思维), 检查系统是否满足用户需求

    • 主要活动:

      1. 审查和评审过程
      2. 系统测试
        • 系统测试涉及使用测试用例执行系统,这些测试用例来自系统要处理的真实数据的规范
        • 测试是最常见的V&V活动
  4. 软件演化

    软件系统随客户需求及时变化

    尽管软件开发和软件演化(维护)之间有一个界限, 但是现在的系统基本上都不是纯净的, 这个界限也就无关紧要了

    graph LR
    	a(定义系统需求) --> b(评估现有系统) --> c(提出系统变更) --> d(修改系统)
    	e[现有系统] --> b
    	f[新系统] --> b
    	d --> f
    

    应对变化

    • 对于所有大型项目来说, 变更无法避免
      • 业务变更导致需求更新
      • 新技术改进老系统的功能实现
      • 平台更换, 对应的应用程序也有所变动
    • 变化的结果是返工, 变更的成本 = 返工成本 + 实现新功能成本 (先填坑后创造)

    降低返工成本

    • 变化预测, 软件过程包括一些能够在重大返工发生之前预测变更的活动. 比如原型系统的开发, 要先给客户看系统的一些重要特征, 避免关键部分出岔子
    • 变化容忍, 通过过程设计使做出变更的成本降低. 要实现这一目的, 通常需要增量开发的软件过程, 使变更在还没有开发的增量上实现, 或者只需要更改一个小的增量来适应变更

# 软件过程活动

软件过程小节已知, 软件过程是由很多软件过程的活动组成的, 真正的软件过程中:

  • 技术活动
  • 写作活动
  • 管理活动

交织在一起, 其总体目标是完成一个软件系统的规格说明, 设计, 实现和测试

对于不同的开发过程, 规格说明, 开发, 确认和演化这4个基本过程活动的组织是不同的. 在瀑布模型中, 它们是顺序组织的, 而在增量式开发中它们是交织在一起的

graph LR
	a[软件过程模型] -- 控制 --> b(软件过程) -- 包含 --> c((软件过程基本活动))
	b -- 包含 --> d((软件过程描述))

# 软件原型

原型是一个软件系统的早期版本, 用于演示概念, 尝试候选设计方案, 发现更多的问题和可能的解决方案

graph LR
	a(建立原型目标) --> b(定义原型功能) --> c(开发原型) --> d(评估原型)
	a --> e[原型构造计划]
	b --> f[概要定义]
	c --> g[可执行的原型]
	d --> h[评估报告]

# 应用领域

  • 软件规格说明的需求工程过程中, 原型有助于启发和验证系统需求
  • 软件开发的软件设计与实现过程中, 原型可用于探索特定的软件解决方案, 并支持用户接口设计
  • 软件确认的软件测试过程中, 原型有利于回归测试(回归初心)

# 原型优点

  • 提高系统可靠性
  • 贴近用户实际需求
  • 改善设计质量
  • 提高可维护性
  • 减少开发工作

# 原型开发

  • 基于快速原型语言或工具
  • 可能会遗漏一些功能(功能可能不完善)
    • 原型应该多注意研究产品的那些不好懂得地方
    • 原型不需要错误检查和恢复功能
    • 关注功能需求而不是非功能性的(例如可靠性和安全性这种日后考虑的东西)

# 抛弃原型

原型应该在开发后丢弃, 它们不是成品系统(production system)的良好基础, 具体解释如下:

  • 在原型上直接实现非功能性需求是几乎不可能的
  • 原型一般是没有文档的
  • 原型的项目结构在快节奏的需求变更下会不断退化(为了适应快速的变化, 代码实现一般都不会优美, 欠缺严谨设计和构思)
  • 原型可能不会达到正常组织化的质量标准

# 增量开发和交付

  • 不是将系统作为单个整体交付, 而是将开发和交付分解为增量, 每个增量交付所需功能的一部分
  • 用户需求被划分优先级,最高优先级的需求包含在早期增量中, 优先实现. 一旦开始了增量开发, 该增量开发对应的增量需求就会被冻结(后续环节中该增量需求仍可以继续发展)

# 增量开发

  • 以增量方式开发系统, 并在进行下一个增量开发之前对每个增量进行评估
  • 敏捷方法中使用的常规方法
  • 由用户/客户代理评估

# 增量交付

graph LR
	a(定义框架需求) --> b(需求到增量的映射) --> c(设计系统体系架构) --> d(开发系统增量) --> e(增量有效性验证) --> f(集成增量) --> g(系统有效性验证) --> h(部署增量) --> i[最终系统]
	h -- 系统未完成? --> d
  • 署供最终用户使用的增量
  • 关于软件实际使用的更实际评估
  • 难以实现替换系统的目的, 因为增量的功能比被替换的系统所含功能要少

增量交付优势:

  • 客户不用等到整个系统交付就能从系统中获得价值
  • 早起增量可以充当原型, 有助于启发后期增量过程对应的需求
  • 降低整个项目失败的风险
  • 具有最高优先权的服务可以接受最多的测试

增量交付的问题:

  • 在"一个新系统要替代一个现存系统"的场景下, 迭代交付(增量交付)反而成了麻烦, 这是因为多数待替代系统的很多功能需要依赖才能运行, 而这些依赖实现的功能暂时不能被新系统全部实现(毕竟是增量交付, 每次的东西都很少, 不会一次给全), 这就直接导致用户不愿意尝试一个功能欠缺的新系统, 而抱着之前的旧系统不放

  • 迭代过程的关键在于软件规范和软件是要一同开发的, 这就是说规范随着软件开发被一点一点写出来, 然而在很多公司的采购合同中, 完整的系统规范是系统开发合同的一部分, 是事先写好的文件

# Boehm螺旋模型

将软件过程用螺旋线表示

  • 螺旋线的每个回路是软件过程的一个阶段
  • 螺旋线内的回路取决于需求, 非常灵活, 并不是什么既定的套路
  • 整个过程的风险是被精确评估和解决的

重要概念:

  • 目标设置

    为项目的这个阶段定义专门目标

  • 风险评估和规避

    每一个项目风险确定以后要进行详细的分析, 并采取措施规避这些风险

  • 开发和有效性验证 选择一种系统开发模型, 该模型可以是任何通用模型

  • 规划

    对项目进行评审以确定是否需要进人螺旋线的下一个环路

螺旋模型的意义:

  • 螺旋模型在帮助人们考虑软件过程中的迭代和将风险驱动的方法引入开发方面非常有影响力
  • 在实际应用中, 这个模型很少用于实际的软件开发

# Rational统一过程(RUP)

  1. 一种从UML工作及其相关过程中诞生的现代化一般过程
  2. 它将之前讲的3个通用流程模型(瀑布模型, 增量式开发, 面向复用的软件工程)的各个方面做了有机结合
  3. 一般从3个视角来描述Rational统一过程:
    1. 动态视角, 给出时间线上的各个阶段
    2. 静态视角, 给出软件过程中的活动
    3. 实践视角, 提出软件过程中的好建议
graph LR
	b((开端)) --> b --> c((细化)) --> c --> d((构造)) --> d --> e((转换)) --> e
	e -- 阶段反复 --> b

概念解释:

  • 开端:

    建立系统的一个业务案例

  • 细化

    增进对问题领域的理解, 建立系统的体系框架

  • 构造

    系统设计, 编程, 测试

  • 转换

    在系统的操作环境下部署系统

  • 阶段内迭代

    每一个阶段都是迭代的, 它的结果是一点一点增量完成的

  • 跨阶段迭代

    所有阶段构成的整体集合有时候也是增量执行的

# 常用的工作流程

名称 描述
业务模型 使用业务用例对业务过程进行建模
需求 找出与系统进行交互的参与者并开发用例完成对系统需求的建模
分析和设计 使用体系结构模型, 组件模型, 对象模型和时序模型来创建并记录设计模型
实现 实现系统中的组件并将它们合理组织在子系线中. 从设计模型自动地生成代码有助于加快此过程
测试 测试是一个迭代过程, 它的执行是与实现紧密相连的. 系统测试紧随实现环节的完成
部署 创建和向用户分发产品版本并安装到工作场所
配置和变更管理 系统变更管理(25章)
项目管理 系统开发相关(22&23章)
环境 关于制作软件开发团队可用的合适的软件工具

# RUP实践

  • 迭代开发软件
  • 需求管理
  • 使用基于组件的体系结构
  • 可视化建模软件
  • 检验软件质量
  • 控制软件的需求变更