学习目标:
- 了解软件、软件工程的定义
- 解释软件的本质
- 区分软件的不同种类
- 分析导致软件项目失败的原因
- 解释实践的本质
一、软件和软件工程
软件
a ) 定义
软件通常远远不止一个程序,还会包含相关的文档,软件是:
- 指令的集合,通过执行这些指令能够满足预期的特性、功能和功能需求
- 数据结构,使得程序可以合理利用信息
- 软件描述信息,以硬拷贝和虚拟形式存在,描述程序的使用和操作
b) 分类
当今的计算机软件可以分为7大类:
- 应用软件(Application Software):解决特定业务需要的独立应用程序,处理商务或者是技术数据,协助业务操作或者协助做出管理和技术决策(e.g. 浏览器、音乐播放器)
- 工程/科学软件(Engineering/Scientific Software):数值计算类软件程序
- 嵌入式软件(Embedded Software):存在于某个产品或者软件中,可以实现和控制面向最终用户和系统本身的特性和功能,可以执行有限的和内部的功能(e.g. 微波炉的按键控制)或者提供重要的功能和控制能力(e.g. 汽车中的仪表盘显示等电子功能)
- 产品线软件(Product-line Software): 为多个不同用户的使用提供特定的功能,关注有限的以及内部的市场(e.g. 库存控制产品)或者大众消费品市场,软件产品线的概念不是新的概念,软件产品线都使用相同的底层应用软件和数据体系结构来开发,并使用可在整个产品线中进行复用的一组软件构件来实现
- Web/移动App(Web/Mobile Application):以 络为中心,其概念覆盖了宽泛的应用软件产品,包括基于浏览器的APP和安装在移动设备上的软件
- 人工智能软件(Artificial Intelligence Software):利用非数值计算解决计算和直接分析无法解决的复杂问题(e.g. 机器人、专家系统、人工神经 络、定理证明和博弈)
c) 软件 vs 硬件
为了更好地理解“软件”的含义,我们有必要将软件和其他人工产品的特点加以区分
软件是逻辑的而非物理的系统元素,因此软件和硬件具有完全不同的特性,他们之间最大的区别点在于:软件不会“磨损”
下面左图中是硬件的失效率,我们可以看到,硬件在早期的失效率是很高的,失效率在缺陷被一个个纠正之后逐渐降低并且在一段时间内保持平稳,但是随着时间的推移,因为灰尘、温度超限等原因,硬件组件损耗累积,失效率再度提高,说明硬件开始磨损
右图是软件的失效率,因为软件是不会磨损的,所以从理论上来说,软件的失效率曲线应该呈现为图中的理想曲线,曲线的含义就是“软件不会磨损”,但是软件退化是可能发生的。而实际曲线是因为在完整的生命周期里,软件会面临变更,每次变更都可能会引入新的错误使得失效率陡然上升,在失效率回到稳定失效率之前,新的变更又会引起曲线上升,所以我们可以说,不断的变更是软件退化的根本原因
d) 软件的变更本质
四大类软件不断演化,在行业中占据主导地位
- WebApp
- 移动App
- 云计算
- 产品线软件
e) 软件项目问题和软件失败
通常来说,小的项目失败的概率要低于大型项目,项目失败的主要原因有:
- 失败的组织和项目管理实践(poor organizational & project management practices)
- 失败的需求分析(poorly defined requirements)
软件失败是项目失败的其中一个原因;
- 在需求分析阶段引入的一个错误error可能会影响到设计和编码
- 引入的错误直到发布产品之后才发现
- 需求手机和规格说明表匆忙,没有和客户进行交流
f) 好的软件的属性
作为一个产品,软件还有一系列相关的反映质量的属性,这些属性不直接涉及软件的功能,而是反映软件在执行时的行为和源程序的结构、组织和相关的文档
- 可维护性(Maintainability) : 软件必须能够不断进化来满足用户的需求变化,这是软件产品最根本的特性,因为工作环境是不断变化的,软件也要跟着变化
- 可依赖性和安全性(Dependability & security) : 软件的可依赖性还包含一些特性(e.g.可靠性reliability, 保密性security, 安全性safety)可靠的软件在系统失败的情况下也不会引起物理性损害和经济损失
- 有效性(Efficiency): 软件不要浪费内存和处理器等系统资源,因而有效性包含响应时间、处理时间和内存利用率等方面
- 可用性(Acceptability) : 软件必须简单易用,容易被用户接受,也就是说,它要容易理解,易用并且和其他系统兼容
软件工程
a) 定义:
1. IEEE定义:软件工程是系统化的、规范化的、可量化的方法,应用于软件的开发、运行和维护,也就是将工程化的方法应用于软件,是对上述内容的研究
2. 在软件工程的定义中有两个关键词:
- 工程学科(Engineering)
- 软件生产的各个方面(All aspect in software production)
b) 层次化技术
软件工程是一种层次化技术
- A quality focus(质量关注点): 支持软件工程的根基在于质量关注点,任何软件工程方法必须构建在质量承诺之上
- Process(过程):软件工程的基础是过程层,软件过程将各个技术层次都结合在一起,它定义了一个框架,构建这个框架是有效实施软件工程技术必不可少的,是项目管理的基础
- Method(方法):为构建软件提供技术上的解决方法(怎么做),方法的覆盖面很广(e.g. 沟通、需求分析、设计建模等等),同时它依赖于一组基本原则,这些原则覆盖了软件工程的所有技术领域
- Tool(工具):为过程Process和方法Method提供自动化或者半自动化的支持,使得一个工具产生的信息可以被另外一个工具使用
c) 软件产品的分类:
- 通用软件产品(Generic Product): 由软件开发机构制作,在市场上公开销售,可以独立使用(e.g. 绘图软件、工程管理工具等)
- 定制软件产品(Costomised Product):受特定客户的委托,由软件承包商专门为这类客户开发,软件描述由客户给出,开发者必须按照客户的要求进行开发
- 区别:在Generic Product中,软件描述由开发者自己完成,而Customized Product是由客户描述,但是现在两者之间的界限正在变得模糊
d)软件工程重要性:
- 个人和 会越来越依赖先进的软件系统,这就需要我们能够既经济又快速地生产出可以依赖和值得信赖的系统
- 从长远来看,运用软件工程方法和技术去开发软件系统比单纯为个人项目写程序更加便宜,绝大多数钱都花在软件变更上
e) 软件过程活动:
软件工程中系统化方法称为软件过程,而所有的软件过程都会包括4个基本活动,这里只是简单介绍,后面会详细介绍软件过程:
- 软件描述:客户和工程师定义所要生产的软件以及对其操作的一些约束
- 软件开发:软件设计和编程实现
- 软件有效性验证:软件经过检查来保证是用户需要的
- 软件进化:随着不同客户和市场需求变化来进行修改
二、软件过程
定义
软件过程是工作产品构建时所执行的一系列活动、动作和任务的集合,是一组引发软件产品生产的活动,它提供了一系列可以预测的步骤(roadmap)和对软件开发而言有用的结构(useful structure)
- 活动activities: 主要实现宽泛的目标(e.g. 与利益相关者进行沟通),与应用领域、项目大小、结果复杂性没有直接关系
- 动作action:包含了主要工作产品生产中的一系列任务(e.g. 体系结构设计)
- 任务task:关注小而明确的目标,能够产生实际产品(e.g. 一个单元测试)
过程活动
虽然有很多不同的软件过程,但所有的软件过程都必须具有4种对软件工程来说的基本活动:
- 软件描述(software specification)
- 软件设计和实现(Software development)
- 软件有效性验证(Software validation)
- 软件进化(Software evolution)
a ) 软件描述/需求工程
理解和定义系统需要提供哪些服务,以及找出开发和运行中受到哪些约束,需求工程是软件过程中的一个特别关键的阶段,这个阶段的错误将不可避免地带来系统设计和实现阶段的后续问题,它的目标是生产一个达成一致意见的需求文档,这个文档需要分成用户的高层需求描述和系统开发人员的详细系统描述
分为4个阶段:
- 可行性研究(feasibility study)
- 需求导出和分析(requirement elicitation ang analysis)
- 需求描述(requirement specification)
- 需求有效性验证(requirement validation)
b) 软件设计和实现
软件开发的实现阶段是把系统描述转换成一个可运行的系统的过程,它总是包含设计和编程
- 软件设计:设计能够实现软件描述的软件结构
- 实现: 把系统描述转换成一个可运行的系统的过程
根据设计过程的通用模型,设计过程主要包括:
- 体系结构设计
- 接口设计
- 组件设计
- 数据库设计
c) 软件有效性验证
通常也称为检验和有效性检验(V&V),要看系统是否符合它的描述以及系统是否符合客户预期,程序测试是基本的有效性检验的技术
测试过程中的阶段包括:
- 组件/单元测试
- 系统测试
- 接收测试
d) 软件进化
软件系统具有灵活性并且可以发生变更,随着需求随着商业环境变化而变化,支持商业活动的软件也必须变化
因为现在完全从头开发的软件很少,不再将软件工程看成是开发和维护两个完全独立的过程
e) 应对变更
对于大型软件来说,变更是没有办法避免的,而 变更增加了软件开发的成本,因为意味着已经完成的工作要重做,也就是返工
有两个相关的方法能够降低返工的成本:
- 变更避免(Change Avoidance):软件过程包括一些能够在重大返工发生之前预测变更的活动
- 变更容忍(Change tolerance):所设计的过程使得变更以相对较低的成本得到处理
软件过程模型
软件过程模型被分成计划驱动和敏捷过程两类,计划驱动的过程是提前计划好所有的过程活动,然后按照计划去考核过程的执行,而敏捷过程的计划是增量式的,而且容易根据不断变化的客户需求变更过程
a) 瀑布模型(waterfall model)
1. 瀑布模型的主要阶段:
- 需求分析和定义(requirement definition): 通过咨询系统用户建立系统的服务、约束和目标,同时对其详细定义形成系统描述
- 系统和软件设计(system & software design): 建立系统的总体体系结构,将需求区分为硬件需求和软件需求,描述和识别一些基本的软件系统抽象和他们之间的关系
- 实现和单元测试(Implementation & unit testing): 将软件设计成一组程序或者程序单元,单元测试就是检验每个单元是不是符合描述
- 集成和系统测试(Integration & system tesing): 集成单个的程序单元或者一组程序,并对系统整体进行测试,在测试之后,系统将交付给用户
- 运行和维护(operation & maintenance): 具有最长的生命周期,系统被安装并投入实际使用,维护包括改正那些在早期各个阶段没有被发现的错误,改善系统各个单元的实现,提高系统服务能力
2. 每一个阶段的结果是一个或者多个经过核准的文档,一个过程结束之后才能进行下一个过程,属于计划驱动模型
3.优点:
- 需求的责任和义务要在第一个阶段就清晰确定
- 需求、设计、实现和测试这四个主要的工作必须在软件打包交付之前完成
- 一个过程必须在前一个过程结束之后进行
- 将项目分解成顺序执行的清晰阶段,能够根据项目计划监控项目的进程
4. 问题:
- 实际的项目很少遵循瀑布模型提出的顺序
- 客户通常很难清楚地描述所有的需求
- 只有在项目接近尾声的时候客户才能得到可执行的程序
5. 适用情况:
瀑布模型只适用于嵌入式系统(Embedded system)、关键系统(critical system)和大型软件(large software)
如果从沟通到部署都采用合理的工作流方式的时候,可以清楚地理解问题的需求,这种情况通常发生在需要对一个已经存在的系统进行明确定义的适应性调整或者增强的时候,也可能发生在很少的新开发的工作上,但是需求必须是准确定义和相对稳定的
如果系统在开发中,特性、功能和信息内容都会发生变更,开发团队的成员之间可以非正式交流,那么不适合使用瀑布模型
所以只有在对需求了解足够好而且在开发过程中不大可能发生重大改变的时候,适合使用瀑布模型
6. 变体(V模型)
描述了质量保证动作同沟通、建模相关动作以及早期构建相关的动作之间的关系,一旦编码结束,团队回沿着V模型的右侧向上推进工作,其本质是进行一系列测试
V模型提供了一种将验证和确认应用于早期软件工程工作中的直观方法
b) 增量式开发(incremental development)
1.思想:增量式开发的思想是先开发出一个初始的实现,给用户使用并听取用户的意见和建议,通过多个版本的不断修改直到产生一个充分的系统
它反映了我们解决问题的方法,我们总是逐步逼近解决方案,当我们意识到错误的时候回溯
2. 增量式软件开发是敏捷方法的一个基本部分,可以是任务驱动的,也可以是敏捷的,更常用的做法是两者结合
系统的每一个增量或者版本包括用户需要的一部分功能,通常,它的早期增量包括最重要或者最紧急的功能需求,是现在最常用的应用系统开发方法
3. 适用情况:对于商务、电子商务和个人系统来说更加适合, 同时适用于人员较少,工期紧的情况
对于那些大型的,生命周期很长的系统,不同团队负责开发系统的不同部分,这种开发模式就会变得捉襟见肘,大型系统通常需要一个稳定的框架或者体系结构,而负责开发不同部分的团队需要根据体系结构明确职责,这就需要提前制定计划而不是增量开发
4. 优点:
- 开发过程中可以更加经济、更加容易地对软件变更做出响应
- 降低了适应用户需求变更的成本:重新修改和分析文档的工作量比waterfall要少很多
- 在开发过程中更容易得到用户对于已经完成的开发工作的反馈意见
- 可以更快向客户交付和部署有用的软件,虽然不是所有的功能都包括在内,但是用户仍然可以更早使用软件并创造商业价值
- Lower cost + Frequent feedback + Faster delivery
5. 从管理的角度看,增量式开发有两个问题:
- 过程不可见:管理者要通过经常性的可交付文档来把握进度
- 随着新的增量的增加,系统结构会退化:除非投入时间和金钱在重构系统结构上来改善软件,否则定期变更会损坏系统结构,越往后系统越难变更
c) 面向复用的软件工程
面向复用的方法依赖于存在大量可以复用的软件组件以及能组合这些组件的集成框架,有的时候,这些组件可能本身就是一个系统(COTS)
1.阶段:
- 组件分析:给出需求描述,搜寻能满足需求的组件
- 需求修改:根据得到的组件信息分析并修改需求,反映可以得到的组件
- 使用复用的系统设计:设计系统的框架或者重复使用一个已经存在的框架
- 开发和集成 :当组件不能买到的时候就要自己开发,然后集成这些自己开发的组件或者和现货组件
2. 3种类型的软件组件可能用于面向复用的过程:
- 通过标准服务开发的Web服务
- 对象的集合,作为一个包和组件的框架
- 独立的软件系统(COTS)
3. 优点:
- 减少了需要开发的软件的数量,降低了软件的开发成本
- 降低了开发的风险
- 是软件可以快速交付
d) 演化过程模型(Iterative Process)
1. 适用情况:
- 在开发过程中,商业和产品需求经常发生变化
- 严格的交付时间导致开发团队不能圆满完成综合性的软件产品,但是必须交付功能有限的版本来用对竞争或者商业压力
- 产品或者系统扩展的细节问题没有定义
2. 演化模型是迭代的过程模型,每个迭代产生软件的一个更加完整的版本
3. 原型构造:
原型是一个软件系统的最初版本,用于验证概念、试用设计选项、发现更多的问题和可能的解决方法,能更好地帮助软件开发人员和其他利益相关者更好地理解需要做什么,软件原型可以用在软件开发过程中,帮助预计可能需要的变更:
- 在需求工程过程中,原型有助于启发和验证系统需求
- 在系统设计中,原型可用于探索特定软件的解决方案,支持用户的接口设计
- 测试
优点:
- 提高系统的可用性
- 更加贴近用户需求
- 提高设计质量和可维护性
- 减少开发的工程量
4. 螺旋模型
螺旋模型是一种演进式的软件过程模型,它结合了原型的迭代特性和瀑布模型的可控性、系统性特点,具有快速开发越来越完善的软件版本的能力,是开发大型系统很实际的方法
螺旋模型是一种风险驱动的过程模型生成器,有两个显著的特点:
- 采用循环的方式逐步加深系统定义和实现的深度,同时降低风险
- 确定一系列里程碑作为支撑点,确保利益相关者认可是可行的并且可以让各方满意
在螺旋线中每个回路被分为4个部分:
- 目标设置Planning:为项目这个阶段专门定义目标,指定对过程或者产品的约束,制定详细的管理计划,分析风险,根据风险规划可选的策略方案
- 风险评估和规避: 每个项目的风险确定之后要进行详细的分析,并采取措施规避风险
- 开发和有效性验证:在风险预估之后,可以为系统选择开发模型
- 规划:对项目进行评审确定是否进入螺旋线的下一个环路
与其他软件过程模型的重要区别在于:螺旋式模型中对风险的考虑是明确的,可以帮助识别项目风险的源头,但是这样很难使客户(特别是以合同的方式)相信演进的方法是可控的,它依赖大量的风险评估专家来保证成功
e) Rational统一模型(RUP模型)
统一模型是一种新式过程模型,来自于UML上的工作和相关的统一软件开发过程,它集合了所有一般过程模型的要素,并在描述和设计上给出了好的实践,还支持原型构造和增量交付的方法
RUP过程认识到传统过程模型只是展现过程的一个视角,相比之下,RUP一般从3个视角来描述过程:
- 动态视角:给出模型中随时间所经历的各个阶段
- 静态视角:给出所进行的过程活动
- 实践视角:提出在过程中可以采用的良好实践的建议
工作流 | 描述 |
业务建模 (business modeling) |
使用业务用例对业务过程进行建模 |
需求 (Requirement) |
找出和系统进行交互的参与者并开发用例完成对系统需求的建模 |
分析和设计 (Analysis and design) |
使用体系结构模型、组件模型、对象模型和时序模型来创建并记录设计模型 |
实现 (implementation) |
实现系统中的组件并将它们合理组织在子系统中,从设计模型自动生成代码可以加速这个过程 |
测试(testing) | 测试是一个迭代的过程,它的执行和实现紧密相连 |
部署(deployment) | 创建和向用户分发产品版本并安装到工作场所 |
配置和变更管理(configuration and change management) | 此支持性工作流用于管理对系统的变更 |
项目管理(project management) | 此支持性工作流用于管理系统开发 |
环境(environment) | 此工作流用于提供软件开发团队可用的合适的软件工具 |
f) 优缺点对比
三、敏捷开发
新的软件要迅速开发来抓住机遇,应对竞争压力,所以,快速的软件开发和交付通常已经成为软件系统最为关键的需求了,因为业务运行在一个变化的环境中,通常来说,不可能导出一个完全的、稳定的软件需求
a ) 什么是敏捷
敏捷方法是增量式开发方法,每一个增量一般都比较小,而且需要频繁创建新版本供用户使用,来快速获得变更需求的反馈, 同时敏捷方法减少了开发过程中的繁琐多余的部分,通过避免那些长远看来没有用处的工作,减少文档的方法来实现软件的快速交付
- 对变更的有效响应
- 鼓励成员之间的有效沟通
- 将客户作为开发团队中的一部分
- 灵活调整项目计划
- 是任务流水线化
- 保留最重要的工作产品并使其保持简洁
- 使用增量式开发策略
b) 敏捷开发的重要性
- 适合正在以飞快的节奏不断变化的现代商业环境
- 保留了基本的框架活动:客户沟通、策划、建模、构建和部署
- 将基本的框架活动缩减到一个推动项目组朝着构建和交付发展的最小任务集
c) 敏捷过程
任何敏捷过程的特征都是以某种方式提出若干关键假设,这些假设可以用于大多数项目
敏捷过程必须具有可适应性,但是原地踏步式的连续适应性变更收效甚微,因而,敏捷软件过程必须增量地适应,敏捷团队需要客户的反馈来做出正确的适应性改变,可执行原型或者可以运行的部分系统是客户反馈的最有效媒介,因此应当采用增量式开发策略
典例 : 极限编程XP + Scrum
Scrum:
一个计划驱动的方法要求经理对于每件事情都有一个稳定的看法,包括必须开发什么和开发进度,但是这不适用于敏捷方法,敏捷方法的需求是增量的,短期内快速交付增量,经常有需求变更
有3个阶段:规划纲要阶段 + 冲刺循环 + 项目结束总结
每个循环会开发出一个系统增量,一个循环是一个工作单元,需要做评估、特征的选择和开发、软件的实现
- 评估:在每个循环提出新的需求和任务建议,然后进行审查、优先级排序和风险分析
- 选择:项目团队的所有人员都要参加,和用户一起选择在冲刺循环要开发的特性和功能
- 开发:每天都要有短时会议
- 结束
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!