第1章 软件与软件工程的概念

了解与软件相关的基本概念,包括软件、程序、数据、文档。

软件是计算机系统中与硬件相互依存的另一部分,它是包括程序,数据及其相关文档的完整集合。

  • 软件 = 程序+数据+文档

程序是按事先设计的功能和性能要求执行的指令序列。

  • 程序 = 数据结构+算法

数据是使程序能正常操纵信息的数据结构。 文档是与程序开发,维护和使用有关的图文材料。

了解软件危机的表现及发生的原因。

软件危机的表现:

对软件开发成本和进度的估计常常很不准确。 用户对“已完成的”软件系统不满意。 软件产品的质量往往靠不住,错误多、性能低、不安全、不可靠。 软件通常没有适当的文档资料,常常不可维护。 软件成本在计算机系统总成本中所占的比例逐年上升。 软件开发生产率提高的速度,既跟不上硬件的发展速度,也远远跟不上计算机应用迅速普及深入的趋势。

软件开发面临的挑战:

  1. 不断增长的系统复杂性 软件系统规模越来越大、越来越复杂 需求不断变化,要求更快地构建和交付
  2. 未采用有效的软件工程方法 有些软件团队不重视软件工程方法的应用,使得软件成本高、性能差、可靠性低。 软件工程方法需要随着客观世界的演化而不断发展,迎接交付更复杂的软件的新挑战。
掌握软件工程的概念。

概括地说,软件工程是指导计算机软件开发和维护的工程学科。 采用工程的概念、原理、技术和方法来开发与维护软件,把经过时间考验而证明正确的管理技术和当前能够得到的最好的技术方法结合起来,以经济地开发出高质量的软件并有效地维护它,这就是软件工程。

软件生命周期由哪三个时期组成,每个时期又可划分为哪些阶段?每个阶段的主要任务是什么?

三个时期:软件定义、软件开发、软件使用与维护

软件定义时期包括:

问题定义(确定做什么): 关键问题是:“要解决的问题是什么”。 提交的内容是关于问题性质、工程目标和工程规模的书面报告。

可行性研究(能不能做): 回答的关键问题是:“上一个阶段所确定的问题是否有行得通的解决办法”。 提交的内容为可行性研究报告,即从技术、经济和社会因素等方面研究各方案的可行性。

需求分析(详细的说做什么):

  1. 对用户提出的要求进行分析并给出详细的定义
  2. 准确地回答“目标系统必须做什么”这个问题。
  3. 对目标系统提出完整、准确、清晰、具体的要求。
  4. 编写软件需求说明书或系统功能说明书及初步的系统用户手册

提交管理机构评审

软件开发时期包括:

概要设计(概要说怎么做): 概括地回答“怎样实现目标系统?”。设计程序的体系结构,也就是确定程序由哪些模块组成以及模块间的关系。提交的文档是概要设计说明书。

详细设计(详细说怎么做): 回答“应该怎样具体地实现这个系统”。详细地设计每个模块,确定实现模块功能所需要的算法和数据结构。提交的文档是软件的详细设计说明书。

编码(根据设计编写代码): 写出正确的容易理解、容易维护的程序模块。提交的文档为源程序、详尽的程序说明和单元测试报告。

软件使用与维护时期:

测试: 通过各种类型的测试(及相应的调试)使软件达到预定的要求。 提交的文档为测试计划、详细测试方案以及实际测试结果等。

维护:

  1. 改正性维护 :运行中发现了软件中的错误需要修正。
  2. 适应性维护 :为适应变化了的软件工作环境,需做适当变更。
  3. 完善性维护 :为了增强软件的功能需做变更。
  4. 预防性维护 :修改软件为将来的维护活动预先做准备。
掌握软件工程方法学的三个基本要素及其作用。

方法:完成软件开发的各项任务的技术方法。 工具:为方法的运用提供自动的或半自动的软件支撑环境; 过程:为了获得高质量的软件所需要完成的一系列任务的框架,它规定了完成各项任务的工作步骤。

了解传统方法及面向对象方法各自的特点。

