软件工程
软件工程概述
软件:计算机系统中与硬件相互依存的另一部分,它是包括程序,数据及其相关文档的完整集合。
-
软件 = 程序+数据+文档
-
程序(一组计算机指令)
数据(操作对象)
文档(设计报告、规格说明、使用维护手册) -
软件危机包含两方面问题:
如何开发软件,以满足不断增长,日趋复杂的需求
如何维护数量不断膨胀的软件产品
软件工程
-
定义
- 建立并使用完善的工程化原则,以较经济的手段获得能在实际机器上有效运行的可靠软件的一系列方法。
-
软件工程—通用过程框架
- 沟通
- 策划
- 建模
- 构建
- 部署
-
软件生命周期
- 计划
- 需求分析
- 设计
- 编码
- 测试
- 运行维护
-
软件过程模型
-
瀑布模型(文档驱动)
- 阶段间具有顺序性和依赖性。
- 是一种严格线性的、按阶段顺序的、逐步细化的过程模型(开发模式)
-
原型模型(用户驱动)
-
原型模型分类
- 抛弃型原型:用于试验某些概念,试验完系统将无用处
- 进化型原型:原型系统不断被开发和被修正,最终它变为一个真正的系统。
-
原型模型特点
- 从实践中学习(Learning by doing)
改善通信、改善用户参与
使部分已知需求清晰化
展示描述的一致性和完整性
提高系统的实用性、可维护性
节省开发的投入、缩短整个软件的开发周期
- 从实践中学习(Learning by doing)
-
原型模型缺陷
- 用户有时误解了原型的角色,例如他们可能误解原型应该和真实系统一样可靠。
缺少项目标准,进化原型方法有点像编码修正。
缺少控制,由于用户可能不断提出新要求,因而原型迭代的周期很难控制。
额外的花费:研究结果表明构造一个原型可能需要10%额外花费。
为了尽快实现原型,采用了不合适的技术,运行效率可能会受影响。
原型法要求开发者与用户密切接触,有时这是不可能的。例如外包软件。
- 用户有时误解了原型的角色,例如他们可能误解原型应该和真实系统一样可靠。
-
-
演化过程模型
-
演化模型是利用一种迭代的思想方法,它的特征是使软件工程师渐进地开发逐步完善的软件版本。
- 增量模型 (Incremental Model)
- 螺旋模型 (Spiral Model)
- 并发模型(Concurrent development model)
-
-
软件工程的基本原理:
- 需求分析:在软件开发之前,必须明确和详细地定义用户需求。
- 设计:基于需求分析,设计软件架构和组件,确保软件的可维护性和扩展性。
- 实现:根据设计文档编写代码,实现软件功能。
- 测试:通过各种测试方法确保软件满足需求并且没有缺陷。
- 配置管理:管理软件的版本和变更,确保开发过程的可追踪性。
- 质量保证:通过过程和产品的质量控制,确保软件达到预期的质量标准。
- 项目管理:使用项目管理技术来规划、监控和控制软件开发过程。
- 持续改进:软件工程是一个持续改进的过程,通过回顾和学习来提高开发效率和产品质量。
- 软件工程的实践不断发展,随着新技术和方法的出现,这些特征和原理也在不断地被更新和扩展。
-
软件工程的本质特征:
- 工程性:软件工程将软件的开发视为一种工程活动,需要系统化的方法和严格的管理。
- 系统性:软件工程强调软件作为系统的一部分,需要考虑与其他系统组件的交互。
- 可度量性:软件工程强调度量软件产品和开发过程,以便于评估和改进。
- 可预测性:通过使用定量方法和工具,软件工程旨在提高软件项目的可预测性。
- 可维护性:软件工程注重软件的可维护性,确保软件能够适应变化和易于更新。
- 用户中心性:软件工程强调以用户为中心的设计,确保软件满足用户需求。
- 迭代性:软件工程通常采用迭代开发方法,通过多个开发周期逐步完善产品。
- 可重用性:软件工程鼓励组件和代码的重用,以提高开发效率。
可行性分析
目的:确定问题是否值得去解决。
- 用最小的代价,在尽可能短的时间内确定问题是否能够解决。
实质:压缩和简化系统分析和设计的过程。
- 在较高层次上以较抽象的方式进行的系统分析和设计的过程。
可行性分析的步骤
-
复查系统规模和目标
- 目的:确保正在解决的问题是所要解决的问题
-
研究目前正在使用的系统
-
导出新系统的高层逻辑模型
-
进一步定义问题
- 定义问题->分析问题->导出试探性解->再次定义问题
-
导出和评价供选择的解法
技术方法
-
系统流程图
-
描述系统物理概貌
- 基本思想是用图形符号以黑盒子形式描绘组成系统的每个部件
- 系统流程图表达的是数据在系统各部件之间流动的情况,而不是对数据进行加工处理的控制过程
-
-
数据流图
-
描述系统逻辑模型
- 数据流图(Data Flow Diagram,DFD)是一种图形化技术,它描绘信息流和数据从输入移动到输出的过程中所经受的变换。
- 在数据流图中没有任何具体的物理部件,它只是描绘数据在软件中流动和被处理的逻辑过程。它与数据字典一起用来构成系统的逻辑模型。
-
-
数据字典
-
配合数据流图使用
- 数据字典是关于数据的信息的集合,也就是对数据流图中包含的所有元素的定义的集合
-
需求工程
需求:指明必须实现什么的规格说明。它描述了系统的行为、特性或属性
-
好的需求具有特点:
- 一致性、完整性
- 可理解、无二义性
- 可测试
需求分析是指用户对目标系统的功能、行为、性能、设计约束等方面的期望
需求分析产生软件工作特征的规格说明,指明软件和其他系统元素的接口,规定软件必须满足的约束。
需求分析的作用
- 定义软件的范围及必须满足的约束
- 确定软件的功能和性能及与其他系统成分的接口
- 建立数据模型、功能模型和行为模型
- 最终提供需求规格说明,并用于作为评估软件质量的依据。
需求
- 功能需求
- 非功能需求
- 邻域需求
需求工程
- 是指致力于不断理解需求的大量任务和技术。
- 任务:理解客户需要什么、分析要求、评估可行性、协商合理的方案、无歧义地详细说明方案、确认规格说明、管理需求等。
- 即:起始、导出、精化、协商、规格说明、确认和管理,
需求建模方法
-
结构化分析
-
着眼于数据流,自顶向下,逐层分解,建立系统的处理流程,以
数据流图和数据字典为主要工具,建立系统的逻辑模型。-
实体-关系图是数据对象之间的关系
- 数据建模
-
数据流图指出当数据在软件系统中移动时怎样被变换,描绘变换数据流的功能和
子功能。- 数据流图是功能建模的基础
-
状态转换图指明了作为外部事件结果的系统行为
- 是行为建模的基础
-
-
-
面向对象的分析
-
要求把问题空间分解成一些类或对象,找出这些对象的特点
(即属性和服务),以及对象间的关系(一般与特殊,整体与部分),并由此
产生一个规格说明
-
-
需求建模
- 模型:是对对象系统的形式化的特征抽象,概括性或近似地表示。
- 模型化:是通过抽象、概括和一般化,把研究的对象或问题转化为本质(关系
或结构)相同的另一对象或问题,从而加以解决的方法。
需求分析阶段的工作
需求获取
需求建模
需求规格说明
需求评审
需求分析的过程可以分成四个阶段
- 问题识别(需求获取)
- 分析与综合(需求建模)
- 需求描述:编制需求分析阶段的文档
- 需求评审(验证)
面向对象的需求分析
面向对象方法
-
原则:按照人们习惯的思维方式,用面向对象的观点建立问题域的模型,开发出尽可能自然地表现求解方法的软件
-
通常需要建立3种形式的模型,分别是描述系统数据结构的对象模型,描述系统控制结构的动态模型,描述系统功能的功能模型。
-
一个典型的软件系统组合了三方面:它使用数据结构(对象模型),执行操作(动态模型),并且完成数据值的变化(功能模型)。
简单的面向对象分析与设计过程
用例模型
- 用例是对于一组动作序列的描述
- 用例建模的三个主要步骤:确定参与者、确定用例、描述用例
对象模型-----不同阶段的类图
-
建立领域模型──使用概念类
- 现实世界中的概念或者事物。UP领域模型包含概念类。
- 概念类代表业务角色执行业务用例时所处理或使用的事物
-
建立分析类──使用分析类
- 从软件的观点出发,抽象出业务需求中的概念类而得到逻辑化的分析类,它可以被计算机所理解
-
建立设计类图──使用设计类
- 引入设计模型,设计软件类
对象模型-----类图
-
类图建立过程
- 发现领域对象,定义概念类
- 识别对象属性
- 识别对象关系
- 建立概念类图
行为模型----动态图的建立
- 动态图反映用例的实现,顺序图、协作图、活动图、状态图。
- 顺序图、协作图、活动图统称为交互图,当对象行为复杂并存在多种状态转换时,还要有状态图。
设计概念与体系结构设计
软件设计概念
-
体系结构
-
软件的整体结构和这种结构为系统提供概念完整性的方式
-
体系结构包括三部分:
- 程序(模块)的结构或组织
- 构件交互的形式
- 构件所用数据的结构
-
系统体系结构示意图是软件设计的目标之一
-
关注点分离
- 是一个设计概念
- 表明任何复杂问题如果被分解为可以独立解决和优化的若干块,该复杂问题能够更容易地被处理
-
-
自顶向下,逐步细化
-
求精
- 将软件的体系结构按自顶向下方式,对各个层次的过程细节和数据细节逐层细化,直到用程序设计语言的语句能够实现为止,从而最后确立整个的体系结构。
-
-
软件结构
-
程序结构
-
模块化
- 模块化
-
抽象化
-
抽象化
- 过程的抽象
- 数据抽象
-
-
信息隐蔽
-
信息屏蔽
- 每个模块的实现细节对于其它模块来说是隐蔽的
-
-
功能独立
-
功能独立的概念是模块化、抽象概念和信息隐蔽的直接结果。
-
独立性可以使用两条定性的标准评估:
- 内聚性和耦合性
-
耦合:模块之间的互相连接的紧密程度的度量。
-
内聚:模块功能强度(一个模块内部各个元素彼此结合的紧密程度)的度量。
-
模块独立性比较强的模块应是高内聚、低耦合
的模块 -
功能内聚
-
信息内聚
-
通信内聚
-
过程内聚
-
时间内聚
-
逻辑内聚
-
巧合内聚
-
设计模型
-
两个维度观察设计模型:
- 过程维度表示设计模型的演化,设计工作作为软件过程的一部分被执行。
- 抽象维度表示过程的详细级别,分析模型的每个元素转化为一个等价的设计,然后迭代精化。
-
体系结构设计
- 软件体系结构=构件+连接件+约東
- 构件:是具有某种功能的可复用的软件结构单元,表示系统中主要的计算元素 和 数据存储
- 连接件:是构件间建立和维护行为关联与信息传递的途径
-
目标
-
体系结构设计——风格与模式
-
软件体系结构风格(Architectural Styles)是描述特定系统组织方式的惯用范例,强调了软件系统中通用的组织结构。
-
针对某种软件应用场景,应该选择与其相适应的构件,以及合理安排构件间的关系
-
体系结构风格的分类——以数据为中心的体系结构
-
体系结构风格的分类——数据流体系结构
-
体系结构风格的分类——调用—返回体系结构
-
体系结构风格的分类面向对象的体系结构
-
体系结构风格的分类-层次体系结构
-
-
体系结构设计-框架
-
基于网络的WEB参考架构-REST
-
体系架构图
- 产品架构图
- 技术架构图
-
-
构件级设计
-
构件的概念
-
构件是计算机软件中的一个模块化的构造块。
-
系统中模块化的、可配置的和可替换的部件,该部件封装了实现并暴露了一组接口。
-
构件包括一组协作的类
-
设计基于类的构件–基本设计原则
-
四个基本设计原则
-
开闭原则
- 模块应该对外延具有开放性,对修改具有封闭性。
-
Liskov替换原则
-
里氏替换原则(Liskov Substitution Principel)是解决继承带来的问题
- 子类必须完全实现父类的方法
- 在类中调用其他类时务必要使用父类或接口,如果不能使用父类或接口,则说明类的设计已经违背了里氏替换原则。
- 所有引用基类(父类)的地方必须能透明地使用其子类的对象。子类可以扩展父类功能,但不能改变父类原有功能。
-
-
依赖倒置原则
- 依赖倒置原则:依赖于抽象,而非具体实现
- 依赖倒置提倡“面向接口编程”
-
接口分离原则
- 接口分离原则:多个用户专用接口比一个通用接口要好
-
-
实施构件级设计—交互界面设计
- 让用户控制界面:使动作可逆、提供信息反馈。
- 减轻认知负担:划分信息或动作序列、促进视觉清晰度
- 使用户界面一致:视觉一致性、功能一致性
-
-
-
软件测试与质量保障
软件测试
-
目的
- 从用户的角度出发,希望通过软件测试暴露软件中隐藏的错误和缺陷,以考虑是否可接受该产品。
- 从软件开发者的角度出发,希望测试成为表明软件产品中不存在错误的过程验证该软件已正确地实现了用户的要求,确立人们对软件质量的信心。
-
准则
-
方法
-
黑盒测试(功能测试,数据驱动测试)
- 把程序看作一个黑盒子,完全不考虑程序的内部结构和处理过程
- 在程序接口进行的测试,只检查程序功能是否能按规格说明书的规定正常使用,程序是否能适当地接收输入数据并产生正确的输出信息。
-
白盒测试(结构测试,逻辑驱动测试)
- 把程序看成装在一个透明的白盒子里,测试者完全知道程序的结构和处理算法。
- 按照程序内部的逻辑测试程序,检测程序中的主要执行通路是否都能按照预定要求正确工作。
-
-
步骤
-
单元测试
-
测试步骤
- 模块接口测试
- 重要路径测试
- 边界条件测试
- 出错处理测试
- 局部数据结构测试
-
单元测试(代码审查)
- 代码审查:由审查小组正式进行的人工测试源程序;
- 组成人员:
口组长,没有直接参与工程、有能力的程序员;
口程序的设计者;
口程序的编写者;
口程序的测试者。
-
单元测试(计算机测试)
- 两类辅助模块来模拟其他模块
-
-
集成测试任务
-
浙增式组装测试
-
先进行模块测试,然后将这些模块逐步组装成较大的系统,每连接一个模块进行一次测试。
-
两种方案
-
自顶向下集成
-
自底向上集成
-
- -
- 基本路径测试法 -
- -
-
-
-
测试信息流的解释