<span>软件工程1</span>
软件工程基础知识
软件生命周期与软件开发模型
一、软件危机与软件工程
1、软件危机
2、软件工程
软件工程是将系统化的、严格约束的、可量化的方法应用于软件的开发、运行和维护,即将工程化应用于软件。
软件工程方法学包括三个要素:方法、工具和过程。
二、软件生命周期
参考:https://blog.csdn.net/foart/article/details/4492080)
是指软件的产生直到报废的生命周期。
包括:问题定义、可行性分析、需求分析、总体设计、详细设计、编码、测试、运行维护等阶段。
1.问题定义
本阶段需要明确回答:“要解决的问题是什么?”。
统分析员应该提出问题的性质、目标和规模的书面报告。通过对实际用户和使用部门的调查、研究,以及讨论、交流,得出一份双方都满意的文档
2 .可行性分析
本阶段需要回答的是:“上一阶段确定的问题有无可行的解决方案,是否值得解决?”。
更进一步明确项目的规模和目标,从技术可行性、经济可行性、操作可行性、法律可行性、社会可行性等方面进行研究,确定是否开发本项目。
3.需求分析
本阶段确定为解决该问题,目标系统必须应具备哪些功能。
系统分析员在本阶段必须与用户密切配合,充分交流,得到经用户确认的系统逻辑模型,用数据流图、数据字典等描述系统的逻辑模型。
需求分析阶段所确定的系统逻辑模型是以后设计和实现目标系统的基础,必须准确、完整的体现用户的需求。
4.总体设计
本阶段确定目标系统的主要功能如何完成。采用流程图或其他工具描述出每种可能的系统,推荐出一个最佳的方案,并制定出实现该系统的详细计划。
本阶段的另一个主要任务是设计软件的结构,确定软件应由哪些模块构成,以及模块之间的关系。
还应考虑系统的开发和应用环境,如计算机系统的配置,计算机网络等。
5.详细设计
详细设计阶段的任务就是把问题的求解具体化,设计出程序的详细规格说明。
通常用HIPO图(层次图/输入/处理/输出)或PDL语言(过程设计语言)描述详细设计的结果。
6.编码和单元测试
本阶段的任务是编写软件程序。程序员应根据目标系统的要求,选取适合的程序设计语言,把详细设计的结果编制成程序,并对每一个模块进行单元测试。
需要考虑软件平台、开发工具等等。
7.综合测试
本阶段的任务是通过各种测试以及相应的调试,使软件达到预定的要求。
应该把测试计划、测试方案、测试结果等以文档的形式保存下来,作为软件配置的一个组成部分。
8.软件维护
软件维护的任务是,通过各种必要的维护活动使系统持久地满足用户的需要。
通常有4类维护活动:改正性维护;适应性维护;完善性维护;预防性维护。
每一项维护活动都应该准确地记录下来,作为正式的文档保存。
三、软件开发模型
参考:软件开发的基本模型
常见的开发模型有:瀑布模型、增量模型、螺旋模型、喷泉模型、智能模型、V模型、快速应用开发模型、构件组装模型、 敏捷方法和统一过程等。
1、瀑布模型
瀑布模型也称为生命周期法,是结构化方法中最常用的开发模型, 它把软件开发的过程分为软件计划、需求分析、软件设计、程序 编码、软件测试和运行维护6个阶段。
特点:
- 阶段间具有顺序性和依赖性:
- 前一阶段完成后,才能开始后一阶段
- 前一阶段的输出文本为后一阶段的输入文本
- 推迟实现的观点
- 质量保证:
- 每个阶段必须交付出合格的文档
- 对文档进行审核
缺点:
- 各个阶段之间产生大量的文档,极大地增加了工作量。
- 由于开发模型是线性的,用户只有等到整个过程的末期才能见到开发成果,从而增加了开发风险。
- 不适应用户需求的变化,并且在需求分析阶段不可能完全获取。
- 在软件开发前期未发现的错误传到后面的开发活动中时,可能会扩散,进而可能会导致整个软件项目开发失败。
所以,瀑布模型适用于<mark>需求明确或很少变更的项目</mark>。
2、快速原型模型
快速原型是利用原型辅助软件开发的一种新思想。
经过简单快速分析,快速建造一个可以运行的软件原型,以便理解和澄清问题,使开发人员与用户达成共识,最终在确定的客户需求基础上开发客户满意的软件产品。
优缺点:
- 优点: 克服瀑布模型的缺点,减少由于软件需求不明确带来的开发风险。
- 缺点: 所选用的开发技术和工具不一定符合主流的发展;快速建立起来的系统结构加上连续的修改可能会导致产品质量低下。
原型类型:
- 探索型原型: 主要用于需求分析阶段,确定所期望的特性,并探索各种方案的可行性。它主要针对开发目标模糊,
- 实验型原型: 主要用于设计阶段,考核;实现方案是否合适,能否实陋
- 演化型原型: 主要用于及早向用户提交一个原型系统,该原型系统或者包含
系统的框架,或者包含系统的主要功能,在得到用户的认可后,将原型系统不断扩充演变为最终的软件系统
3、演化模型
也称为变换模型,根据用户的基本需求,通过快速分析构造出一个初始可运行版本(原型),然后根据用户在使用原型的过程中提出的意见和建议对原型进行改进,获得原型的新版本。重复这一过程,最终可得到令用户满意的软件产品。
快速原型模型是“抛弃式”的,演化模型是“渐进式”原型方法。
<mark>演化模型特别适用于对软件需求缺乏准确认识的情况。</mark>
开发顺序:
- 根据用户的核心需求,设计,编码,测试,后提交用户
- 精化:根据以能满足用户核心需求的核心系统上,增加用户反馈的其他全部功能
优点:
- 很早就可以验证是否符合产品需求。
- 风险管理可以在早期就获得项目进程数据,可据此对后续的开发进度作出比较切实的估算。增加项目成功的机率。
- 经验教训能反馈于本产品的下一个循环过程,提高质量效率。
- 心理上,开发人员早日见到产品的雏型,是一种鼓舞。
- 使用户可以在新的一批功能开发测试后,立即参加验证,以便提供非常有价值的反馈。
缺点:
- 主要需求开始并不完全弄清楚的话,会给总体设计带来困难及削弱产品设计的完整性,并因而影响产品性能的优化及产品的可维护性
- 缺乏严格过程管理的话,这生命周期模型很可能退化为“试-错-改”模式
- 不加控制地让用户接触开发中尚未测试稳定的功能,可能对开发人员及用户都产生负面的影响
4、增量模型
融合了瀑布模型的基本成分和原型实现的迭代特征,是第三种原型化开发方法,但它不是“抛弃式”的,也不是“渐进式”的。 增量模型把软件产品划分为一系列的增量构件,第一个增量往往 是核心的产品,即第一个增量实现了基本的需求。客户对每一个增量的使用和评估都作为下一个增量发布的新特征和功能,这个过程在每一个增量发布后不断重复,直到产生了最终的完善产品。
构件思想:
- 第一构件完成软件提供的基本最核心的功能
- 后面的增构件是为了第一构件提供服务提供功能的
- 而且避免吧难题退后,首先完成的应该是高风险和重要部分
困难:
- 每个新的构件集成到现有的软件结构中必须破坏原来以开发的产品,所以必须定义很好的接口
优点:
- 短时间内向用户提供可完成部分工作的产品
- 逐步增加产品功能可以使用户有时间了解和适应新产品
- 开放结构的软件拥有的维护性明显好于封闭结构的软件
缺陷:
- 容易退化为边做边改模型,从而使软件过程的控制失去整体性
- 如果增量包之间存在相交的情况且未很好处理,则必须做全盘系统分析
增量模型的<mark>特点</mark>是引进了增量包的概念,无须等到所有需求都出来,只要某个需求的增量包出来即可进行开发。
增量模型将功能细化、分别开发的方法<mark>适应于</mark>需求经常改变的软 件开发过程。
5、螺旋模型
限制条件:
- 适应于内部的大规模软件开发:螺旋模型强调风险分析,许多客户都无法接受和相信这种分析因此
- 适合于大规模软件项目(执行风险分析将大大影响项目的利润,进行风险分析就毫无意义)
- 软件开发人员应该擅长寻找可能的风险,准确地分析风险,否则将会带来更大的风险
优点:
- 设计上的灵活性,可以在项目的各个阶段进行变更。
- 以小的分段来构建大型系统,使成本计算变得简单容易。
- 客户始终参为保证了项目不偏离正确方向以及项目的可控性。
- 随着项目推进,客户始终掌握项目的最新信息,从而他或她能够和管理层有效地交互。
- 客户认可这种公司内部的开发方式带来的良好的沟通和高质量的产品。
缺点:
- 很难让用户确信这种演化方法的结果是可以控制的.建设周期长,而软件技术发展比较快,所以经常出现软件开发完毕后,和当前的技术水平有了较大的差距,无法满足当前用户需求。
核心:
- 在于您不需要在刚开始的时候就把所有事情都定义的清清楚楚.在定义最重要的功能时,去实现它,然后听取客户的意见,之后再进入到下一个阶段.如此不断轮回重复,直到得到您满意的最终产品。
每轮循环包含如下六个步骤:
- 确定目标,可选项,以及强制条件
- 识别并化解风险
- 评估可选项
- 开发并测试当前阶段
- 规划下一阶段
- 确定进入下一阶段的方法步骤.
模型:
6、喷泉模型
是一种以用户需求为动力,以对象为驱动的模型,主要用于描述面向对象的软件开发过程,该模型认为软件开发过程自下而上的,各阶段是相互迭代和无间隙的。 软件的某个部分常常被重复工作多次,相关对象在每次迭代中加入渐近的软件成分。
<mark>适合于面向对象的软件开发,开发效率相对较高。</mark>
缺点是常规的项目管理方法不适用。
无间隙是指在开发活动中,分析、设计和编码之间不存在明显的边界。
7、基于构件的开发模型
将整个系统模块化,并在一定构件模型的支持下复用构件库中的一个或多个软件构件,通过组合手段高效率、高质量地构造应用软件系统的过程。
基于构件的开发模型由软件的需求分析和定义、体系结构设计、构件库建立、应用软件构建以及测试和发布5个阶段组成。
优点:
- 构件复用,提高了软件开发的效率。构件可由一方定义其规格说明,被另一方实现。然后供给第三方使用,构件组装模型允许多个项目同时开发,降低了费用,提高了可维护性,可实现分步提交软件产品。
缺点:
- 缺乏通用的组装结构标准,因而引入了较大的风险。可重用性和软件高效性不易协调,需要精干的有经验的分析和开发人员。客户的满意度低,并且由于过分依赖于构件,所以构件库的质量影响着产品质量。
8、快速应用开发模型(RAD)
是一个增量型的软件开发过程模型。强调极短的开发周期。
RAD 模型是瀑布模型的一个“高速”变种,通过大量使用可复用构件, 采用基于构件的建造方法赢得快速开发。如果需求理解得好且约束了项目的范围,随后是数据建模、过程建模、应用生成、测试及反复。
软件开发方法
一、结构化分析和设计
1、结构化分析(SA)
一种面向数据流的需求分析方法,利用图形表达用户需求,常用工具有数据流图、数据字典。
(1)数据流图(DFD)
用来描述数据流从输入到输出的变换流程。
(2)数据字典(DD)
对软件中的每个数据规定一个定义条目,以保持数据在系统中的一致性。
- 数据项:只含一个数据,又称为数据元素
- 数据流:由多个相关数据项组成
- 数据文件(数据库):
2、结构化设计(SD)
是一种面向数据流的设计方法,以分析阶段产生的文档(数据流图、数据字典、软件需求说明书)为基础,逐步求精和模块化的过程。结构化设计通常可以分为概要设计和详细设计。
(1)概要设计
- 概要设计也称为结构设计或总体设计。
- 概要设计的基本任务:设计软件系统结构,进行模块划分,确定每个模块的功能、接口、模块间的调用关系。
- 概要设计工具:结构图、数据字典(DD)、判定树和判定表
(2)详细设计
为每个模块设计其实现的细节。
详细设计工具:
- 程序流程图
- 盒图(NS 图)
- 问题分析图(PAD)
- 程序设计语言 (PDL)
二、面向数据结构的设计
根据输入/输出数据结构导出程序结构。 Jackson方法和Warnier方法是最著名的两个面向数据结构的设计方法。
三 、面向对象的分析与设计
面向对象的方法是一种运用对象、类、继承、封装、聚合、消 息传送、多态性等概念来构造系统的软件开发方法。
面向对象=对象(object) +类(classification) +继承(inheritance) +通信(communication with messages)
采用这四个概念开发的软件系统是面向对象的。
1. 对象(object)
- 对象是系统中用来描述客观事物的一个实体,是构成系统的 一个基本单位。
- 属性(attribute)也称为状态或数据,用来描述对象的静态 特征。
- 操作(operation)(也称方法或服务)规定了对象的行为, 表示对象所能提供的服务。
- 封装(encapsulation)是一种信息隐蔽技术,用户只能看见对象封装界面上的信息,对象的内部实现对用户是隐蔽的。
2. 类(class)
类是一组具有相同属性和相同操作的对象的集合。
- 一个类中的每个对象都是这个类的一个实例(instance)。
- 类是创建对象的模板,从同一个类实例化的每个对象都具有相同的结构和行为。
对象和类的描述
对象和类一般采用“对象图”和“类图”来描述。
3.继承(inheritance)
继承是指特殊类(子类)的对象拥有其一般类(父类)的全部属性与服务。
父类中定义了其所有子类的公共属性和操作,在子类中除了定义自己特有的属性和操作外,可以继承其父类(或祖先类)的属性 和操作,还可以对父类(或祖先类)中的操作重新定义其实现方 法。
如果一个子类只有唯一一个父类,这个继承称为<mark>单一继承</mark>。如果 一个子类有一个以上的父类,这种继承称为<mark>多重继承</mark>。
4. 多态性
多态性(polymorphism)是指同一个操作作用于不同的对象上可以有不同的解释,并产生不同的执行结果。
例如“画”操作,作用在“矩形”对象上,则在屏幕上画一个矩形,作用在“圆”对象上,则在屏幕上画一个圆。
5.消息(message)
消息传递是对象间通信的手段,一个对象通过向另一个对象发送消息来请求其服务。一个消息通常包括接收对象名、调用的操作名和适当的参数(如果有必要的话)。
消息只告诉接收对象需要完成什么操作,但并不指示接收者怎样完成操作。消息完全由接收者解释执行。
面向对象方法的优点
- 与人类习惯的思维方法一致
- 稳定性好
- 可重用性好
- 较易开发大型软件产品
- 可维护性好
模块设计原则
模块设计:高内聚,松耦合,单功能,低扇出。
模块的7种内聚类型
所谓的内聚是指模块内的交互程度,即模块内部各个元素彼此结合的紧密程度。
一个模块内部各元素之间的紧密程度越高,则其内聚性越高,模块独立性越好。
内聚又分为一下几种
-
偶然性内聚:组件的部件是不相关的,只是简单地绑定成单个组件。
不足:程序的可读性和复用性差 -
逻辑性内聚:把相似的功能(类如输入,错误处理)放在一块,通过传递一个参数来决定是哪一个功能来执行。
不足:接口可读性差,代码复用性低 -
时间性内聚:所有的语句在同一时刻被激活,就像电脑关机的时候,其他所有的程序都要被关闭。
不足:模块内的关联不高,而与模块外的关联却很高,所以在维护的时候工作量会 比较大。 -
过程性内聚:简单地把一系列过程关联在一起
不足:代码的复用性比较差 -
通信性内聚:操作相同的输入数据或者输出相同的输出数据,可能产生多种功能。
不足:代码的复用性不高 -
顺序内聚:从一个部分的输出作为另一部分的输入。可能包含几个功能或部分不同的功能。
不足:代码的复用性不高 -
信息聚合:执行多个功能,每个函数都有自己的入口点,每个函数都有独立的代码,所有的功能都在相同的数据结构上执行。不同于逻辑衔接,因为功能没有交织在一起。
-
功能内聚:每一部分都需要执行一个单一的功能。例如,计算平方根或排序数组。通常在其他情况下可重复使用。维修容易。
以上几种内聚程度由低到高
参考:https://blog.csdn.net/qq_20480611/article/details/51329688
7种耦合
模块之间的相对独立性(相互连接的紧密程度)的度量。他取决于各个模块之间接口的复杂程度、调用模块的方式以及哪些信息通过接口。
-
内容耦合(Content Coupling)
如果发生下列情形,两个模块之间就发生了内容耦合。
- 一个模块直接访问另一个模块的内部数据;
- 一个模块不通过正常入口转到另一模块内部;
- 两个模块有一部分程序代码重叠(只可能出现在汇编语言中);
- 一个模块有多个入口。
-
公共耦合(Common Coupling)
若一组模块都访问同一个公共数据环境,则它们之间的耦合就称为公共耦合。公共的数据环境可以是全局数据结构、共享的通信区、内存的公共覆盖区等。
-
外部耦合(External Coupling)
一组模块都访问同一全局简单变量而不是同一全局数据结构,而且不是通过参数表传递该全局变量的信息,则称之为外部耦合。
-
控制耦合(Control Coupling)
如果一个模块通过传送开关、标志、名字等控制信息,明显地控制选择另一模块的功能,就是控制耦合。
-
印记耦合(Stamp Coupling)
如果一组模块通过参数表传递记录信息,就是标记耦合。它是某一数据结构的子结构,而不是简单变量。
-
数据耦合(Data Coupling)
如果一个模块访问另一个模块时,彼此之间是通过数据参数(不是控制参数、公共数据结构或外部变量)来交换输入、输出信息的,则称这种耦合为数据耦合。
-
非直接耦合(Nondirect Coupling)
如果两个模块之间没有直接关系,它们之间的联系完全是通过主模块的控制和调用来实现的,这就是非直接耦合。这种耦合的模块独立性最强。
软件开发文档
软件开发文档是软件开发使用和维护过程中的必备资料。它能提高软件开发的效率,保证软件的质量,而且在软件的使用过程中有指导,帮助,解惑的作用,尤其在维护工作中,文档是不可或缺的资料。