传统方法的特点:

  1. 传统方法建立的软件结构依赖于要完成的功能,当功能需求发生变化时将引起软件结构的整体修改。用户需求基本是针对功能的,系统不稳定。

  2. 传统的软件重用技术是利用标准函数库。标准函数库往往只提供最基本、最常用的功能,还缺乏必要的柔性。

OO方法学的主要优点

可重用性好

传统的软件重用技术是利用标准函数库。 标准函数库往往只提供最基本、最常用的功能,还缺乏必要的柔性。 对象固有的封装性和信息隐蔽,使对象具有较强的独立性。 对象提供了较理想的可重用的软件成分。重用时提供了很大的灵活性。(派生和继承)

可维护性好

面向对象的软件稳定性好 面向对象的软件容易理解 面向对象的软件容易修改 易于测试和调试

第2章 软件生存期模型

典型的软件生存期模型(即软件过程模型)有哪几种,每种模型有哪些优缺点。

软件过程:为了获得高质量的软件所需要完成的一系列任务的框架,它规定了完成各项任务的工作步骤。

可将软件生存周期划分为:

(1)3个过程是:软件定义过程、软件开发过程、软件使用与维护过程。

(2)9个阶段有:可行性研究、需求分析、概要设计、详细设计、实现、组装测试、验收测试、使用与维护、退役。

1、瀑布模型

将软件生存周期的各项活动规定为按固定顺序而连接的若干阶段工作,包括问题定义及规划、需求分析、软件设计、程序编码、软件测试和运行维护等六个基本活动,并且规定了他们自上而下,相互衔接的固定次序,形如瀑布流水,逐级下落,具有顺序性和依赖性,最终得到软件产品。

因此,如果有信息未被覆盖或者发现了问题,那么最好 “返回”上一个阶段并进行适当的修改,项目开发进程从一个阶段“流动”到下一个阶段,这也是瀑布模型名称的由来。

2、V模型

通过开发和测试同时进行的方式来缩短开发周期,提高开发效率。其形状像一个字母A,故称为V模型。传统软件开发模型,一般适用于一些传统信息系统应用的开发。

3、敏捷开发模型

以用户需求进化为核心(强调沟通、弱化文档)、迭代、循序渐进的开发方法。强调以人为本,专注于交付对客户有价值的软件,是一个用于开发和维持复杂产品的框架。

瀑布模型的优缺点

瀑布模型就像工厂流水线一样把软件开发分层化。 让软件开发过程有序、可控,使分工协作成为可能。 质量有保证。 瀑布模型是现代软件工程的起源,软件工程的发展,很大部分都是构建于瀑布模型的基础之上的。 由于瀑布模型几乎完全依赖于书面的规格说明,很可能导致最终开发出的软件产品不能真正满足用户的需要

瀑布模型适用于需求已确定、工作采用线性方式完成的情况。

快速原型模型的优点

有助于满足用户的真实需求 原型系统已经通过与用户的交互而得到验证,据此产生的规格说明文档能够正确地描述用户需求。

增量模型的优点

能在较短时间内向用户提交可完成一些有用的工作的产品,即从第一个构件交付之日起,用户就能做一些有用的工作。 逐步增加产品的功能可以使用户有较充裕的时间学习和适应新产品,从而减少一个全新的软件可能给用户组织带来的冲击。 项目失败的风险较低,虽然某些增量构件可能遇到问题,但其他增量构件将能够成功地交付给客户。 优先级最高的服务首先交付,然后再将其他增量构件逐次集成进来。因此,最重要的系统服务将接受最多的测试。

增量模型的困难

软件体系结构必须是开放的,即向现有产品中加入新构件的过程必须简单、方便。 在把每个新的增量构件集成到现有软件体系结构中时,必须不破坏原来已经开发出的产品。 采用增量模型比采用瀑布模型和快速原型模型更需要精心的设计。

螺旋模型

