软件工程导论
绪论
软件工程定义
是把软件当作一种工业产品,要求 “采用工程化的 原理与方法对软件进行计划、开发和维护 ”。
1983年IEEE:软件工程是开发、运行、维护和修复软件的系统方法。
Fairly:软件工程学是为了在成本限额以内完成开发和修改软件产品所需要的系统生产和维护技术及管理学科。
Fritz Bauer:软件工程是为了经济地获得可靠的且能在实际机器上有效地运行的软件,而建立和使用的完善的工程化原则。
1993年IEEE:①软件工程是把系统化的、规范的、可度量的途径应用于软件开发、运行和维护的过程,也就是把工程化应用于软件中;②研究①中的提到的途径。
软件工程学包含的主要内容
- 软件开发技术
- 软件开发方法学
- 软件工具
- 软件工程环境
- 软件工程管理
- 软件管理学
- 软件经济学
- 软件度量学
- 软件开发技术
软件工程环境
- 定义
- 方法与工具相结合,再加上配套的软、硬件支持就形成软件工程环境。
- 定义
三种编程范型
- 过程式编程范型
- 程序=数据结构+算法
- 面向对象编程范型
- 程序=对象+消息
- 有效地降低软件的复杂性,简化程序的开发;使因修改程序而引发软件故障的机会大大减少,令大型软件的维护更快、更简单。
- 基于构件编程范型
- 程序=构件+架构
- 构件是通用的、可复用的标准化对象类
- 过程式编程范型
软件生存周期与软件过程
软件生存周期(Software Life Cycle):一个软件项目从问题提出开始,直到软件产品最终退役(废弃不用)为止。应该可以说是最早的软件工程概念。
分为三个时期:计划、开发和维护
软件生存周期
- 一个软件项目从问题提出开始,直到软件产品最终退役(废弃不用)为止。
- 分为三个时期:计划、开发和维护
软件过程
- 围绕软件开发所进行的一系列活动
- 软件生存周期中的阶段和软件过程中的活动是基本一致的。
瀑布模型waterfall model
快速原型模型rapid prototype model
基于原型的迭代化开发模型
特点
- “逼真”的原型可以使用户迅速作出反馈
- 循环回溯和迭代:非线性模型
- 使用快速开发工具
硬件相比原型的不同之处及相应措施
单件产品
种类
渐进型:对原型补充和修改获得最终系统
抛弃型:原型废弃不用应防止的偏向舍不得抛弃,从而影响软件质量(用户与开发者)
启示
软件生存周期不等于过程模型
敏捷过程
敏捷开发的价值观
- 个人和交互胜过过程和工具
- 可以运行的软件胜过面面俱到的文档
- 客户合作胜过合同谈判
- 响应变化胜过遵循计划
12条原则
允许改变需求,利用变化来为客户创造优势尽快、不断地提交可运行的软件在业务人员和开发人员必须天天都在一起工作以积极向上的员工为中心建立项目组,提供环境和支持,并信任他们的工作在团队内部重视面对面的交流依据可运行软件来评估项目的进展提倡可持续的开发时刻关注技术上的精益求精和好的设计,以增强敏捷能力简单是最根本的最好的构架、需求和设计出于自组织团队每隔一定时间,要反省如何才能更有效地工作,然后作相应调整
极限编程
- 一种轻量级的、敏捷的软件开发方法
- 交流、简单、反馈、勇气
- 加强交流、从简单做起、寻求反馈、勇于实事就是
软件生存周期的主要活动
- 需求分析
- 明确需要解决的问题(从用户的视角)
- 建立需求模型:功能、性能、约束、外部接口等
- 软件分析
- 从开发人员的视角对软件进行分析
- 建立分析模型:软件的逻辑模型
- 软件设计
- 确定软件的总体结构和各部件的数据结构和操作(总体、概要、详细)
- 建立软件设计模型:考虑实现技术和平台
- 编码(含单元测试 )
- 用程序设计语言将设计文档翻译成源程序
- 建立软件实现模型:包含现有软件构件包
- 软件测试
- 发现程序中的错误、提高软件质量
- 集成测试、确认测试(α , ß )、系统测试
- 运行维护
- 延长使用寿命
结构化分析与设计
- 瀑布模型的各个阶段
- SA和SD阶段的内容和使用的工具
- SA与SD是瀑布模型的首次实践
- 需求定义与分析→总体设计→详细设计→编码→测试→使用维护
- SA与SD的流程
- 结构化分析(工具:DFD、PSPEC、DD ) 分析模型+ SRS
- 结构化设计(工具:SC图)映射 初始设计模型(初始SC图)
- 初始设计模型(初始SC图) 优化 最终设计模型(最终SC图)
- SA与SD是瀑布模型的首次实践
- 扇出和扇入
- 保持高扇入/低扇出的原则
- 扇入:被其他模块调用数
- 扇出:调用其他模块数
- 瓮型结构
- 清晰第一与效率第二
面向对象与UML
面向对象的基本特征
- 对象:代表客观世界中实际或抽象的事物 ,它由状态(属性)和行为(方法)组成。
- 抽象
- 在某个重要的或想关注的方面来表示某个物体或概念 忽略主题中与当前目标无关的方面
- 封装
- 把操作和数据包围起来,对数据的访问只通过已定义的接口来完成
- 继承
- 类层次,定义一个新类,可以从现有的类中派生出来 子类可以从父类继承方法和属性 \
- 多态
- 不同类的对象可以对同一消息作出响应,执行不同的处理
- 多态性:同一消息发送至不同类或对象可导致不同的操作结果,使软件开发设计更便利,编码更灵活。
- 抽象
- 对象:代表客观世界中实际或抽象的事物 ,它由状态(属性)和行为(方法)组成。
UML
- 组成
- UML的模型元素
- UML的元模型结构
- 图与视图
- 每个视图由一组图构成,图中包含了强调系统中某一方面的信息,显示了这个系统中一个特定的方面。
- 特点
- 统一标准
- 面向对象
- 可视化、表示能力强
- 应用
- 组成
UML的模型元素
表示模型中的某个概念
- 类、对象、构件、用例、结点(node)、接口(interface)、包(package)和注释(note)
表示模型元素之间的关系
关联,泛化,依赖,实现,聚集和组合
1、关联
关联关系是一种结构关系,它指明一个事物的对象与另一个事物的对象之间存在固定的对应关系时,这两个事物之间为关联关系。
2、聚合
表示“整体”与“部分”关系,“部分” 元素是 “整体”元素的一部分。
3、组合
表示强烈的”整体“与”部分“关系,”部分“不能独立于”整体“存在。
4、泛化
泛化关系也称为继承关系,这种关系意味着一个元素是另一个元素的特例。泛化用一条空心三角箭头的实线表示,它从表示特殊性事物的模型元素指向表示一般性事物的模型元素。
5、实现
实现关系描述一个元素实现另一个元素。实现关系用一条空心三角箭头的虚线表示,箭头从源模型指向目标模型,表示源模型元素实现目标元素模型。
6、 依赖
表示一个元素以某种方式依赖于另一个元素,用一条虚线加箭头来箭头从源事物指向目标事物,表示源事物依赖于目标事物。
- 关联关系
- 例子:在学校管理系统里,“学生” 和 “课程” 之间存在关联关系。一个学生可以选修多门课程,一门课程也会有多个学生来选修,这种多对多的对应联系,就是关联。在代码层面,可能会在 “学生” 类里有一个列表属性来存放所选 “课程” 对象的引用,反之亦然 ,以此来确立二者固定的选课对应关系。
- 聚合关系
- 例子:汽车和轮胎。轮胎是汽车的一部分,汽车作为 “整体”,轮胎作为 “部分”,它们是聚合关系。从生命周期来讲,轮胎可以独立生产制造,在被安装到汽车上之前,轮胎有自己的独立存在状态,即便后期从车上拆卸下来,也不影响轮胎本身的存在。在代码里,“汽车” 类可能有一个属性,用来存储一组 “轮胎” 类的对象。
- 组合关系
- 例子:鸟和它的翅膀。翅膀是鸟身体构造不可或缺的部分,离开鸟这个 “整体”,翅膀就失去了作为有生物功能的 “翅膀” 的意义,没办法单独存活、发挥作用。在代码实现时,“鸟” 类内部定义 “翅膀” 类的实例变量,当 “鸟” 的对象被销毁时,其内部 “翅膀” 对象也会随之被销毁。
- 泛化关系
- 例子:在图形绘制程序里,“圆形”“三角形”“矩形” 和 “图形” 之间的关系。“圆形”“三角形”“矩形” 都是 “图形” 的特例,它们继承了 “图形” 的一些通用属性,比如颜色、位置等,同时又各自有独特的属性,像圆形有半径,三角形有三条边长。用代码表示,“圆形”“三角形”“矩形” 类会继承自抽象的 “图形” 类 。
- 实现关系
- 例子:在 Java 里,接口和实现类的关系。例如,定义一个 “可飞行” 接口,其中声明了 “起飞”“飞行”“降落” 等抽象方法。然后 “飞机” 类实现这个 “可飞行” 接口,意味着飞机类要去具体实现接口里的抽象方法,满足接口定义的飞行行为契约,这里就用到了实现关系。
- 依赖关系
- 例子:在一个电商订单处理系统中,“订单” 类和 “用户地址验证” 类存在依赖关系。当创建一个订单时,需要调用 “用户地址验证” 类的方法,来确保收货地址的准确性,“订单” 类依赖 “用户地址验证” 类完成部分关键业务流程,如果 “用户地址验证” 类发生变更,很可能影响 “订单” 类的功能。
动态图
- 状态图、时序图、协作图和活动图
静态图
- 用例图、类图、对象图、构件图和部署图
包
- 内容
- 可以是类的列表,也可以是另一个包图,还可以是一个类图。
- 包可以有接口,接口与包之间用实线相连,接口通常由包的一个或多个类实现。
- 内容
用例图:
- 描述系统功能
- 用例是对系统提供的功能(即系统的具体用法)的描述。用例图从用户的角度描述系统功能,并指出各个功能的操作者。用例图定义了系统的功能需求。
类图 :
- 描述系统的静态结构;
- 不仅定义系统中的类,表示类与类之间的关系(例如,关联、依赖、泛化等关系),也表示类的内部结构(类的属性和操作)。
- 类图描述的是一种静态关系,在系统的整个生命期内都是有效的。
状态图
- 描述系统元素的状态条件和响应;
- 描述类的对象可能具有的所有状态,以及引起状态变化的事件,状态变化称作状态转换
- 状态图是对类图的补充。
时序图
- 按时间顺序描述系统元素间的交互;
- 显示若干个对象间的动态协作关系,它强调对象之间发送消息的先后次序,描述对象之间的交互过程。
协作图
按照时间和空间的顺序描述系统元素间的交互和关系;
描述对象间的动态协作关系。除了显示对象间发送的消息之外,协作图还显示对象及它们之间的关系(称为上下文相关)。相互协作的对象间的交互与链接。
两者的区别和联系画法
由于二者都描述对象间的交互关系,所以建模者可以选择其中一种表示对象间的协作关系:
如果需要强调时间和顺序,最好选用时序图;
如果需要强调上下文相关,最好选择协作图。
- 活动图
- 描述系统元素的活动
用例图、时序图(或者协作图)、类图(重点掌握)类图中的六种联系(重点掌握)
需求工程与需求分析
软件需求的层次关系(业务、用户和功能)
业务需求
反映了组织机构或客户对系统、产品高层次的目标要求,通常在项目定义与范围文档中予以说明 。
业务需求的确定对之后的用户需求和功能需求起了限定作用,任何需求不得与之相违背。
用户需求
用户需求(user requirement) 从用户使用角度来描述软件产品必须完成的任务。通常在用例模型中描述,同时引出软件的质量属性。
用户需求的重心是如何收集用户的需求,即确定软件系统的功能以及软件与环境的交互。
功能需求
功能需求(functional requirement)定义了开发人员必须实现的软件功能,以及为了有效实现这些功能而必须达到的非功能要求、约束条件等,使得用户能完成他们的任务,从而满足了业务需求
功能需求依赖于用户需求,是用户需求在系统上的一个映射(Mapping)。
面向对象的需求建模过程
- 画用例图
- 存在于系统外部、与系统交互的人、硬件、其他系统
- 写用例规约
- 考察每个参与者与系统的交互和需要系统提供的服务
- 描述补充规约
- 编写术语表
- 画用例图
需求模型的组成
- 结构化需求模型
- 面向对象需求模型
面向对象分析
OOA模型的组成结构
- /需求模型: 以用例模型为主体。
- 类/对象模型:通过属性、操作和协作者
- 对象-关系模型:静态关系,消息路径
- 对象-行为模型:动态关系,对象间协作与响应消息
OOA过程
- 识别与确定分析类
- 查找分析类
边界类、控制类和实体类
边界类<
> :负责系统与外界的通讯与交通 - ①用户界面类 ②系统接口类 ③设备接口类
控制类<< control>>:负责协调、调度、处理事务并控制系统内部其它对象的行为、
实体类<
>:负责承担系统中需要持久化的信息及其关联的行为
面向对象设计
QS模块独立性、内聚和耦合、
系统架构设计的主要内容(重点掌握)
- 系统高层结构设计
- 套用软件架构模式来设计高层组织结构
- 模型-视图-控制架构(Model-View-Control)
- 层次架构(Layers)
- 管道与过滤器架构(Pipes and Filters)
- 黑板架构(Blackboard)
- 专家系统架构模式。黑板模型主要由“黑板”、知识源(Knowledge Source)和控制机构三大部分组成。
- 黑板”是一个分层的全局工作区,它被分为若干层,每一层用于描述领域问题的某一类信息。
- 知识源是一个知识模块。它的先决条件一旦与黑板状态匹配,该知识源便被激活,其执行结果将导致黑板状态的变化。
- 控制机构是求解问题的推理机构,由监督程序和调度程序组成。监督程序时刻注视着黑板状态,根据黑板状态采用某种策略选择合适的知识源。若知识源的条件部分与黑板状态匹配成功,则将其动作部分放入调度队列。
- 套用软件架构模式来设计高层组织结构
- 确定设计元素
- 识别和确定设计类和子系统,将设计类组织到相应的包中,为子系统设计接口,确定复用机会。
- 映射分析类到设计元素
- 确定子系统 表示具有与类似的特征的包的特定用法。
- 识别和确定设计类和子系统,将设计类组织到相应的包中,为子系统设计接口,确定复用机会。
- 确定任务管理策略
- 多任务、并发执行等可能引起的冲突或运行性能等
- 并行需求三种解决方案:
- 多处理器方案–将并发子系统分配到不同的处理器
- 操作系统方案–将并发子系统分配到相同的处理器并由操作系统提供同步控制
- 应用程序方案–应用软件负责在适当的时间从一个代码分支切换到另一个代码分支
- 两种实现技术
- 引进任务管理部件
- 基于进程和线程的控制
- 并行需求三种解决方案:
- 多任务、并发执行等可能引起的冲突或运行性能等
- 实现分布式机制
- 选择支持远程通信的构件,给出实现构件通信的统一方案
- 确定网络拓扑配置
- 将设计元素分配到网络节点
- 设计分布处理机制
- 选择支持远程通信的构件,给出实现构件通信的统一方案
- 设计数据存储方案
- 选择数据库访问的支持构件,设计类/对象数据的存储、读取、删除或修改等操作的方法
- 基于JDBC的数据存储机制
- 选择数据库访问的支持构件,设计类/对象数据的存储、读取、删除或修改等操作的方法
- 人机界面设计
- 确定统一要求和规范,确定实现的技术基础和工具
- 分类分析用户特点,设计不同界面
- 增加用户界面专用的类与对象
- 利用快速原型演示,改进界面设计
- 确定统一要求和规范,确定实现的技术基础和工具
- 系统高层结构设计
系统元素设计
- 包括类、子系统与接口、包等。系统元素设计包括三方面的内容:
- 类/对象设计
- 在分析类的基础上对每个设计类的属性及其类型、操作及其算法、接收及发送的消息等进行详细设计。
- 子系统设计
- 设计与确定每个子系统内部组织、子系统对应接口、子系统之间的关联等。
- 包设计
- 将逻辑上相关的设计元素组织在一起。
- 类/对象设计
- 包括类、子系统与接口、包等。系统元素设计包括三方面的内容:
模式
- 模式是解决某一类问题的方法论,也是对通用问题的通用解决方案。是把解决某类问题的方法总结、归纳到理论高度,供其他人员在解决类似问题时参考或直接套用。
- 利用已取得成功的设计结果和经验,既可以减少工作量,又可以提高设计结果的质量。
编码与测试
编码风格:
- 清晰与效率标准
- 控制结构
- 源程序的文档化
- 用户友好的输入输出风格
测试的特性
- 挑剔性:测试是证明程序有错,而不是证明程序无错;
- 复杂性:设计测试用例是一项需要细致和高度技巧的工作,不亚于程序的开发;
- 不彻底性:不可能让被测程序在一切可能的输入情况下全部执行一遍。
静态分析和动态测试
- 静态分析(程序不执行)
- 静态分析器分析 (自动方式)
- 代码评审(人工方式)
- 代码会审
- 以小组会的形式进行
- 代码走查
- 以小组会的方式进行
- 办公桌检查
- 程序作者在程序通过编译之后,进行单元测试之前,对源代码进行分析、检验,并补充有关文档,以发现程序中的错误。
- 代码会审
- 动态分析(程序执行)
- 黑盒测试(测试程序功能) 重点掌握
- 把测试对象看做一个黑盒子,测试人员完全不考虑程序内部的逻辑结构和内部特性,只依据程序的需求规格说明书,检查程序的功能是否符合它的功能说明。
- 又叫做功能测试或数据驱动测试。
- 等价分类法
- 边界值分析法
- 错误猜测法
- 白盒测试(测试程序结构)
- 此方法把测试对象看做一个透明的盒子,它允许测试人员利用程序内部的逻辑结构及有关信息,设计或选择测试用例,对程序所有逻辑路径进行测试。
- 又称为结构测试或逻辑驱动测试。
- 逻辑覆盖测试:对所有的逻辑判定,取“真”与取“假”的两种情况都至少测试一次.
- 路径测试:对程序模块的所有独立的执行路径至少测试一次。
- 黑盒测试(测试程序功能) 重点掌握
- 静态分析(程序不执行)
单元测试
- 针对软件设计的最小单位 ─ 程序模块,进行正确性检验的测试工作。目的在于发现各模块内部可能存在的各种差错。
集成测试、
- 在单元测试的基础上,将所有模块按照设计要求组装成为系统。
确认测试、
- 任务是验证软件的功能和性能及其它特性是否与用户的要求一致。
系统测试、
- 将通过确认测试的软件,作为整个基于计算机系统的一个元素,与计算机硬件、外设、某些支持软件、数据和人员等其它系统元素结合在一起,在实际运行环境下,对计算机系统进行一系列的组装测试和确认测试。
阿尔法测试、
- 软件开发公司组织内部人员模拟各类用户对即将面市软件产品进行测试,试图发现错误并修正。
贝塔测试
- 在阿尔法测试之后,由部分实际用户在实际使用环境中对软件进行测试,以进一步发现问题并收集反馈。
软件维护
- 软件维护
- 指软件系统交付使用以后,为了改正软件运行错误,或者因满足新的需求而加入新功能的修改软件的过程。