一、 软件工程概述
1. 软件的定义
软件是指令的集合
软件是一种数据结构,使得程序可以合理利用信息
软件是软件描述信息,用来描述程序的操作和使用
2. 软件产品的特性是什么?
是一种逻辑产品,与物质产品有很大的区别
软件产品的生产成本主要在开发和研制,完成后,通过复制就产生了大量的软件产品
软件产品的生产过程主要是脑力劳动,大部分软件是定制开发
开发软件的成本不断增加
软件产品不存在磨损和消耗(但是因为软件是在不断迭代更新的,所以软件退化确实存在)
3. 什么是软件危机,软件危机有哪些表现
什么是软件危机:
- 软件开发技术的进步满足不了发展的需求
- 在软件开发中遇见的问题得不到有效的解决方案,久而久之,问题累积起来,形成尖锐的矛盾,导致了软件危机
软件危机的表现:
- 用户对开发出的软件不满意
- 软件产品的质量不可靠
- 软件可维护性较低
- 软件生生产效率较低
- 软件开发成本越来越高
- 软件开发进度难以估计
4. 什么是软件工程,它的目标和内容是什么
要获得成功的软件就需要在设计和构建软件时有所规范,因此,各种形式各个应用领域的软件都需要工程化。
软件工程定义:将系统的、规范的、可量化的方法应用于软件的开发、运行和维护,并对这些方法进行研究
软件工程的内容:软件工程是一种层次化的技术,包含工具、方法、过程和质量关注点。其中,支持软件工程的根基在于质量关注点(quality focus)
- 过程:软件工程的基础。过程是为了获得高质量的软件所需要完成的一系列任务的框架,它规定了完成各项任务的工作步骤
- 方法:为构建软件提供技术上的解决方法,回答怎样做问题
- 工具:为过程和方法提供自动化或半自动化的支持
软件工程的目标:(解决软件危机)
- 付出较低的开发成本,达到要求的功能,取得较好的性能
- 开发的软件可靠性高
- 开发的软件易于移植
- 降低软件维护费用
- 按时完成开发任务,及时交付使用
5. 软件工程的本质特性
软件过程具有下述本质特性:
- 软件工程关注于大型程序的构造
- 软件工程的中心课题是控制复杂性
- 软件经常变化
- 软件必须有效地支持它的用户
- 开发软件的效率非常重要
- 和谐的合作是开发软件的关键
- 在软件工程领域中通常由具有一种文化背景的人代替另一种文化背景的人创造产品
6. 什么是软件生存周期
软件生存周期:一个软件从提出开发要求开始到该软件报废为止的整个时期
包括:
- 可行性分析和项目开发计划
- 需求分析
- 概要设计
- 详细设计
- 编码
- 测试
- 维护
二、软件工程方法学
软件工程方法学包含 3 个要素:方法、工具和过程
- 方法:完成软件开发的各项任务的技术方法,回答怎样做问题
- 过程:为了获得高质量的软件而定义的一系列任务的框架,它规定了完成各项任务的工作步骤
- 工具:为过程和方法提供自动化和半自动化的技术支持
1. 传统/结构化开发方法
结构化开发方法把软件生命周期的全过程依次划分为若干个阶段,然后顺序地完成每个阶段的任务。前一个阶段任务的完成是开始进行后一个阶段工作的前提和基础,而后一阶段任务的完成通常是使前一阶段提出的解法更进一步具体化。且每个阶段都需要提交详细的文档。(类似瀑布模型)
结构化开发方法主张把软件系统按功能进行逐步的细分,采用自顶向下设计方法,在设计阶段需要考虑每个模块应该分解成哪些子模块,每个子模块又该分解成哪些更小的子模块,以此内推,直到模块被细化为一个个函数。
结构化开发方法把数据和对数据的处理分离开来,增加了软件开发与维护的难度
这种结构化的设计方法显然是有局限性的:
- 设计不够直观,与人类的思维方式不一致。因为开发者需要将客观世界的模型分解成一个个功能,每个功能用于完成一定的数据处理。
- 适应性差,可扩展性不强。由于采用自顶向下的设计方法,当用户需求改变时,需要自顶向下的修改模块结构,维护的成本相当大。
2. 面向对象开发方法
面向对象程序设计方法的基本思想是使用类、对象、继承、封装和消息等概念进行程序设计。它从现实世界客观存在的事物(对象)出发来构造软件系统。强调尽可能用人类自然的思维方式思考问题,认识问题,从而将现实世界中的事物抽象成系统中的类,作为系统的基本构成单元。这样构建的系统能直接映射客观世界,更符合现实世界的本来面貌。
面向对象方法将数据与数据操作封装成一个整体,对象的修改只能由自身的成员函数完成。
面向对象的设计方法的优点是:
与人类习惯的思维方式一致;
稳定性好
可重用性好
易于开发大型的软件产品
可维护性好
三、软件过程
1. 什么是软件过程
软件过程是软件工程的基础。过程是为了获得高质量的软件所需要完成的一系列任务的框架,它规定了完成各项任务的工作步骤
2. 什么是软件过程模型
通常使用软件过程模型简洁地描述软件过程。生命周期模型规定了把生命周期划分成哪些阶段及各个阶段的执行顺序,因此,也成为软件过程模型。
软件过程模型:描述软件开发过程中各种活动如何执行的模型。对软件开发提供强有力的支持,为开发过程中的活动提供统一的政策保证,为参与开发的人员提供帮助和指导,是软件生存周期模型化技术的基础,也是建立软件开发环境的核心。
3. 常见的软件过程模型
① 瀑布模型 waterfall model
瀑布模型又称为经典生命周期,它提出了一个系统的、顺序的软件开发方法
开发过程是通过设计一系列阶段顺序展开的,从系统需求分析开始直到产品发布和维护,每个阶段都会产生循环反馈,因此,如果有信息未被覆盖或者发现了问题,那么最好 “返回”上一个阶段并进行适当的修改,项目开发进程从一个阶段“流动”到下一个阶段,这也是瀑布模型名称的由来,如瀑布流水,逐级下落
瀑布模型的前提条件是:需求必须是准确定义且相对稳定的,对于经常变化的项目而言,瀑布模型毫无价值。
瀑布模型的特征:
- 各个阶段之间的顺序性和依赖性:
- 必须等前一阶段的工作完成之后,才能开始后一阶段的工作;
- 前一阶段的输出文档就是后一阶段的输入文档,因此,只有前一阶段的输出文档正确,后一阶段的工作才能获得正确的结果。
瀑布模型的优点:
- 可强迫开发人员采用规范的方法(例如,结构化技术);
- 严格地规定了每个阶段必须提交的文档;
- 要求每个阶段交出的所有产品都必须经过质量保证小组的仔细验证;
瀑布模型的缺点:
- 突出缺点是不适应用户需求的变化
- 各个阶段的划分完全固定,阶段之间产生大量的文档,极大地增加了工作量
- 由于开发模型是线性的,用户只有等到整个过程的末期才能见到开发成果,从而增加了开发风险
② 快速原型模型
所谓快速原型就是快速建立起来的可以在计算机上运行的程序,它所能完成的功能往往是最终产品能完成的功能的一个子集。
快速原型的第一步是快速建立一个能反映用户主要需求的原型系统,让用户在计算机上试用它,然后用户会提出许多修改意见,开发人员按照用户的意见快速的修改原型系统,然后再次请用户试用…… 一旦用户认为这个原型系统满足了用户的需求,原型系统将被抛弃。也就是说,原型的作用就是为了获知用户的真正需求。
③ 增量过程模型
在许多情况下,初始的软件需求有明确的定义,但是整个开发过程中需要逐步为用户添加更多的功能,此时就用到了增量过程模型
使用瀑布模型或者快速原型模型开发软件的时候,目标都是一次就把一个满足所有需求的产品交给用户。而增量过程模型交付一系列称为增量的版本,随着每个版本的交付,再逐步为用户提供更多的功能
④ 螺旋模型
集合了瀑布模型和快速原型的优点,螺旋模型就相当于在每个阶段之前都增加了风险分析过程的快速原型模型。如果风险不能排除,则停止开发工作或大幅度消减项目规模,如果风险排除,则进入下一个开发步骤,这个工作过程和瀑布模型类似。
螺旋模型适用于内部开发的大规模软件项目,因为只有内部开发的项目,才能在风险过大时方便的中止项目。
④ 喷泉模型
“喷泉” 这个词体现了面向对象软件开发过程迭代和无缝的特性。
两个活动之间存在交迭,而面向对象方法在概念和方法上的一致性,保证了在各项开发活动之间的无缝过渡。
4. Rational 统一软件开发过程 / RUP
① 什么是 RUP
Rational 统一过程(Rational Unified Process,RUP)是由Rational公司推出的一种完整且完美的软件过程
RUP 总结了经过多年商业化验证的 6 条最有效的软件开发经验,这些经验被称为 最佳实践
- 迭代开发
- 管理需求
- 使用基于构件的体系结构
- 可视化建模
- 验证软件质量
- 控制软件变更
② RUP 的三大特点
软件开发是一个迭代过程
RUP强调软件开发是一个迭代模型(Iterative Model),它定义了四个阶段(Phase):
初始(Inception)
细化(Elaboration)
构造(Construction)
交付(Transition)
只有通过了上一阶段才能进入下一阶段,这种迭代模型的实现在很大程度上提供了及早发现隐患和错误的机会,因此被现代大型信息技术项目所采用。
软件开发是由用例驱动的
用例是RUP方法论中一个非常重要的概念。简单地说,一个用例就是系统的一个功能。在系统分析和系统设计中,用例被用来将一个复杂的庞大系统分割、定义成一个个小的单元,这个小的单元就是用例。然后以每个小的单元为对象进行开发。
按照RUP过程模型的描述,用例贯穿整个软件开发的生命周期。在需求分析中,客户或用户对用例进行描述,在系统分布和系统设计过程中,设计师对用例进行分析,在开发实现过程中,开发编程人员对用例进行实现,在测试过程中,测试人员对用例进行检验。
软件开发是以架构设计为中心的
构架设计(ArchitecturalDesign)是系统设计的一个重要组成部分。在构架设计过程中,设计师必须完成对技术和运行平台的选取,整个项目的基础框架( Framework)的设计,完成对公共组件的设计,如审计( Auditing)系统、日志(Iog)系统、错误处理(Exception Handling)系统、安全(Security)系统等。设计师必须对系统的可扩展性( Extensibility)、安全性(Security)、可维护性( Maintainability)、可延拓性(Scalability)、可重用性(Reusability)和运行速度(Performance)提出可行的解决方案。
5. 敏捷开发过程与极限编程
① 什么是敏捷开发过程
为了使软件开发团队具有高效工作和快速响应的能力,17 位著名的软件专家起草了敏捷软件开发宣言,由下述 4 个简单的价值观声明组成:
个体和交互胜过过程和工具
可以工作的软件胜过面面俱到的文档
客户合作胜过合同谈判
响应变化胜过遵循计划
根据上述价值观提出的软件过程称为敏捷开发过程,其中最重要的是极限编程
🚩 敏捷开发以用户的需求进化为核心,采用迭代、循序渐进的方法进行软件开发。在敏捷开发中,软件项目在构建初期被切分成多个子项目,各个子项目的成果都经过测试,都具备集成和可运行的特征。
换言之,就是把一个大项目分为多个相互联系,但也可独立运行的小项目,并分别完成,在此过程中软件一直处于可使用状态。
敏捷开发属于增量式开发,对于需求范围不明确,需求变更较多的项目而言,可以很大程度上响应和拥抱变化。
敏捷开发最大程度体现 80/20 法则的价值,通过增量迭代,每次都优先交付那能产生 80% 价值效益的 20% 功能,最大化单位成本收益。
② 什么是极限编程 XP
极限编程(Extreme Programming,XP)是敏捷开发过程中最富盛名的一个,”极限” 二字的含义是指把好的开发实践运用到极致。极限编程广泛应用于需求模糊且经常改变的场合。
四、可行性研究
1. 可行性研究的目的
并非任何问题都能在预定的系统规模或时间期限内解决,可行性研究的目的就是用最小的代价在尽可能短的时间内确定问题是否能够解决。如果问题没有可行的解,分析员应该建议停止这项开发工程。
2. 从哪些方面进行可行性研究
- 技术可行性:使用现有的技术能实现这个系统吗
- 经济可行性:这个系统的经济效益能超过它的开发成本吗
- 操作可行性:系统的操作方式在这个用户组织内行得通吗
五、需求
1. 什么是需求工程
需求工程 (Requirement Engineering / RE)
制作一个软件的最终目的是满足客户的需求,然而开发人员往往无法准确理解客户的需求,又或是客户无法准确描述甚至根本不清楚自己的需求。试想在开发一个计算机软件时,如果软件解决的问题是错误的,那么即使软件再精巧也满足不了任何人的要求。
需求工程就是致力于不断理解需求。需求工程为理解客户需要,分析要求,评估可行性等工作提供了良好的机制,为设计和构造奠定了坚实的基础,如果没有需求工程,那么实现的软件很有可能无法满足用户的需求。
2. 需求分析
① 什么是需求分析
需求分析也称软件需求分析,是开发人员经过深入细致的调研和分析,准确理解用户的需求和项目的功能等要求,将用户非形式的需求表述转化为完整的需求定义,从而确定系统必须做什么的过程
需求分析的目标是分析系统在功能上要 “实现什么”,而不是 “如何实现”
② 需求分析的过程 / 基本任务
- 确定对系统的综合需求
- 功能需求
- 性能需求
- 可靠性和可用性需求
- 出错处理需求
- 接口需求
- 逆向需求:说明软件系统不应该做什么
- 约束
- 将来可能提出的需求
- 分析系统的数据要求
- 导出系统的逻辑模型
- 修正系统开发计划
六、概要设计和详细设计
1. 什么是概要设计
概要设计也称总体设计,经过了需求分析之后,概要设计重点明确系统总体实现方案,确定软件的总体布局,各个子模块的功能以及各个子模块之间的关系,同时,还要设计系统的总体数据结构和数据库结构,并编写概要设计文档。
2. 概要设计的基本原理
模块化
抽象化
逐步求精
信息隐藏和局部化
使得一个模块内包含的信息对于不需要这些信息的模块来说,是不能访问的
模块独立
模块的独立程度可由两个标准度量:
- 耦合:不同模块之间的互连程度
- 内聚:一个模块内各个元素彼此结合的紧密程度
力争低耦合、高内聚
3. 什么是详细设计
概要设计之后,进入详细设计阶段。重点明确每个模块该如何实现,确定每个模块使用的数据结构、算法等,并编写详细设计说明书
七、软件测试
1. 软件测试的概念、目标和原则
概念:
软件测试是使用人工或自动的手段来运行或测定某个软件系统的过程,其目的在于检验它是否满足规定的需求或弄清预期结果与实际结果之间的差别。
目标:
- 测试的目的在于发现错误;
- 一个好的测试用例是发现了至今尚未发现的错误的测试用例;
- 一个成功的测试时发现了至今尚未发现的错误的测试
原则:
测试用例应由输入数据和预期的输出数据两部分组成。这样便于对照检查,做到有的放矢。
测试且例不仅选用合理输入数据,还要选择不合理的输入数据。这样能更多地发现错误,提高程序的可靠性。对于不合理的输入数据,程序应拒绝接受,并给出相应的提示。
除了检查程序是否做了它应该做的事,还应该检查程序是否做了它不应该做的事。
应制定测试计划并严格执行,排除随意性。
长期保留测试用例。
对发现错误较多的程序段,应进行更深入的测试。
程序员应避免测试自己的程序。测试是一种”挑剔性”的行为,心理状态是测试自己程序的障碍。
2. 白盒测试法
① 什么是白盒测试法
白盒法测试法把测试对象看作一个打开的盒子,测试人员须了解程序内部结构和处理过程,以检查处理过程的细节为基础,对程序中尽可能多的逻辑路径进行测试,检验内部控制结构和数据结构是否有错,实际的运行状态与预期的状态是否一致。
② 逻辑覆盖
从覆盖源程序语句的详尽程度分析,大致有以下一些不同的覆盖标准:
语句覆盖:至少每个语句应该执行一次。语句覆盖是很弱的逻辑覆盖标准
🎲 测试用例:A = 2,B = 0,X = 4
判定覆盖:不仅每个语句必须至少执行一次,而且每个判定的每个分支都至少执行一次
🎲 以上图为例,测试用例:
A = 3,B = 0,X = 3(覆盖 sacbd)
A = 2,B = 1,X = 1(覆盖 sabed)
条件覆盖:不仅每个语句至少执行一次,而且使判定表达式中的每个条件都取到各种可能的结果
以上图为例,有两个判定表达式,每个表达式中有两个条件,为了做到条件覆盖,
在 a 点,应有下述各种结果出现:
A > 1,A ≤ 1,B = 0,B ≠ 0
在 a 点,应有下述各种结果出现:
A = 2,A ≠ 2,X > 1,X ≤ 1
🎲 测试用例:
A = 2,B = 0,X = 4(覆盖 sacbed)
A = 1,B = 1,X = 1(覆盖 sabd)
判定/条件覆盖:使得判定表达式中的每个分支都至少执行一次,而且每个判定表达式中的每个条件都取到各种可能的结果
🎲 以上图为例,测试用例:
A = 2,B = 0,X = 4
A = 1,B = 1,X = 1
条件组合覆盖:每个判定表达式中条件的各种可能组合都至少出现一次
3. 黑盒测试法
① 什么是黑盒测试法
黑盒测试法把被测试对象看成是一个黑盒子,测试人员完全不考虑程序的内部结构和处理过程,只在软件接口处进行测试,依据需求规格说明书,检查程序是否满足功能要求。
黑盒测试能发现的错误类型:
- 不正确或遗漏的功能
- 接口错误
- 数据结构或外部数据库访问错误
- 行为或性能错误
- 初始化或终止错误
白盒测试一般在测试过程的早期执行,而黑盒测试倾向于应用在测试的后期阶段。
下面讲解两种黑盒测试技术
- 等价划分
- 边界值分析
② 等价划分
将程序的输入划分为若干个数据类,从中生成测试用例。理想的测试用例是可以单独发现一类错误
③ 边界值分析 BVA
一般来说,大量的错误发生在输入域的边界处,而不是发生在输入域的中间。
边界值分析 Boundary Value Analysis 选择测试用例检查边界值
一般来说除了使用等价划分设计出的测试方案外,还应该使用边界值分析法再补充下测试方案
八、软件架构
1. 什么是软件体系结构
软件体系结构是指系统的一个或者多个结构,它包括软件构件、构件的外部可见属性以及它们之间的相互关系。
2. 软件架构的重要性
体系结构的重要性:
- 软件体系结构提供了一种表示,有助于对计算机系统开发感兴趣的利益相关者开展交流
- 体系结构突出了早期的设计决策,这些决策对随后的所有软件工程工作都有深远的影响
- 体系结构构建了一个相对较小的、易于理解的模型,该模型描述了系统如何构成以及构件如何一起工作
软件架构的重要性在于它决定了—个系统的主体结构、宏观特性和具有的基本功能。复杂软件设计的成功在于软件系统有宏观层次上结构设计的正确性和合理性。
九、软件工程的人员方面
1. 软件工程师应有的特质
软件工程师应具备的七种特质
- 责任感
- 高度的公平感 / 避免利益冲突和破坏他人劳动成果
- 对用户和团队成员的需求有敏锐的意识
- 良好的抗压能力
- 实事求是 / 坦诚
- 遵守科学规则 / 务实
- 注重细节
十、软件项目管理
1. 软件项目管理和软件开发的关系
所谓管理,就是合理的配置和使用各种资源,以达到既定目标的过程。
软件项目管理先于任何技术活动之前,并且贯穿于整个软件生命周期中。
大多数软件的规模都很庞大,单个软件开发人员无法在规定期限内完成开发工作,因此必须通过软件项目管理把多名软件开发人员合理的组织起来,使他们有效的分工协作共同完成开发任务。