优点 是开发高风险的大型软件系统的实用模型。 可以降低风险,减少项目因风险造成的损失。 缺点 螺旋模型是风险驱动的,因此要求软件开发人员必须具有丰富的风险评估经验和这方面的专门知识,否则将出现真正的风险:当项目实际上正在走向灾难时,开发人员可能还以为一切正常。

第3章 软件需求分析

软件需求分析分为哪4个步骤?各个步骤的主要任务是什么?

需求获取,需求分析,需求定义,需求验证

需求获取 通过启发、引导客户(或用户)而获得软件的原始需求,即软件的业务要求(needs),简称为N。

需求分析 获取的需求N可能存在各种问题,直接把获取的需求作为软件设计阶段的依据将会导致严重的后果。 需要对获取的需求全面分析并进行相应的调整,从而得到分析的需求R1(b+c)。

需求定义 清晰、全面、系统、准确地描述需求文档,编写需求规格说明。

需求验证 为了确保已定义的需求(需求规格说明)准确无误,并能为客户(或用户)理解和接受,需要对其进行严格的评审。

软件需求分析的困难是什么?

系统的目标或范围问题 需求不准确性问题 需求的易变问题 需求获取除了需要有专业的系统分析师,还需要通过有效的客户/开发者的合作才能成功。

用户说不清楚需求 用户经常变更需求 合作态度 知识技能问题:隔行如隔山 双方误解需求 开发人员写不好需求文档

第4章 人机交互设计

人机交互设计的准则

第5章 面向对象方法与UML

UML模型由事物、关系和图组成

了解UML中的事物及其分类。

事物是对模型中最具代表性成分的抽象; 在UML中,分为结构事物、行为事物、分组事物和注释事物4类。

结构事物:是UML模型的静态部分,主要用来描述概念的或物理的元素,包括类、主动类、接口、对象、用例、参与者、协作、构件和节点等。 行为事物:行为事物是UML模型的动态部分,包括两类: 交互(interaction):由在特定的上下文环境中共同完成一定任务的一组对象之间传递的消息组成。 状态机(state machine):描述了一个对象或一个交互在生存周期内响应事件所经历的状态序列,单个类或者一组类之间协作的行为都可以用状态机来描述。

分组事物 UML模型的组织部分,作用是为了降低模型复杂性。 UML中的分组事物是包(package)。 包是把模型元素组织成组的机制,结构事物、行为事物甚至其他分组事物都可以放进包内。 注释事物 UML模型的解释部分,用来描述和标注模型的任何元素。 通常可以用注释修饰带有约束或者解释的图。

了解UML中的关系,包括依赖关系、关联关系、泛化关系和实现关系等。

wishimg

掌握UML中5种类型的图,包括用例图、类图、顺序图、状态图、活动图。
用例图

用例是对系统提供的功能(即系统的具体用法)的描述。 用例图从用户的角度描述系统功能,并指出各个功能的操作者。 用例图定义了系统的功能需求。

wishimg

类图

类图不仅定义系统中的类,表示类与类之间的关系,也表示类的内部结构(类的属性和操作)。 类图描述的是一种静态关系,在系统的整个生命期内都是有效的。

wishimg

wishimg

wishimg

顺序图

顺序图显示若干个对象间的动态协作关系,它强调对象之间发送消息的先后次序,描述对象之间的交互过程。

wishimg

状态图

状态图描述类的对象可能具有的所有状态,以及引起状态变化的事件,状态变化称作状态转换。通常,状态图是对类图的补充。

wishimg

活动图

活动图描述为满足用例要求而进行的动作以及动作间的关系。 活动图是状态图的一个变种,它是另一种描述交互的方法。

wishimg

第6章 面向对象分析

了解面向对象分析中的三个模型和五个层次。
  • 面向对象分析就是抽取和整理用户需求并建立问题域精确模型的过程。
  • 三个模型:用例模型、对象模型、交互模型
  • 五个层次:类与对象层、属性层、服务层、结构层、主题层
掌握有关用例模型、对象模型和动态模型的基本概念。
能够针对具体应用,建立用例模型、对象模型和动态模型(状态图和顺序图)的过程。

第7章 面向对象设计原则与软件设计模式

