ARTICLE · 1219476
考前八页纸[软件工程]

软件工程,把概念背完就能拿分?
软件工程
开发模型 · 构件化与过程 · 需求工程 · 结构化设计 · 设计模式 · 测试 · 维护
系统架构设计师 · 考前冲刺
📦 7 Parts + Conclusion
👉 滑动
PART 01
开发模型
瀑布 · 原型 · V · 螺旋
PART 02
构件化与过程
CBSD · UP · 敏捷
PART 03
其他方法
逆向工程 · 净室
PART 04
需求工程
获取 · 分析 · 跟踪
PART 05
软件设计
内聚耦合 · 模式
PART 06
软件测试
白盒 · 黑盒 · 阶段
PART 07
软件维护
遗留系统 · 四类
PART ///
写在最后
易错速查
图最多、案例最碎,但套路最固定
「软件工程」这一页,是八页纸里示意图密度最高的一页——瀑布、原型、V 模型、螺旋、构件化开发、统一过程、敏捷、数据流图、状态转换图、ER 图、UML 全家族、内聚耦合表、设计模式三表、集成测试图、性能测试图……几十张图挤在一页里。
一共挂了 15 组题、23 个空。这一页的特点是案例「碎」——单个知识点后面就跟一道题,所以按七条主线拆开,每部分自带案例。
七个分支依次是:开发模型 → 构件化与过程 → 其他方法 → 需求工程 → 软件设计 → 软件测试 → 软件维护。表和图照原样还原,源图未标注答案的题会单独说明。
01
PART
开发模型
DEVELOPMENT MODELS
瀑布模型
一张阶梯图,从左上走到右下:
需求分析 → 软件设计 → 程序设计 → 编码实现 → 单元测试 → 集成测试 → 系统测试 → 运行维护
两个特征
严格区分阶段,每个阶段因果关系紧密相连。
只适合需求明确的项目。
原型模型
同样是阶梯图,但在左侧多了一条从「原型开发」出发的虚线回路——先做一个原型,再回到需求分析重新走一遍。
适合需求不明确的项目。
原型模型两个阶段:原型开发阶段和目标软件开发阶段。
V 模型
一张 V 字形的图,左臂向下、右臂向上,左臂每往下一层,右臂就对应一层测试:
需求分析 ↔ 验收测试与系统测试
概要设计 ↔ 集成测试
详细设计 ↔ 单元测试
测试贯穿于始终。
测试分阶段,测试计划提前。
迭代与增量
脑图把这一支画成两个并列的节点——迭代型与增量型,两者汇聚成一个框:增量与迭代【UP / 敏捷】。也就是说,统一过程和敏捷方法在过程模型上的共同底色,就是「增量 + 迭代」。
螺旋模型
螺旋上依次排布四个象限,每一圈都要再走一遍:
目标设定
决定目标、方案和限制
风险分析
评价方案、识别风险、消除风险
开发与有效性验证
对应「开发和有效性验证、下一产品」
评审
图上另一处标注为「提交线 / 评审」
以快速原型为基础 + 瀑布模型。
考虑了风险问题。
本节案例(4 组 6 空)
哪个模型按「目标设定 / 风险分析」组织阶段(答案 C)
( )把整个软件开发流程分成多个阶段,每一个阶段都由目标设定、风险分析、开发和有效性验证以及评审构成。
A 原型模型
B 瀑布模型
C 螺旋模型
D V 模型
答案C。「风险分析」是螺旋模型的招牌动作,四个象限里唯一带「风险」二字的就是它。
统一过程的阶段与核心工作流(2 空,答案 B、D)
统一过程开发方法分初始、细化、构建和移交四个阶段,每次通过这四个阶段就会产生一代软件,其中( )阶段的核心任务是完成系统架构。统一过程开发方法从另一个维度看,有 9 个核心工作流,其中不包括( )。
第 1 空:A 初始 B 细化 C 构建 D 移交
第 2 空:A 商业建模 B 实现 C 环境 D 风险
答案B、D。四个阶段里「细化」负责把架构定下来;9 个核心工作流是业务建模、需求、分析与设计、实现、测试、部署、配置与变更管理、项目管理、环境——没有「风险」,风险是螺旋模型的语言。
关于敏捷方法,哪一句是错的(答案 B)
下列关于敏捷方法的叙述中,错误的是( )。
A 与传统方法相比,敏捷方法比较适合需求变化大或者开发前期对需求不是很清晰的项目
B 敏捷方法尤其适合于开发团队比较庞大的项目
C 敏捷方法的思想是适应性,而不是预设性
D 敏捷方法以原型开发思想为基础,采用迭代式增量开发
答案B。敏捷强调面对面沟通、小步快跑,适合的是小规模、能坐在一起的团队;「团队比较庞大」恰恰是它的短板,脑图里还专门用「适合小型项目」和「增量迭代,小步快跑」来对比传统方法。
水晶系列与 FDD(2 空,答案 A、D)
( )提倡「机动性」的方法,其家族实际上是一组经过证明、对不同类型项目非常有效的敏捷过程。( )认为有效的软件开发需要 3 要素:人、过程、技术。
第 1 空
A 水晶系列(Crystal)开发方法
B 开放式源码(Open source)开发方法
C SCRUM 开发方法
D 特征驱动开发方法(FDD)
第 2 空
A 自适应软件开发(ASD)
B 极限编程(XP)开发方法
C 开放统一过程开发方法(OpenUP)
D 特征驱动开发方法(FDD)
答案A、D。「机动性」是水晶系列的关键词;「人、过程、技术」三要素是特征驱动开发方法(FDD)的定义,它还定义了 6 种关键角色:项目经理、首席架构设计师、开发经理、主程序员、程序员和领域专家。
02
PART
构件化开发与过程方法
CBSD · RAD · UP · AGILE
基于构件的开发模型(CBSD)
脑图把 CBSD 画成六步流水线,每步都围绕「构件库」转:
需求分析和定义 → 设计构件组装 → 建立构件库 → 构建应用软件 → 测试和发布
配套两个节点:「构件获取」「构件管理」,共同构成「构件库」
【优点】易扩展、易重用、降低成本、安排任务更灵活。
【缺点】构件设计要求经验丰富的架构师、设计不好的构件难重用、强调重用可能牺牲其它指标(如性能)、第三方构件质量难控制。
基于构件的软件工程(CBSE)
CBSE 体现了【购买而不是重新构造】的哲学。
【CBSE 的构件应该具备的特征】五条:
1、可组装性:所有外部交互必须通过公开定义的接口进行。
2、可部署性:构件总是二进制形式的,能作为一个独立实体在平台上运行。
3、文档化:用户根据文档来判断构件是否满足需求。
4、独立性:可以在无其他特殊构件的情况下进行组装和部署。
5、标准化:符合某种标准化的构件模型。
【构件的组装】三种:
1、顺序组装:按顺序调用已经存在的构件,可以用两个已经存在的构件来创造一个新的构件。
2、层次组装:被调用构件的「提供」接口必须和调用构件的「请求」接口兼容。
3、叠加组装:多个构件合并形成新构件,新构件整合原构件的功能,对外提供新的接口。
三大构件标准
CORBA、Sun 的 J2EE、Microsoft 的 DNA
快速应用开发(RAD)
两条并列的路线:
SDLC(瀑布)→ 业务建模 → 数据建模 → 过程建模 → 应用生成 → 测试与交付
CBSD(基于构件)→ 业务建模 → 数据建模 → 过程建模 → 应用生成 → 测试与交付
图右侧标出「【能快速的原因】」指向这两条路线
统一过程(UP / RUP)
四个阶段
初始 → 细化 → 构造 → 移交(「迭代」贯穿每个阶段,图上细化与构造各有第 1 次、第 2 次两次迭代)
9 个核心工作流
业务建模 · 需求 · 分析与设计 · 实现 · 测试 · 部署 · 配置与变更管理 · 项目管理 · 环境
三大特点
用例驱动 · 以架构为中心 · 迭代和增量
四个阶段各自的任务,图上写得比较细:
初始
定义最终产品视图和业务模型,确定系统范围。
细化
设计及确定系统架构,制定工作计划及资源要求。
构造
开发剩余构件和应用程序功能,把这些构件集成为产品,并进行详细测试。
移交
确保软件对最终用户是可用的,进行 β 测试,制作产品发布版本。
敏捷宣言
√ 个体和交互胜过过程和工具
√ 可工作的软件胜过大量的文档
√ 客户合作胜过合同谈判
√ 响应变化胜过遵循计划
脑图把敏捷方法和传统软件开发方法做了四项对照:
对应传统方法的「以开发过程为本」
对应传统方法的「预设性的」
「增量迭代,小步快跑」,对应传统方法的「整体分阶段」
图上与「无软件开发方法」的「无序,不可控」并列对比
敏捷方法 — XP
4 大价值观
沟通【加强面对面沟通】
简单【不过度设计】
反馈【及时反馈】
勇气【接受变更的勇气】
12 条过程实践规则
简单设计 · 测试驱动 · 代码重构 · 结对编程 · 持续集成 · 现场客户
发行版本小型化 · 系统隐喻 · 代码集体所有制 · 规划策略 · 规范代码 · 40 小时工作机制
脑图另标出「从相关方处获得需求」
敏捷方法 — SCRUM
产品负责人(PO)
产品待办列表 → 迭代计划会议 → 迭代待办事项 → 迭代(1–4 周)→ 每日站会 → 潜在可发布的产品增量
迭代评审会议、迭代回顾会议
同一层级上,脑图还列了另外几种敏捷家族的方法:
极限编程(XP)
价值观【交流、朴素、反馈、勇气】、近螺旋式的开发方法。
水晶方法
提倡「机动性」的方法,拥有对不同类型项目非常有效的敏捷过程。
SCRUM
侧重于项目管理。
特征驱动开发方法(FDD)
认为有效的软件开发需要 3 要素【人、过程、技术】。定义了 6 种关键的项目角色:项目经理、首席架构设计师、开发经理、主程序员、程序员和领域专家。
开放式源码
程序开发人员在地域上分布很广【其他方法强调集中办公】。
ASD 方法
其核心是三个非线性的、重叠的开发阶段:猜测、合作与学习。
动态系统开发方法(DSDM)
倡导以业务为核心。
03
PART
其他方法
REVERSE ENGINEERING · CLEANROOM
逆向工程
脑图把正向工程、逆向工程、再工程画成一个循环:
现有系统 →(逆向工程)→ 考虑新需求 →(正向工程)→ 新系统;三者合起来就是再工程
图上另标注一句:逆向工程是设计的恢复过程
与逆向工程相关的概念有重构、设计恢复、再工程和正向工程:
(1)重构 / 重组(Restructuring)
重构是指在【同一抽象级别】上【转换系统描述形式】。
(2)设计恢复(Design recovery)
设计恢复是指借助工具从已有程序中抽象出有关数据设计、总体结构设计和过程设计等方面的信息。
(3)逆向工程(Reverse engineering)
逆向工程是分析程序,力图在比源代码更高抽象层次上建立程序的表示过程,逆向工程是设计的恢复过程。
(4)正向工程(Forward engineering)
正向工程是指不仅从现有系统中恢复设计信息,而且使用该信息去改变或重构现有系统,以改善其整体质量。
(5)再工程 / 重构工程(Re-engineering)
再工程是对现有系统的重新开发过程,包括逆向工程、新需求的考虑过程和正向工程三个步骤。
逆向工程导出信息的四个抽象层次:
实现级
包括程序的抽象语法树、符号表、过程的设计表示。
结构级
包括反映程序分量之间相互依赖关系的信息,例如调用图、结构图、程序和数据结构。
功能级
包括反映程序段功能及程序段之间关系的信息,例如数据和控制流模型。
领域级
包括反映程序分量或程序诸实体与应用领域概念之间对应关系的信息,例如实体关系模型。
净室软件工程
√ 净室即无尘室、洁净室。也就是一个受控污染级别的环境。
√ 使用盒结构规约(或形式化方法)进行分析和设计建模,并且强调将正确性验证,而不是测试,作为发现和消除错误的主要机制。
√ 使用统计的测试来获取认证被交付的软件的可靠性所必需的出错率信息。
技术手段
√ 统计过程控制下的增量式开发:控制迭代
√ 基于函数的规范和设计:盒子结构
√ 正确性验证:净室工程的核心
√ 统计测试和软件认证:使用统计学原理,总体太大时必须采用抽样方法
定义 3 种抽象层次:行为视图(黑盒)→ 有限状态机视图(状态盒)→ 过程视图(明盒)。
【缺点】
√ 太理论化,正确性验证的步骤比较困难且耗时。
√ 开发小组不进行传统的模块测试,这是不现实的。
√ 脱胎于传统软件工程,不可避免带有传统软件工程的一些弊端。
04
PART
需求工程
REQUIREMENTS ENGINEERING
概述与阶段划分
软件需求是指用户对系统在功能、行为、性能、设计约束等方面的期望。
【需求工程主要活动的阶段划分】:
需求开发(前四步)
√ 需求获取
√ 需求分析
√ 形成需求规格【形成 SRS】
√ 需求确认与验证【形成需求基线(经过评审的 SRS)】
需求管理
√ 需求管理【变更控制、版本控制、需求跟踪、需求状态跟踪】
图下补了一句:需求管理是对【需求基线】进行管理。
需求分类
分层
√ 业务需求(整体全局)
√ 用户需求(用户视角)
√ 系统需求(计算机化)→ 功能需求 / 性能需求(非功能)/ 设计约束
项目管理维度(QFD)
√ 基本需求(明示,常规需求)
√ 期望需求(隐含)
√ 兴奋需求(多余)
需求获取方法
用户面谈
1 对 1–3,有代表性的用户,了解主观想法,交互好。成本高,要有领域知识支撑。
联合需求计划(JRP)
高度组织的群体会议,各方参与,了解想法,消除分歧,交互好,成本高。
问卷调查
用户多,无法一一访谈,成本低。
现场观察
针对较为复杂的流程和操作。
原型化方法
通过简易系统方式解决早期需求不确定问题。
头脑风暴法
一群人围绕新业务,发散思维,不产生新的观点。
需求分析:结构化方法
核心是一张「数据字典」,向外连出三张图:
数据流图(功能模型)
数据流、加工、数据存储、外部实体
状态转换图(行为模型)
状态(初态、终态)、事件
E-R 图(数据模型)
实体、联系(1:1 / 1:n / m:n 三种联系)
数据字典
数据元素、数据结构、数据流、数据存储、加工逻辑、外部实体
数据流图另配了一个「在线教育学员注册」的实例,从学员、培训部、辅导老师三个外部实体出发,经「注册请求」「课程安排数据」「类别列表」等数据流,穿过加工与数据存储。
需求分析:面向对象分析(OOA)与 UML
UML 的构造块
√ 事物:结构事物(最静态的部分,包括类、接口、协作、用例、活动类、构件和节点)/行为事物(代表时间和空间上的动作,包括消息、动作次序、连接)/分组事物(看成是个盒子,如包、构件)/注释事物(UML 模型的解释部分,描述、说明和标注模型的元素)
√ 关系 · √ 图
公共机制
范围:给一个名字以特定含义的语境
可见性:怎样使用或看见名字
完整性:事物如何正确、一致地相互联系
执行:运行或模拟动态模型的含义是什么
规格说明:事物语义的细节描述,它是模型真正的核心
修饰:通过修饰来表达更多的信息
公共分类:类与对象、接口与实现
扩展机制:允许添加新的规则
UML(统一建模语言):平台无关、语言无关。
UML 图分成静态图(结构图)和动态图(行为图)两大类:
静态图(结构图)
类图:一组类、接口、协作和它们之间的关系
对象图:一组对象及它们之间的关系
构件图:一个封装的类和它的接口
部署图:软硬件之间映射
制品图:系统的物理结构
包图:由模型本身分解而成的组织单元,以及它们之间的依赖关系
组合结构图
动态图(行为图)
用例图:系统与外部参与者的交互
顺序图:强调按时间顺序
通信图(协作图)
状态图:状态转换变迁
活动图:类似程序流程图,并行行为
定时图:强调实际时间
交互概览图
需求定义
通常有两种常用的需求定义方法,各自的适用前提正好相反:
严格定义法
√ 所有需求都能够被预先定义
√ 开发人员与用户之间能够准确而清晰地交流
√ 采用图形 / 文字可以充分体现最终系统
原型法
√ 并非所有的需求都能在开发前被准确的说明
√ 项目参加者之间通常都存在交流上的困难
√ 需要实际的、可供用户参与的系统模型
√ 有合适的系统开发环境
√ 反复是完全需要和值得提倡的,需求一旦确定,就应遵从严格的方法
需求验证与需求跟踪
需求验证
需求验证 → 需求评审(正式评审 / 非正式评审)+ 需求测试
√ 用户签字确认
√ 验收标准之一
需求跟踪
用户原始需求 →(正向跟踪)→ 软件需求 →(正向跟踪)→ 下游工作产品
下游工作产品 →(反向跟踪)→ 软件需求 →(反向跟踪)→ 用户原始需求
两张跟踪矩阵:原始需求 × 用例(FR-1 … FR-m / UC-1 … UC-n);用例 × 元素(功能点、设计元素、代码模块、测试用例)
需求管理:变更控制
需求变更管理过程
识别出问题 → 问题分析和变更描述 → 变更分析和成本计算 → 变更实现 → 修改后的需求
本节案例(4 组 6 空)
需求管理与需求开发(答案 D)
下列关于软件需求管理或需求开发的叙述中,正确的是( )。
A 所谓需求管理是指对需求开发的管理
B 需求管理包括:需求获取、需求分析、需求定义和需求验证
C 需求开发是将用户需求转化为应用系统成果的过程
D 在需求管理中,要求维持对用户原始需求和所有产品构件需求的双向跟踪
答案D。需求管理管的是「需求基线」以及基于它的变更控制、版本控制、需求跟踪和需求状态跟踪,和需求开发是并列关系;A、B 把两者混为一谈,C 说的其实是「需求开发」的定义,落脚点也不对。
功能模型与行为模型(2 空,原图未标注答案)
在结构化分析方法中,用( )表示功能模型,用( )表示行为模型。
第 1 空
A ER 图 B 用例图 C DFD D 对象图
第 2 空
A 通信图 B 顺序图 C 活动图 D 状态转换图
原图未标注答案字母。按结构化需求分析的三张图直接对位:数据流图(DFD)承担功能模型、状态转换图承担行为模型、E-R 图承担数据模型——所以两空应填 C 和 D。
哪种假设不适合严格定义方法(原图未标注答案)
通常有两种常用的需求定义方法:严格定义方法和原型方法。下述的各种假设条件中,「( )」不适合使用严格定义方法进行需求定义。
A 所有需求都能够被预先定义
B 开发人员与用户之间能够准确而清晰地交流
C 需求不能在系统开发前被完全准确地说明
D 采用图形(或文字)充分体现最终系统
原图未标注答案字母。严格定义法的三条前提正好就是 A、B、D,C 是原型法的前提(「并非所有的需求都能在开发前被准确的说明」),所以应选 C。
需求变更管理(2 空,原图未标注答案)
需求变更管理是需求管理的重要内容。需求变更管理的过程主要包括问题分析和变更描述、( )、变更实现。具体来说,在关于需求变更管理的描述中,( )是不正确的。
第 1 空
A 变更调研 B 变更判定 C 变更定义 D 变更分析和成本计算
第 2 空
A 需求变更要进行控制,严格防止因失控而导致项目混乱,出现重大风险
B 需求变更对软件项目开发有利无弊
C 需求变更通常按特定的流程进行
D 在需求变更中,变更审批由 CCB 负责审批
原图未标注答案字母。第一空对着流程图填「变更分析和成本计算」(D);第二空里「有利无弊」是绝对化表述,应选 B。
05
PART
软件设计
DESIGN & PATTERNS
软件系统建模
软件系统建模(Software System Modeling)是软件开发中的重要环节,通过构建软件系统模型可以帮助系统开发人员理解系统、抽取业务过程和管理系统的复杂性,也可以方便各类人员之间的交流。软件系统建模是在系统需求分析和系统实现之间架起的一座桥梁,系统开发人员按照软件系统模型开发出符合设计目标的软件系统,并基于该模型进行软件的维护和改进。
脑图把「物理系统 ↔ 物理模型 ↔ 逻辑模型」画成上下两条线:上面一条是现有系统经模型化、抽象化得到逻辑模型,下面一条是新系统经具体化、实例化回到物理系统,中间标注「软件设计 / 需求分析」,两侧是「调整 / 优化」。
常用的三类建模方法
1、结构化建模方法
以过程为中心的技术,可用于分析一个现有的系统以及定义新系统的业务需求。结构化建模方法所绘制的模型称为数据流图(DFD)。对于流程较为稳定的系统可考虑结构化建模方法。
2、信息工程建模方法(或数据库建模方法)
一种以数据为中心,但过程敏感的技术,它强调在分析和研究过程需求之前,首先研究和分析数据需求。信息工程建模方法所创建的模型被称为实体联系图(ERD)。主要用于数据建模。
3、面向对象建模方法
将「数据」和「过程」集成到被称为「对象」的结构中,消除了数据和过程的人为分离现象。面向对象建模方法所创建的模型被称为对象模型。随着面向对象技术的不断发展和应用,形成了面向对象的建模标准,即 UML(统一建模语言)。UML 定义了几种不同类型的模型图,这些模型图以对象的形式共建一个信息系统或应用系统,是目前比较常用的建模方法。
结构化设计
两条主线
概要设计【外部设计】:功能需求分配给软件模块,确定每个模块的功能和调用关系,形成模块结构图
详细设计【内部设计】:为每个具体任务选择适当的技术手段和处理方法
结构化设计原则
模块独立性原则(高内聚、低耦合)
保持模块的大小适中
多扇入,少扇出
深度和宽度均不宜过高
图例:模块 A:扇入 3,扇出 2
内聚七种从高到低、耦合七种从低到高,两张表必须能背出来:
内聚(高 → 低)
功能内聚
完成一个单一功能,各个部分协同工作,缺一不可
顺序内聚
处理元素相关,而且必须顺序执行
通信内聚
所有处理元素集中在一个数据结构的区域上
过程内聚
处理元素相关,而且必须按特定的次序执行
时间内聚(瞬时内聚)
所包含的任务必须在同一时间间隔内执行
逻辑内聚
完成逻辑上相关的一组任务
偶然内聚(巧合内聚)
完成一组没有关系或松散关系的任务
脑图还给这七种内聚配了一段「记忆方法」,把抽象概念翻译成了生活场景——偶然内聚像垃圾箱,什么都往里扔;逻辑内聚开始把相似的东西放一起,比如所有的报告任务;时间内聚按时间安排事情,像一天的日程;过程内聚像遵循配方做菜,每一步都有位置;通信内聚像柜台只接待 VIP 客户;顺序内聚像流水线上的产品逐步完成;功能内聚像匠人只打造一种产品。
口诀
偶然逻辑,时间过程行;通信顺序,功能好评定。
耦合(低 → 高)
非直接耦合
两个模块之间没有直接关系,它们之间的联系完全是通过主模块的控制和调用来实现的
数据耦合
一组模块借助参数表传递简单数据
标记耦合
一组模块通过参数表传递记录信息(数据结构)
控制耦合
模块之间传递的信息中包含用于控制模块内部逻辑的信息
外部耦合
一组模块都访问同一全局简单变量,而且不是通过参数表传递该全局变量的信息
公共耦合
多个模块都访问同一个公共数据环境
内容耦合
一个模块直接访问另一个模块的内部数据;一个模块不通过正常入口转到另一个模块的内部;两个模块有一部分程序代码重叠;一个模块有多个入口
模块的四个要素
输入和输出:模块的输入来源和输出去向都是同一个调用者,即一个模块从调用者那儿取得输入,进行加工后再把输出返回调用者。
处理功能:指模块把输入转换成输出所做的工作。
内部数据:指仅供该模块本身引用的数据。
程序代码:指用来实现模块功能的程序。
面向对象设计与设计原则
基本过程
分析模型 → 用例模型 →(设计用例实现方案 / 架构图(用包图表示)/ 用例实现图(用交互图表示))→ 设计模型
→ 设计用户界面 / 细化设计模型 / 类图(完整、精确)/ 其他(状态图、活动图等)
图上另标注「设计技术支撑实施」与「(领域模型)」
类的分类
边界类
人机交互 · 用户界面 · API 接口;例:显示屏、窗体、打印机接口、通信协议、对话框、菜单、购物车、报表、二维码
控制类
应用逻辑 · 业务逻辑 · 数据访问逻辑;例:身份验证器
实体类
数据;例:学员类、课程类
设计原则
单一职责原则:设计目的单一的类
★ 开放-封闭原则:对扩展开放,对修改封闭
李氏(Liskov)替换原则:子类可以替换父类
依赖倒置原则:要依赖于抽象,而不是具体实现;针对接口编程,不要针对实现编程
★ 接口隔离原则:使用多个专门的接口比使用单一的总接口要好
组合重用原则:要尽量使用组合,而不是继承关系达到重用目的
★ 迪米特(Demeter)原则(最少知识原则):一个对象应当对其他对象有尽可能少的了解
速记口诀:单抽元件厂
设计模式
三句口诀:创建型「单抽元件厂」、结构型「外侨组员带配饰」、行为型「观摩(模)对(迭)策,责令解放(访),戒(介)忘台(态)」。
创建型设计模式(5 种):
Abstract Factory 抽象工厂模式
记忆关键字:抽象接口。提供一个接口,可以创建一系列相关或相互依赖的对象,而无需指定它们具体的类
Builder 构建器模式
记忆关键字:类和构造分离。将一个复杂类的表示与其构造相分离,使得相同的构建过程能够得出不同的表示
Factory Method 工厂方法模式
记忆关键字:子类决定实例化。定义一个创建对象的接口。但由子类决定需要实例化哪一个类。使得子类实例化过程推迟
Prototype 原型模式
记忆关键字:原型实例,拷贝。用原型实例指定创建对象的类型,并且通过拷贝这个原型来创建新的对象
Singleton 单例模式
记忆关键字:唯一实例。保证一个类只有一个实例,并提供一个访问它的全局访问点
结构型设计模式(7 种):
Adapter 适配器模式
记忆关键字:转换,兼容接口。将一个类的接口转换成用户希望得到的另一种接口,使原本不相容的接口得以协同工作
Bridge 桥接模式
记忆关键字:抽象和实现分离。将类的抽象部分和它的实现部分分离开来,使它们可以独立的变化
Composite 组合模式
记忆关键字:整体-部分,树形结构。将对象组合成树型结构以表示「整体-部分」的层次结构,使得用户对单个对象和组合对象的使用具有一致性
Decorator 装饰模式
记忆关键字:附加职责。动态的给一个对象添加一些额外的职责。它提供了用子类扩展功能的一个灵活的替代,比派生一个子类更加灵活
Facade 外观模式
记忆关键字:对外统一接口。定义一个高层接口,为子系统中的一组接口提供一个一致的外观,从而简化了该子系统的使用
Flyweight 享元模式
记忆关键字:细粒度,共享。提供支持大量细粒度对象共享的有效方法
Proxy 代理模式
记忆关键字:代理控制。为其他对象提供一种代理以控制这个对象的访问
行为型设计模式(11 种):
Chain of Responsibility 职责链模式
记忆关键字:传递请求,职责链接。通过给多个对象处理请求的机会,减少请求的发送者与接收者之间的耦合,将接收对象链接起来,在链中传递请求,直到有一个对象处理这个请求
Command 命令模式
记忆关键字:日志记录、可撤销。将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化,将请求排队或记录请求日志,支持可撤销的操作
Interpreter 解释器模式
记忆关键字:解释器、虚拟机。给定一种语言,定义它的文法表示,并定义一个解释器,该解释器用来根据文法表示来解释语言中的句子
Iterator 迭代器模式
记忆关键字:顺序访问,不暴露内部。提供一种方法来顺序访问一个聚合对象中的各个元素而不需要暴露该对象的内部表示
Mediator 中介者模式
记忆关键字:不直接引用。用一个中介对象来封装一系列的对象交互。它使各对象不需要显式地相互调用,从而达到低耦合,还可以独立的改变对象间的交互
Memento 备忘录模式
记忆关键字:保存,恢复。在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,从而可以在以后将该对象恢复到原先保存的状态
Observer 观察者模式
记忆关键字:通知、自动更新。定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新
State 状态模式
记忆关键字:状态变成类。允许一个对象在其内部状态改变时改变它的行为
Strategy 策略模式
记忆关键字:算法替换。定义一系列算法,把它们一个个封装起来,并且使它们之间可互相替换,从而让算法可以独立于使用它的用户而变化
Template Method 模板方法模式
记忆关键字:子类按照父类的模板去实现。定义一个操作中的算法骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重新定义算法的某些特定步骤
Visitor 访问者模式
记忆关键字:数据和操作分离。表示一个作用于某对象结构中的各元素的操作,使得在不改变各元素的类的前提下定义作用于这些元素的新操作
UML 图整体解释
脑图把每种 UML 图对应到它的版本和用途,考卷上常问「这张图是干什么的」:
类图(UML 1.x)
描述了系统中对象的类型以及它们之间存在的各种静态关系。
组件图(UML 1.x,UML 2.0 重新定义了)
描绘了系统中组件提供的、需要的接口、端口等,以及它们之间的关系。
对象图(UML 1.x)
对象图是类图的一个实例,是系统在某个时间点的详细状态的快照。
轮廓图(UML 2.0)
提供了一种通用的扩展机制,用于为特定域和平台定制 UML 模型。
组合结构图(UML 2.0)
描述了一个「组合结构」的内部结构,以及他们之间的关系。
部署图(UML 1.x)
描述了系统内部的软件如何分布在不同的节点上。
包图(UML 2.0)
描绘了系统在包层面上的结构设计。
用例图(UML 1.x)
指由参与者、用例,边界以及它们之间的关系构成的用于描述系统功能的视图。
活动图(UML 1.x)
描述了具体业务用例的实现流程。
状态机图(UML 1.x)
描述了对象在它的整个生命周期里,响应不同事件时,执行相关事件的顺序。
序列图(UML 1.x)
描述了在用例的特定场景中,对象如何与其他对象交互。
时序图(UML 2.0)
时序图被用来显示随时间变化,一个或多个元素的值或状态的更改。
交互概览图(UML 2.0)
交互概览图与活动图类似,但是它的节点是交互图。
通讯图(UML 1.x 叫协作图,UML 2.0 改名了)
描述了收发消息的对象的组织关系,强调对象之间的合作关系而不是时间顺序。
界面设计:黄金三法则
★ 置于用户控制之下
· 以不强迫用户进入不必要的或不希望的动作的方式来定义交互方式
· 提供灵活的交互
· 允许用户交互可以被中断和撤销
· 当技能级别增加时可以使交互流水化并允许定制交互
· 使用户隔离内部技术细节
· 设计应允许用户和出现在屏幕上的对象直接交互
★ 减少用户的记忆负担
· 减少对短期记忆的要求
· 建立有意义的缺省
· 定义直觉性的捷径
· 界面的视觉布局应该基于真实世界的隐喻
· 以不断进展的方式揭示信息
★ 保持界面的一致性
· 允许用户将当前任务放入有意义的语境
· 在应用系列内保持一致性
· 如过去的交互模型已建立起了用户期望,除非有迫不得已的理由,不要改变它
本节案例(1 题)
哪一句不符最少知识原则(答案 C)
最少知识原则(也称为迪米特原则)是面向对象设计原则之一,指一个软件实体应当尽可能少地与其他实体发生相互作用。这样,当一个实体被修改时,就会尽可能少地影响其他的实体。下列叙述中,「( )」不符最少知识原则。
A 在类的划分上,应当尽量创建松耦合的类
B 在类的设计上,只要有可能,一个类型应当设计成不变类
C 在类的结构设计上,每个类都应当尽可能提高对其属性和方法的访问权限
D 在对其他类的引用上,一个对象对其他对象的引用应当降到最低
答案C。最少知识原则的方向是「少暴露、少依赖」,C 说的却是「尽可能提高访问权限」,正好反着走。提高访问权限意味着更多实体能看到并依赖它,耦合只增不减。
06
PART
软件测试
TESTING
测试类型
动态测试【计算机运行】
白盒测试法 · 黑盒测试法 · 灰盒测试法
静态测试【人工监测和计算机辅助分析】
桌前检查 · 代码审查 · 代码走查
静态分析方法有四类:
控制流分析:是否存在没有使用的语句 / 无法达到的语句 / 调用并不存在的子程序。
数据流分析:引用未定义的变量、对以前未使用的变量再次赋值。
接口分析:模块之间接口的一致性、子程序和函数之间的接口一致性、函数形参与实参的数量、顺序、类型的一致性。
表达式分析:括号不配对、数组引用越界、除数为零。
黑盒与白盒测试
白盒测试【结构测试】:主要用于单元测试阶段
控制流测试【逻辑覆盖测试(语句覆盖最弱,路径测试覆盖最强)】
数据流测试
程序变异测试【错误驱动测试】
黑盒测试【功能测试】:主要用于集成测试、确认测试和系统测试阶段
等价类划分:不同等价类,揭示不同问题;有效等价类 / 无效等价类。
边界值分析:1 <= x <= 10,可取 x 的值为 0、1、10 和 11 作为测试数据。
错误推测:依靠测试人员的经验和直觉。
判定表:最适合描述在多个逻辑条件取值的组合所构成的复杂情况下,分别要执行哪些不同的动作。
因果图:根据输入条件与输出结果之间的因果关系来设计测试用例。
脑图给白盒测试的三种方法各配了一个例子,讲得很细:
控制流测试
主要关注程序的控制结构,确保所有可能的执行路径都经过测试。它通常涉及创建和检查程序流程图来识别循环、条件判断、分支等控制结构。
例:函数 get_grade(score) 按 90 / 80 / 70 分段返回 A、B、C、D,就分别取 95、85、75、65 四个输入覆盖全部分支路径
数据流测试
着重于程序中数据的生命周期,包括数据的定义、使用和覆盖。它旨在验证程序中数据的正确性和合理性。
例:账户余额更新函数 update_balance(transactions, initial_balance),关注 balance 是否被初始化为 initial_balance 后正确使用、每次 transaction 处理后是否正确更新、提现且余额不足时是否未发生变化
错误驱动测试
是一种测试策略,它基于程序可能发生错误的地方进行测试。测试者会专门寻找程序的弱点并尝试引入错误以确保程序能够妥善处理。
例:向 update_balance 传入空的 transactions 列表、负数的初始余额、包含非法交易类型的 transactions、余额不足时提现超额金额
测试阶段
单元测试:依据【详细设计】,模块测试,模块功能、性能、接口等
集成测试:依据【概要设计】,模块间的接口
系统测试:依据【需求文档】,在真实环境下,验证完整的软件配置项能否和系统正确连接
确认测试:依据【需求文档】,验证软件与需求的一致性。内部确认测试、Alpha 测试、Beta 测试、验收测试
回归测试:测试软件变更之后,变更部分的正确性和对变更需求的符合性
集成测试策略
装配方式
一次性组装【风险高】
增量式组装【测试全面】
增量式的三条路线
√ 自顶向下【需要桩模块】
√ 自底向上【需要驱动模块】
√ 混合式【桩模块和驱动模块都需要】
图例:测试用例 → 驱动模块 → 被测模块 → 桩模块 ×3 → 测试结果
性能测试
测试阶段(图上并列的六类)
功能测试 · 性能测试 · 健壮性测试 · 用户界面测试 · 安全性测试 · 安装与反安装测试
性能测试细分(5 种)
负载测试:各种工作负载下系统的性能
压力测试【测上限】:系统的瓶颈或不能接受的性能点
强度测试【测下限】:系统资源特别低的情况下运行
容量测试【并发测试】:同时在线的最大用户数
可靠性测试:MTTF 之类的参数
本节案例(4 组 6 空)
动态测试与静态测试各有哪些(2 空,答案 A、C)
软件测试一般分为两个大类:动态测试和静态测试。前者通过运行程序发现错误,包括( )等方法;后者采用人工和计算机辅助静态分析的手段对程序进行检测,包括( )等方法。
A 边界值分析、逻辑覆盖、基本路径
B 桌面检查、逻辑覆盖、错误推测
C 桌面检查、代码审查、代码走查
D 错误推测、代码审查、基本路径
答案A、C。动态测试三项(边界值分析、逻辑覆盖、基本路径)都要靠「跑程序」;静态测试的三件套是桌前(桌面)检查、代码审查、代码走查,正好对应脑图里挂在「静态测试」下的那三个框。
属于哪一类静态分析(答案 B)
在静态测试中,主要是对程序代码进行静态分析。「数据初始化、赋值或引用过程中的异常」属于静态分析中的( )。
A 控制流分析
B 数据流分析
C 接口分析
D 表达式分析
答案B。题干里的「初始化、赋值、引用」都是变量的使用环节,正是数据流分析的三个动作;控制流分析看的是语句能不能到达、子程序存不存在。
单元测试里的驱动模块与桩模块(答案 A)
在单元测试中,( )。
A 驱动模块用来调用被测模块,自顶向下的单元测试中不需要另外编写驱动模块
B 桩模块用来模拟被测模块所调用的子模块,自顶向下的单元测试中不需要另外编写桩模块
C 驱动模块用来模拟被测模块所调用的子模块,自底向上的单元测试中不需要另外编写驱动模块
D 桩模块用来调用被测模块,自底向上的单元测试中不需要另外编写桩模块
答案A。驱动模块在上、负责调用被测模块,桩模块在下、模拟被调用的子模块,这一点四个选项里只有 A 说对了;自顶向下是从上层往下测,上层已经有了,所以不需要再写驱动模块。
测上限与最大并发数(2 空,答案 A、D)
软件性能测试有多种不同类型的测试方法,其中,( )用于测试在限定的系统下考查软件系统极限运行的情况,( )可用于测试系统同时处理的在线最大用户数量。
第 1 空
A 强度测试 B 负载测试 C 压力测试 D 容量测试
第 2 空
A 强度测试 B 负载测试 C 压力测试 D 容量测试
答案A、D。「限定系统下考查极限运行」对应强度测试【测下限】;「同时在线的最大用户数」对应容量测试【并发测试】。
07
PART
软件维护
MAINTENANCE
遗留系统处置
一张四象限图,纵轴是技术水平、横轴是业务价值,四个格子对应四种演化策略:
高水平 · 高价值 → 改造
改造包括系统功能的增强和数据模型的改造两个方面
高水平 · 低价值 → 集成
图上标注「针对『信息孤岛』」
低水平 · 高价值 → 继承
开发新系统时,需要完全兼容遗留系统的功能模型和数据模型
低水平 · 低价值 → 淘汰
直接弃用
影响可维护性的因素
【可理解性】
是指通过阅读源代码和相关文档,了解软件的功能和如何运行的容易程度。
【可修改性】
是指修改软件的难易程度。
【可测试性】
是指验证软件程序正确的难易程度。可测试性好的软件,通常意味着软件设计简单,复杂性低。因为软件的复杂性越大,测试的难度也就越大。
【可靠性】
一个软件的可靠性越高,需要维护的概率就会越低。
【可移植性】
是指将软件从一个环境移植到新的环境下正确运行的难易程度。软件运行环境的变化是软件维护的一种常见情形,可移植性好的软件会降低维护的概率。
维护类型
★ 正确性维护【修 BUG】
识别和纠正软件错误 / 缺陷,测试不可能发现所有错误。
★ 适应性维护【应变】
指使应用软件适应环境变化【外部环境、数据环境】而进行的修改。
★ 完善性维护【新需求】
扩充功能和改善性能而进行的修改。
★ 预防性维护【针对未来】
为了适应未来的软硬件环境的变化,应主动增加预防性的新的功能,以使用系统适应各类变化而不被淘汰。经典实例:【专用】改【通用】。
本节案例(2 组 4 空)
信息孤岛该用哪种策略(原图未标注答案)
遗留系统的演化可以采用淘汰、继承、改造和集成四种策略。若企业中的遗留系统技术含量较高,业务价值较低,在局部领域中工作良好,形成了一个个信息孤岛时,适合于采用( )演化策略。
A 淘汰
B 继承
C 改造
D 集成
原图未标注答案字母。「技术含量较高」对应纵轴的「高水平」,「业务价值较低」对应横轴的「低价值」,落进左上角那一格——即集成。题干里的「信息孤岛」也正是图上给「集成」标注的场景。
三类维护活动辨析(3 空,原图未标注答案)
软件的维护并不只是修正错误。为了满足用户提出的增加新功能、修改现有功能以及一般性的改进要求和建议,需要进行( ),它是软件维护工作的主要部分;软件测试不可能揭露旧系统中所有潜在的错误,所以这些程序在使用过程中还可能发生错误,诊断和更正这些错误的过程称为( );为了改进软件未来的可维护性或可靠性,或者为了给未来的改进提供更好的基础而对软件进行修改,这类活动称为( )。
第 1 空
A. 完善性维护 B. 适应性维护 C. 预防性维护 D. 改正性维护
第 2 空
A. 完善性维护 B. 适应性维护 C. 预防性维护 D. 改正性维护
第 3 空
A. 完善性维护 B. 适应性维护 D. 改正性维护 C. 预防性维护
原图未标注答案字母,且第三空的选项顺序与前两空不同(D 在 C 前面),照原样保留。按定义对位:增加新功能、修改现有功能 → 完善性维护(A);诊断和更正错误 → 改正性维护(D);为未来打基础、提升可维护性与可靠性 → 预防性维护(C)。
///
LAST
写在最后:这一页最容易混的四组
QUICK RECAP
V 模型的三条对应:需求分析 ↔ 验收测试与系统测试、概要设计 ↔ 集成测试、详细设计 ↔ 单元测试。别把「概要」和「详细」对调。
内聚的七级和耦合的七级方向是反的——内聚越「单一」越高(功能内聚最高),耦合越「间接」越低(非直接耦合最低)。
驱动模块在上(调用被测模块)、桩模块在下(模拟子模块)。自顶向下不需要驱动模块,自底向上不需要桩模块。
四类维护的触发词:出错 → 正确性;环境变了 → 适应性;要新功能、要更快 → 完善性;为未来打基础 → 预防性(经典实例「专用改通用」)。
⚠ 三个「别搞反」
一是严格定义法和原型法的前提条件,题干里出现「不能预先定义」「交流困难」就往原型法上靠;二是需求开发与需求管理是两个并列的活动,管理管的是基线;三是白盒用于单元测试、黑盒用于集成与系统测试,别调换。
✦ 这一页的复习重心
这一页分支多、图多,但真正的考点集中在四处:开发模型的适用场景与风险特征、UML 各图的用途、内聚耦合的排序与识别、测试方法与测试阶段的对应关系。把 23 个空连着做两遍,这页就算过关了。
软件工程的分,一半在背表,一半在读图。
我是 violetdream,一个正在陪你把软考架构啃完的人。
这页纸的内容来自「架构考前八页纸」,共 8 篇,这是第 7 篇。下一篇进入操作系统。
既然看到这里了,如果觉得有用,随手点个赞、在看、转发三连吧。
THANKS FOR READING















































