掌握面向对象设计原则

单一职责原则、开闭原则、里氏代换原则、依赖倒转原则、合成复用原则、接口隔离原则、迪米特法则。

设计原则名称设计原则简介重要性
单一职责原则类的职责要单一,不能将太多的职责放在一个类中★★★★☆
开闭原则软件实体对扩展是开放的,但对修改是关闭的,即在不修改一个软件实体的基础上去扩展其功能★★★★★
里氏代换原则在软件系统中,一个可以接受基类对象的地方必然可以接受一个子类对象★★★★☆
依赖倒转原则要针对抽象层编程,而不要针对具体类编程★★★★★
接口隔离原则使用多个专门的接口来取代一个统一的接口★★☆☆☆
合成复用原则在系统中应该尽量多使用组合和聚合关联关系,尽量少使用甚至不使用继承关系★★★★☆
迪米特法则一个软件实体对其他实体的引用越少越好,或者说如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用,而是通过引入一个第三者发生间接交互。★★★☆☆
掌握设计模式的概念。

设计模式描述了软件设计过程中某一类常见问题的一般性的解决方案。

设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结,使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。

掌握常用的设计模式:单例模式、简单工厂模式、工厂方法模式、抽象工厂模式、适配器模式、外观模式、桥接模式、观察者模式、迭代器模式。

单例模式:

确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类。 单例模式的要点有三个 某个类只能有一个实例; 它必须自行创建这个实例; 它必须自行向整个系统提供这个实例。

简单工厂模式:

在简单工厂模式中,可以根据参数的不同返回不同类的实例。 简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

简单工厂模式的优点 将对象的创建和对象本身业务处理分离可以降低系统的耦合度,使得两者修改起来都相对容易。 简单工厂模式的要点在于:当你需要什么,只需要传入一个正确的参数,就可以获取你所需要的对象,而无须知道其创建细节。

简单工厂模式的缺点 简单工厂模式最大的问题在于工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,这一点与开闭原则是相违背的。 在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。 使用简单工厂模式将会增加系统中类的个数,在一定程序上增加了系统的复杂度和理解难度。

工厂方法模式:

定义抽象工厂类。 再定义若干具体工厂类

结构型模式(Structural Pattern)描述如何将类或者对象结合在一起形成更大的结构

适配器模式(Adapter Pattern):将一个接口转换成客户希望的另一个接口,使接口不兼容的类可以一起工作

外观模式(Facade Pattern):外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面

行为型模式是对在不同的对象之间划分责任和算法的抽象化。

观察者模式:定义对象间的一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。

第8章 面向对象设计

了解软件系统分解的方法。
掌握典型的面向对象设计模型。
了解4个子系统的设计方法。

第10章 软件测试

了解软件测试的概念、软件测试的目标。
  • 软件测试是为了发现错误而执行程序的过程。
  • 软件测试是根据软件开发各阶段的规格说明和程序的内部结构而精心设计一批测试用例(即输入数据及其预期的输出结果),并利用这些测试用例去运行程序,以发现程序错误的过程。
  • (1) 测试是程序的执行过程,目的在于发现错误; (2) 一个好的测试用例在于, 能发现至今未发现的错误; (3) 一个成功的测试是,发现了至今未发现的错误的测试。
掌握白盒测试中使用逻辑覆盖和基本路径测试的测试用例设计方法。

语句覆盖就是设计若干个测试用例,运行被测程序,使得每一可执行语句至少执行一次

判定覆盖,又称分支覆盖,就是设计若干个测试用例,运行被测程序,使得程序中每个判断框的取真分支和取假分支至少执行一次

条件覆盖就是设计若干个测试用例,运行被测程序,使得程序中每个判断框中的每个条件的可能取值至少执行一次。

判定-条件覆盖就是设计足够的测试用例,使得每个判断框的所有可能取值至少执行一次;判断框中每个条件的所有可能取值至少执行一次。

条件组合覆盖就是设计足够的测试用例,运行被测程序,使得每个判断框的所有可能的条件取值组合至少执行一次。(但可能有的路径会遗漏掉)

路径覆盖就是设计足够的测试用例,覆盖程序中所有可能的路径。 (路径覆盖并不一定达到条件组合覆盖)

掌握程序控制流图的画法及环路复杂性的计算方法。

控制流图 :描述程序控制流的一种图示方法。 即退化的程序流程图。

wishimg

边和结点圈定的区域叫做区域,当对区域计数时,图形外的区域也应记为一个区域。

wishimg

如果判断中的条件表达式是由一个或多个逻辑运算符 (OR, AND, …)连接的复合条件表达式,则需改为 一系列只有单个条件的嵌套的判断。

wishimg

wishimg

McCabe方法,又称环路复杂性度量,是一种基于程序控制流的复杂性度量方法。 它基于一个程序模块的流图中环路的个数。

有向图G的环路复杂性的公式 I. V (G)=m-n+2

​ 其中,V(G)—– 有向图G中的环路个数 ​ m —— 图G中边的个数 ​ n ——- 图G中结点个数 ​ II.区域个数 ​ III.V(G)=判定结点数+1

wishimg

(1) V(G) = 边的条数-节点个数+2 =11-9+2=4 (2) V(G) = 区域个数 = 4 (3) V(G) = 判定节点个数+1 = 3+1=4

掌握黑盒测试用例设计的方法:等价类划分法、边界值分析。
  • 等价类划分法:把所有可能的输入数据,即程序的输入域划分成若干部分,然后从每一部分中选取少数有代表性的数据作为测试用例。
  • 等价类 :某个输入域的子集合。 在该子集合中,各个输入数据对于揭露程 序中的错误都是等效的。测试某等价类的代 表值就等价于对这一类其它值的测试。
  • 等价类的划分 有效等价类: 对于程序的规格说明来说,是合理的、有意义的输入数据构成的集合。 无效等价类:对于程序的规格说明来说,是不合理的,无意义的输入数据构成的集合。 设计测试用例时,要同时考虑有效等价类和无效等价类的设计。
  • 为什么要用边界值分析 大量的错误都发生在输入或输出范围的边界上,而不是在输入范围的内部。
  • 边界值分析不仅考虑输入条件,还要考虑输出空间产生的测试情况。
了解软件测试的步骤和策略,包括单元测试、组装测试、确认测试和系统测试。
  • 单元测试又称模块测试,是针对软件设计的最小单位 ─ 程序模块,进行正确性检验的测试工作。
  • 一次性组装方式(big bang):首先对每个模块分别进行模块测试,然后再把所有模块组装在一起进行测试,最终得到要求的软件系统。 是一种非增殖式组装方式,也叫做整体拼装。
  • 增殖式组装方式:又称渐增式组装 首先对一个个模块进行模块测试,然后将这些模块逐步组装成较大的系统。 在组装的过程中边连接边测试,以发现连接过程中产生的问题。 通过增殖逐步组装成为要求的软件系统。
  • 确认测试的步骤:有效性测试 在开发环境下,运用黑盒测试方法,验证被测软件是否满足需求规格说明书列出的需求。
  • 系统测试(system testing)是将软件作为整个计算机系统的一个元素,与硬件、其他软件、数据、人员等其他系统元素结合在一起,在实际使用环境下,对计算机系统进行一系列的组装测试和确认测试。

第9章 编码

理解程序设计风格的重要性。

程序实际上也是一种供人阅读的文章,有一个文章的风格问题。应该使程序具有良好的风格。

了解程序设计风格的4个方面。

源程序文档化 数据说明标准化 语句结构简单化 输入/输出规范化

重构的概念、目的、具体做法。
  • 重构的概念:在不改变代码外在行为的前提下,对代码做出修改,以改进程序的内部结构。
  • 重构的本质是在代码写好之后改进它的设计。
  • 重构的目的 改进软件的设计。 使软件更容易理解。 帮助尽早的发现错误。 提高编程速度。
  • 重构的流程 读懂代码(包括测试例子代码) 重构 运行所有的Unit Tests