软件工程 (Software Engineering) 期末复习资料

本资料覆盖全部 16 个 Lecture,包含每讲的核心知识点全面梳理、易错点深度分析和高频考点精讲。

目标是:读完本资料后直接掌握期末考试所需要的全部知识点。

Lecture 1 --- 软件工程导论

快速理解

这是整门课的总纲,回答"什么是软件工程、为什么需要它"。从软件危机出发,引出软件工程的必要性和核心概念。理解本讲是掌握后续所有内容的基础。

核心知识点

1. 软件的定义
  • 软件(Software)= 程序(Programs)+ 文档(Documentation)+ 数据(Data)
    • 程序:在给定输入下产生预期输出的指令序列
    • 文档:描述软件的使用、设计、维护等的人工制品
    • 数据:程序处理的信息结构
  • 软件不是物理产品,是逻辑产品
  • 软件不会"磨损",但会"过时" / "退化"(因环境变化)
2. 软件危机(Software Crisis)
  • 发生背景:1960s,随着硬件性能爆炸式增长,软件规模和复杂度远超手动开发能力
  • 核心问题:软件复杂度增长速度 > 人类开发能力的增长速度
  • 典型表现
    1. 进度和成本失控:项目频繁延期、预算大幅超支
    2. 质量低下:交付的软件充满缺陷,可靠性差
    3. 维护困难:软件难以修改和扩展,修改引入新 bug
    4. 用户满意度低:交付的产品与用户期望不符
3. 软件工程的定义
  • IEEE 定义:"将系统化、规范化、可量化的方法应用于软件的开发、运行和维护(即:对软件的工程化应用)"
  • 核心关键词:systematic(系统化)、disciplined(规范化)、quantifiable(可量化)
  • 软件工程 vs 计算机科学
维度 计算机科学 软件工程
关注点 理论和算法 实践和交付
核心问题 如何自动化 / 计算"正确" 如何在有限资源下构建有用的系统
产出 新算法、新理论 高质量软件产品
时间维度 追求"对"的答案 在时间 / 预算约束下做出权衡
4. 软件四大质量属性
属性 英文 解释 反面例子
可维护性 Maintainability 软件能否被容易地修改以适应新需求或修复缺陷 改一行代码要改几十个文件
可靠性 / 可信性 Dependability 软件在给定条件下正确运行的程度,包括安全性、可靠性、可用性等 银行系统偶尔算错账
效率 Efficiency 软件对系统资源(CPU、内存、磁盘、网络)的使用是否高效 一个简单查询卡死整个服务器
可用性 Usability / Acceptability 用户学习 / 使用软件是否容易,是否被用户接受 功能强大但无人会用
  • 四个属性之间存在权衡:提高安全性可能降低性能,提高可用性可能降低效率。软件工程就是在这些属性之间做权衡(trade-off)。
5. 软件工程面临的挑战
  • 异质性(Heterogeneity):软件需要在不同硬件、操作系统、网络环境中运行
  • 交付压力(Delivery pressure):业务需求要求快速交付
  • 信任和安全性(Trust & Security):用户对软件的信任和隐私保护
  • 业务和社会的变革:需求总是在变化
6. 专业伦理(Professional Ethics)
  • 应遵循的原则:
    • PUBLIC:始终以公众利益为重
    • CLIENT & EMPLOYER:在符合公众利益前提下服务客户和雇主
    • PRODUCT:确保产品和文档达到最高专业标准
    • JUDGMENT:保持判断的独立性和诚实性
    • MANAGEMENT:通过道德和专业的管理推动高质量开发
    • PROFESSION:提升软件工程专业的声誉和诚信
    • COLLEAGUES:公平支持同事
    • SELF:持续学习,提升专业能力

易错点

  1. 把"软件"等同于"程序":考试中常考------软件 = 程序 + 文档 + 数据,三者缺一不可。例如仅仅写好了代码(程序)没有用户手册(文档)和配置数据(数据),不能称为完整的软件。
  2. 混淆四大质量属性
    • Maintainability(可维护性)关注"修改容易度"
    • Dependability(可靠性)关注"不出故障"和"坏了能恢复"
    • Efficiency(效率)关注"资源消耗"
    • Usability(可用性)关注"用户友好程度"
  3. 以为软件工程只是编码:编码只是整个生命周期中很小的一部分。需求、设计、测试、维护等同样重要。
  4. 计算机科学和软件工程混淆:CS 关心"什么是对的"(理论正确性),SE 关心"什么在现实中可行"(实用权衡)。

高频考点

  • 软件危机的定义、三个典型表现(必考------简答或选择)
  • 软件四大质量属性的中文 + 英文名称及含义(必考------考选择或简答名称)
  • 软件工程的定义(特别是 disciplined approach)(高频考)
  • 软件 = 程序 + 文档 + 数据的完整定义
  • 软件工程 vs 计算机科学的区别

Lecture 2 --- 软件过程模型

快速理解

"软件开发有哪些组织方式?"本讲从瀑布模型演进到敏捷方法,展示了软件开发过程的发展脉络。核心是理解每种模型的特点、优缺点和适用场景。

核心知识点

1. 软件过程(Software Process)的概念
  • 软件过程 = 一系列活动(Activities),目标是开发或演化一个软件系统
  • 四个基础过程活动 (所有模型都包含):
    1. 软件规格(Specification):定义系统的功能和约束
    2. 开发 / 设计实现(Development & Implementation):产生软件系统
    3. 验证 / 确认(Validation / Verification):检查软件是否满足需求
    4. 演化 / 维护(Evolution / Maintenance):适应需求变化
2. 瀑布模型(Waterfall Model)
  • 阶段 :需求 → 设计 → 实现 → 测试 → 维护(严格线性顺序
  • 关键特征 :每个阶段有正式评审,评审通过才能进入下一阶段
  • 优点:管理简单、阶段清晰、文档完善、易于理解
  • 缺点
    • 不适应需求变化(晚期修改成本极高)
    • 客户很晚才能看到可运行的软件(风险高)
    • 阻塞问题(一个阶段卡住,后续全部停滞)
  • 适用场景:需求稳定、明确、不太可能变化的项目(如嵌入式系统、安全关键系统)
  • 不适用场景:需求不确定或快速变化的大型项目
3. 增量开发(Incremental Development)
  • 核心思想 :将系统分批次(increment)交付,每个增量增加一些功能
    • 增量 1:核心功能(如登录)
    • 增量 2:扩展功能(如搜索)
    • 增量 3:高级功能(如报表)
  • 优点
    • 用户能早期看到部分功能,提供反馈
    • 降低项目失败风险(核心功能首先开发)
    • 可逐步交付使用
  • 缺点
    • 需要系统架构支持增量扩展
    • 随着增量增加,需求可能偏离原有架构
  • 和迭代(Iterative)的区别
    • 增量:搭积木------每次加一块新功能
    • 迭代 :打磨雕塑------每次对整个系统进行精化改进
4. 螺旋模型(Spiral Model)
  • 核心驱动力风险分析(Risk Analysis)
  • 四大象限 (每轮螺旋):
    1. 确定目标:设定本轮的目标、约束和备选方案
    2. 风险评估:识别和评估方案中的技术风险和项目管理风险
    3. 开发和验证:选择最安全的方案,进行开发和验证
    4. 规划下一轮:评审结果,规划下一轮螺旋
  • 优点
    • 风险管理能力强
    • 适用于大型、高风险、复杂项目
  • 缺点
    • 管理复杂,不适合小项目
    • 风险分析本身需要专业能力
5. RUP(Rational Unified Process)
  • 由 Rational(IBM)公司开发,是一个迭代式、架构优先、用例驱动的过程框架
  • 四大阶段
阶段 英文 主要目标 耗时占比参考
初始 Inception 确定项目范围、识别用例、理解业务需求 ~10%
细化 Elaboration 建立架构基线、解决核心风险、细化用例 ~30%
构建 Construction 大规模开发和测试、构件实现 ~50%
交付 Transition Beta 测试、部署、用户培训 ~10%
  • 六大核心工程工作流(Disciplines)
    • Business Modeling(业务建模)
    • Requirements(需求)
    • Analysis & Design(分析与设计)
    • Implementation(实现)
    • Test(测试)
    • Deployment(部署)
  • RUP 的核心价值观
    • 迭代开发(Iterative Development)
    • 风险管理(Risk Management)
    • 架构优先(Architecture-Centric)
    • 用例驱动(Use-Case Driven)
6. 敏捷方法(Agile Methods)

敏捷宣言(Agile Manifesto)四句话:

  1. 个体和交互 > 流程和工具
  2. 可工作的软件 > 详尽的文档
  3. 客户合作 > 合同谈判
  4. 响应变化 > 遵循计划
  • 右边的内容仍然有价值,但左边的优先级更高

敏捷的核心价值观:

  • 快速响应需求变化
  • 小版本迭代交付
  • 团队成员紧密协作
  • 持续改进

XP(极限编程,Extreme Programming):

  • 将好的实践做到"极致"
  • 核心实践
    • 测试驱动开发(TDD):先写测试,再写代码
    • 结对编程(Pair Programming):两人共用一台机器编码
    • 持续集成(Continuous Integration):每天多次集成代码
    • 重构(Refactoring):持续改进代码结构
    • 简单设计(Simple Design):只做最简单的能工作的设计
    • 集体代码所有权:任何人都可以修改任何代码
    • 短迭代(1-2周)

Scrum:

  • 角色
    • Product Owner:定义产品 Backlog,确定优先级
    • Scrum Master:确保 Scrum 流程执行,清除障碍
    • Development Team:自组织团队,负责开发
  • 工件(Artifacts)
    • Product Backlog:产品待办列表(所有需求的优先级清单)
    • Sprint Backlog:Sprint 待办列表(当前迭代的任务)
    • Increment:可交付的增量产品
  • 事件(Events)
    • Sprint:1-4周的开发迭代周期
    • Sprint Planning:规划本次 Sprint 要完成的任务
    • Daily Scrum(每日站会):15分钟,同步进度
    • Sprint Review:演示完成的功能
    • Sprint Retrospective:回顾改进
7. 模型对比总览
维度 瀑布 增量 螺旋 RUP 敏捷
需求明确度
风险应对 最强
用户参与度
适应变化 极差 最强
文档要求
适用规模 小-中 中-小

易错点

  1. 增量和迭代混淆:增量 = 每次加功能(搭积木),迭代 = 每次改进整体(打磨)。考试中常给出场景让你判断。
  2. 认为敏捷 = 没有文档:敏捷是"恰到好处的文档(just enough documentation)",不是零文档。
  3. RUP 阶段的顺序:Inception → Elaboration → Construction → Transition。常见陷阱是混淆 Elaboration(精化)和 Construction(构建)。
  4. Scrum 角色混淆:Product Owner 决定"做什么"和优先级,Scrum Master 确保流程正确运行,Team 决定"怎么做"。
  5. 瀑布模型仍有价值:不要以为瀑布已经过时------对安全关键系统(如航空电子、医疗设备),瀑布的严格评审流程仍然必要。
  6. 螺旋模型的核心不是迭代,是风险分析。螺旋每一轮都是从目标设定→风险分析→开发验证→下一轮规划,风险分析才是灵魂。

高频考点

  • 各种过程模型的特点和适用场景对比(必考------选择题或简答)
  • 瀑布模型的优缺点(高频选择 / 简答)
  • 敏捷宣言四句话(必考------简答或填空)
  • RUP 四大阶段的英文和中文名称及顺序(高频)
  • 增量 vs 迭代的区别(高频选择)
  • Scrum 的核心角色和职责(高频)
  • 螺旋模型的风险驱动特点
  • XP 的主要实践(尤其是 TDD、结对编程、持续集成)

Lecture 3 --- 需求工程

快速理解

"软件出问题第一原因就是需求出问题。"需求工程回答的是:我们到底要构建什么?本讲涵盖从需求获取到需求验证的全过程。

核心知识点

1. 需求工程(Requirements Engineering, RE)
  • 目标:确定系统需要提供什么功能、有什么约束
  • 需求 (Requirements) 是系统必须满足的能力或条件
  • 需求错误的修复成本随开发阶段指数级增长:需求阶段的 bug 修复成本是 1,实现阶段是 10-100,发布后可能是 1000+
2. 需求工程的四个主要活动
复制代码
需求获取 (Elicitation) 
    → 需求分析与协商 (Analysis & Negotiation) 
    → 需求规格说明 (Specification) 
    → 需求验证 (Validation)

(1)需求获取(Elicitation)

  • 目标:从涉众(Stakeholder)处获取需求信息
  • 主要技术
技术 做法 优点 缺点
访谈(Interview) 一对一问问题 深入,可追问 耗时,涉众可能说不清
观察(Ethnography / Observation) 观察用户实际工作过程 发现"说不出的需求" 耗时,用户可能因被观察而改变行为
场景分析(Scenarios) 描述用户使用系统的具体场景 具体形象,用户易理解 不一定覆盖所有异常
原型法(Prototyping) 快速构建界面原型 用户"看到"后才知道要什么 客户可能误会原型就是最终产品
头脑风暴(Brainstorming) 集体讨论创意 激发新想法 需要好的主持人
用例(Use Cases) 描述 Actor 与系统的交互 结构化、标准化 学习曲线

(2)需求分析与协商

  • 识别需求之间的冲突(如:安全 vs 易用性)
  • 优先级排序(Must have / Should have / Could have)
  • 涉众分析(Stakeholder Analysis):识别关键决策者

(3)需求规格说明(Specification)

  • 两种层次的规格说明:
层次 面向受众 形式 详细程度
用户需求(User Requirements) 客户 / 用户 自然语言 + 图表 高层、概述性
系统需求(System Requirements) 开发人员 结构化文本、模型 详细、精确
  • 好的需求应当清晰、一致、完整、可验证

(4)需求验证(Validation)------五项检查

检查项 英文 解释
有效性 Validity 这个需求是否真的反映用户需要?
一致性 Consistency 需求之间没有矛盾(如:要求"快"又要"加密"但没考虑性能影响)
完整性 Completeness 没有遗漏关键需求和边界情况
可实现性 Realism / Feasibility 在现有技术和预算下能否实现?
可验证性 Verifiability 能否通过测试或检查来确认是否满足?
  • "系统应是用户友好的" --- 违反可验证性,因为"友好"无法被客观测试
3. 功能需求(Functional Requirements)vs 非功能需求(Non-functional Requirements)

功能需求:

  • 描述系统做什么(具体行为 / 功能)
  • 例子:"系统应该允许用户搜索产品"
  • 直接来源于用例和场景

非功能需求:

  • 描述系统做得怎么样(质量属性和约束)
  • 例子:"搜索响应时间应在 500ms 内"
  • 通常对应系统的整体质量属性

非功能需求的三分类:

复制代码
非功能需求
├── 产品需求(Product Requirements)
│   ├── 性能 (Performance):响应时间、吞吐量
│   ├── 可靠性 (Reliability):MTBF、可用性百分比
│   ├── 可用性 (Usability):学习时间、操作效率
│   └── 安全性 (Security):认证、授权、加密
├── 组织需求(Organizational Requirements)
│   ├── 开发标准:使用特定语言 / 框架 / 流程
│   ├── 交付时间:必须何时完成
│   └── 开发工具和环境要求
└── 外部需求(External Requirements)
    ├── 法规合规:GDPR、HIPAA、行业标准
    ├── 互操作性:必须与哪些其他系统对接
    └── 伦理要求:隐私保护、无障碍访问

非功能需求的重要性:

  • 往往决定了系统的架构选择
  • 非功能需求的满足比功能需求的满足更难量化
  • 非功能需求之间通常是冲突的(trade-off)
4. 需求管理(Requirements Management)
  • 需求会变化------这是不可避免的
  • 需要管理需求的版本变更
  • 建立需求追踪矩阵(Requirements Traceability Matrix, RTM)
    • 每个需求 → 对应的设计 → 对应的代码 → 对应的测试
    • 当需求变化时,能快速定位影响范围

易错点

  1. 功能需求 vs 非功能需求判断:考试常给描述让你判断类型。关键技巧------功能需求回答"做什么",非功能需求回答"多快 / 多好 / 多安全 / 多可靠"。
  2. 把"非功能需求"当作"不重要的需求":事实上非功能需求往往更关键、更难满足。
  3. 误把 UI 界面设计当作需求:界面是设计方案的体现,不是原始需求。
  4. 需求验证五项检查的名称混淆:Validity(有效性)、Consistency(一致性)、Completeness(完整性)、Realism(可实现性)、Verifiability(可验证性)------五个 V / C 开头的英文词。
  5. 以为需求一次获取完毕:需求是逐步发现的(Iterative Elicitation),这是共识。
  6. "系统应是用户友好的" 是典型的不良需求------无法验证。好的需求应可量化、可测试。

高频考点

  • 功能需求 vs 非功能需求的区分(必考------选择题,给出描述判断类型)
  • 需求验证的五项检查(高频考------简答或选择)
  • 需求获取技术的名称和适用场景(高频考)
  • 非功能需求的三分类(中频------简答)
  • 需求工程的四个主要活动(步骤顺序)
  • 用户需求 vs 系统需求的区别

Lecture 4 --- 系统建模

快速理解

"不用图形描述系统,沟通就会出问题。"系统建模是用图形化的方式抽象和描述系统,帮助理解、沟通和分析。本讲介绍四种模型的用途和各自的核心图。

核心知识点

1. 系统建模的目的
  • 帮助理解系统的结构和行为
  • 便于团队成员之间沟通
  • 提供设计文档
  • 支持系统分析和验证
2. 系统建模的四大类型
模型类型 回答的问题 代表性图表 建模阶段
上下文模型 系统边界在哪?与谁交互? 上下文图 (Context Diagram) 早期需求分析
交互模型 系统内各部分如何协作? 序列图、用例图 分析 & 设计
结构模型 系统由什么组成?各部分关系? 类图、组件图、部署图 分析 & 设计
行为模型 系统如何响应事件和数据? 状态图、活动图、DFD 分析
3. 上下文模型(Context Models)
  • 上下文图 :将系统视为一个黑盒,显示系统与外部实体(Actor)的关系
  • 作用:确定系统边界------"什么在系统内,什么在系统外"
  • 特点:最高层的抽象,不展示内部细节
  • 例子:图书馆系统上下文图 → 外部有 Librarian、Member、Book Supplier 等 Actor
4. 交互模型(Interaction Models)
  • 用例图(Use Case Diagram) :展示系统功能(用例)与外部参与者(Actor)的关系
    • 重点关注:哪些人为系统做什么
    • 关联关系:Actor 和 Use Case 之间用线连接
    • 关系:<<include>>(必须包含)、<<extend>>(可选扩展)、泛化(父子用例 / 参与者)
  • 序列图(Sequence Diagram) :展示对象间按时间顺序的消息传递
    • 生命线(Lifeline)对象名:类名 的矩形框 + 虚线
    • 激活框(Activation Box):矩形条,表示对象在做什么
    • 消息类型
      • 同步消息(实心箭头 + 实线):发送方等待返回
      • 异步消息(空心箭头 + 实线):发送方不等待
      • 返回消息(虚线箭头):方法返回值
5. 结构模型(Structural Models)
  • 类图(Class Diagram) :展示系统的静态结构
    • 类 = 名称 + 属性 + 方法(操作)
    • 属性的可见性:+ public, - private, # protected
    • 关系类型(重点 ⭐):
关系 图形 说明 例子
关联 (Association) 实线 ------------ 类之间有联系 学生 ------ 课程
聚合 (Aggregation) 空心菱形 ◇------------ 整体-部分,部分可独立存在 学校 ◇------------ 老师(老师可换学校)
组合 (Composition) 实心菱形 ◆------------ 整体-部分,部分随整体消亡 页面 ◆------------ 按钮(按钮随页面销毁)
泛化 (Generalization) 空心三角 ------▷ 继承关系 猫 ------▷ 动物
实现 (Realization) 虚线空心三角 - - ▷ 接口实现 Circle - - ▷ Drawable
依赖 (Dependency) 虚线箭头 - - -> 一个类使用另一个类(临时) Printer - - -> Paper
  • 多重性(Multiplicity)
    • 1:恰好一个
    • 0..1:零或一个
    • 0..**:零或多个
    • 1..*:一或多个
6. 行为模型(Behavioral Models)
  • 数据驱动建模:DFD(Data Flow Diagram)
DFD 元素 图形 说明
进程 (Process) 圆形 / 椭圆 对数据做变换操作
数据流 (Data Flow) 箭头 数据在进程间流动
数据存储 (Data Store) 平行线 / 开口矩形 数据持久存放
外部实体 (External Entity) 矩形 系统外的数据源或目的地
  • DFD 的三个抽象级别:

    • Level 0(上下文 DFD):整个系统视为一个进程
    • Level 1(0 层 DFD):系统分解为多个主要进程
    • Level 2(1 层 DFD):对主要进程进一步分解
  • 事件驱动建模:状态机图(State Machine Diagram)

要素 说明 例子
State(状态) 对象在特定条件下的情况 "等待输入"、"已登录"
Initial State 初始状态(实心圆)
Final State 终止状态(实心圆+圈)
Transition(转移) 状态间的变化 从"待处理"→"处理中"
Event(事件) 触发转移的事件 "用户点击提交"
Action(动作) 转移时的操作 "验证输入、保存数据"
  • 状态图适合描述单个对象的生命周期行为
  • 活动图(Activity Diagram)适合描述业务流程或算法步骤
    • 要素:开始节点、动作节点、决策 / 分支(菱形)、分叉 / 汇合(粗线)、泳道(Swimlane,按角色划分责任区域)
7. 模型之间的关系
  • 不同的模型从不同角度描述同一个系统
  • 用例图 驱动后续的序列图类图
  • 状态图活动图补充行为描述
  • 上下文图定义系统边界

易错点

  1. 聚合 vs 组合 :菱形是空心的还是实心的?考试常给一个场景(如"教室和椅子"------如果椅子可以搬到别的教室就是聚合,如果椅子是教室不可分割的一部分就是组合)。记住:聚合(空心◇)的部分可独立存在;组合(实心◆)的部分随整体一起销毁。
  2. DFD 不是流程图:DFD 关注的是"数据如何流动和变换",不是"程序的控制流(先做什么后做什么)"。活动图 / 流程图才关注控制流。
  3. DFD 和活动图的混淆:两者看起来都有数据 / 控制流动,但 DFD 展示数据变换和存储,活动图展示业务流程步骤序列。
  4. 多重性方向1 --------- 0..* 要注意哪个方向。Member 1 --------- 0..* Loan 表示一个 Member 对应零或多个 Loan。
  5. 状态图只适合单个对象:状态机图描述的是"一个对象在其生命周期中的状态变化",不是业务流程。
  6. 用例图中 actor 是人还是系统?:Actor 可以是人、其他系统、硬件设备------只要与当前系统有交互。

高频考点

  • 类图中六种关系的识别和绘制(必考------给出关系类型描述,选 / 画出正确图形)
  • 聚合 vs 组合的区分(绝对高频)
  • 状态图中的要素(State、Transition、Event、Action)(高频简答)
  • DFD 的四个基本元素及图形表示(高频选择)
  • 用例图中 <> 和 <> 的区分(高频考)
  • 四种模型类型各自回答什么问题(选择 / 简答)
  • 序列图的元素(生命线、激活框、消息类型)
  • 上下文模型的作用(确定系统边界)

Lecture 5 --- 面向对象基础

快速理解

"面向对象的五个核心概念。"本讲为理解 OO 分析和设计打下基础,是后续 UML、OOA、OOD 的理论前提。

核心知识点

1. 面向对象的四大基本特征 + 类与对象

(1)抽象(Abstraction)

  • 定义:关注本质特征,忽略无关细节
  • 例子:将"一辆汽车"抽象为"交通工具",忽略颜色、型号等非本质属性
  • 软件中的应用:接口 / 抽象类 = 对外只暴露必要的操作,隐藏内部细节
  • 关键词:关注"是什么"而不是"如何实现的"

(2)封装(Encapsulation)

  • 定义:数据和操作数据的方法绑定在一起,隐藏内部实现细节,仅暴露公开接口
  • 核心思想:Information Hiding(信息隐藏)
  • 实现方式:private 属性 + public getter / setter 方法
  • 好处:
    • 降低复杂度(外部不需要知道内部实现)
    • 提高可维护性(内部修改不影响外部)
    • 提高安全性(防止外部非法修改内部状态)
  • 关键词:保护内部状态,暴露操作接口

(3)继承(Inheritance)

  • 定义:子类(Subclass)继承父类(Superclass)的属性和方法,实现代码复用
  • 关系语义:"is-a"(猫 动物,轿车车辆)
  • 子类可以:完全继承、重写(Override)、扩展新的属性和方法
  • 类继承 vs 接口继承:
    • 类继承:继承实现(代码复用)
    • 接口继承:继承类型规范(多态)
  • 虚拟方法(Virtual Method):子类可以重写的父类方法
  • 抽象类(Abstract Class):不能实例化,必须被子类继承才可使用
  • 注意:过多继承层次会使系统难以维护

(4)多态(Polymorphism)

  • 定义:同一接口可以被不同类以不同方式实现
  • 核心机制:动态绑定(Dynamic Binding)------运行时决定调用哪个方法
  • 两种形式:
    • 编译时多态(Compile-time Polymorphism) = 方法重载(Overloading):同名方法不同参数列表(在 Java / C++ 中编译期确定)
    • 运行时多态(Runtime Polymorphism) = 方法重写(Overriding):子类重写父类方法(运行期确定)
  • 多态的好处:代码灵活、可扩展性强

(5)类(Class)与对象(Object)

  • 类 = 模板 / 蓝图(定义属性和方法),不占用运行时内存
  • 对象 = 类的实例(实例化后占用内存)
  • 一个类可以有多个对象实例
2. 消息传递(Message Passing)
  • OO 系统中,对象之间通过发送消息来交互
  • 消息 = 对象名 + 方法名 + 参数
  • 例子:student1.getGrade("CS101")
3. 继承 vs 组合(Inheritance vs Composition)
  • 继承("is-a") :子类是父类的一种
    • 优点:代码复用直接
    • 缺点:破坏封装(子类依赖父类实现),继承层次过深难以维护
  • 组合("has-a") :一个类包含另一个类的对象作为成员
    • 优点:松耦合、灵活(运行时可替换)
    • 缺点:需要额外的代码委托
  • 原则:优先使用组合而非继承(Favor composition over inheritance)
4. 对象之间的关系总结
关系 语义 表示
继承 (Generalization) is-a 类继承
关联 (Association) knows-a / has-a 双向或单向引用
聚合 (Aggregation) has-a (弱) 部分可独立
组合 (Composition) has-a (强) 部分随整体
依赖 (Dependency) uses-a 方法参数 / 返回值

易错点

  1. 抽象 vs 封装混淆:抽象是"从外部观察对象时看到的本质特征"(从复杂中提取关键),封装是"把内部细节藏起来"(信息隐藏)。抽象回答"这个对象是什么?",封装回答"内部实现不让外界看到"。
  2. 多态 ≠ 方法重载(Overloading):Overloading 是"同名不同参"(编译期决定),多态更核心的是动态绑定 / 重写(运行期决定)。考试常考多态的两种形式。
  3. "is-a" vs "has-a"判断错误:给定两个类,判断是继承还是组合。如 "Student" 和 "Course" → has-a(组合 / 关联),"GraduateStudent" 和 "Student" → is-a(继承)。
  4. 抽象类 vs 接口混淆:抽象类可以有部分实现,接口只有方法签名(在 Java 8+ 之前)。但很多考试中保持传统定义。
  5. 消息传递的写法object.method(args) 不是简单的函数调用,而是"向对象发送一条消息"。

高频考点

  • 面向对象五大概念的定义和区分(必考------选择或简答)
  • 封装的好处 / 信息隐藏的作用(高频简答)
  • 继承 vs 组合的对比和选择(高频简答)
  • 多态的两种形式:Overriding 和 Overloading(高频选择)
  • 抽象类和接口

Lecture 6 --- UML 入门

快速理解

UML(统一建模语言)是 OO 分析与设计的标准建模语言。本讲详细介绍了最重要的五种 UML 图及其使用方法。

核心知识点

1. UML 概述
  • UML = Unified Modeling Language(统一建模语言)
  • 作用:为 OO 分析和设计提供标准的图形化表示方法
  • 用于:可视化、规格说明、构造和文档化系统的产出物
  • UML 2.0 包含 13 种图,本讲重点覆盖 5 种核心图
2. 用例图(Use Case Diagram)
  • 用途 :捕捉功能需求,展示系统对外提供的功能
  • 要素
    • 参与者(Actor):与系统交互的人、系统或设备(用小人图标表示)
    • 用例(Use Case):系统提供的一个完整功能(椭圆 / 矩形 + 文本表示)
    • 系统边界(System Boundary):矩形框,内部是系统,外部是 Actor
    • 关联(Association):连接 Actor 和 Use Case(实线)
  • 关系
    • <<include>>(包含):一个用例总是会执行 另一个用例。箭头从"调用方"指向"被调用方"(虚线箭头 + <<include>> 标注)。语义:A 总是包含 B,没有 B 则 A 不完整。
    • <<extend>>(扩展):一个用例在某些条件下 会执行另一个用例。箭头从"扩展用例"指向"被扩展用例"。语义:A 在特定条件下才扩展 B,B 本身是完整的。
    • 泛化(Generalization):子用例 / 子 Actor 继承父用例 / 父 Actor 的行为(空心三角箭头)。
3. 类图(Class Diagram)
  • 用途 :展示系统的静态结构(类及其之间的关系)

  • 类的表示

    ┌─────────────────────┐
    │ ClassName │ ← 类名(粗体居中)
    ├─────────────────────┤
    │ - attribute1: Type │ ← 属性(可见性 名称: 类型)
    │ + attribute2: Type │
    ├─────────────────────┤
    │ + method1(): Type │ ← 方法(可见性 名称(参数): 返回类型)
    │ - method2(p: Type) │
    └─────────────────────┘

  • 可见性+(public)、-(private)、#(protected)、~(package)

  • 六种关系(详细已在 Lecture 4 介绍,这里是核心总结):

关系 图形 弱→强
依赖 - - - -> 最弱
关联 ------------
聚合 ◇------------
组合 ◆------------
泛化 ------▷
实现 - - -▷ 最强(类型层面)
4. 序列图(Sequence Diagram)
  • 用途:按时间顺序展示对象之间的消息交互
  • 要素
    • 生命线(Lifeline)对象名:类名 的矩形 + 向下的虚线
    • 激活条(Activation Bar):对象执行操作的时间段(矩形条)
    • 消息(Message):对象间传递的通信
  • 消息类型
    • 同步消息(实心箭头):如方法调用,调用方等待返回
    • 异步消息(普通箭头):发送后不等待
    • 返回消息(虚线箭头):返回值
    • 自调用消息:对象调用自己的方法
  • 交互片段(Interaction Fragment)
    • alt:可选 / 替代片段(类似 if-else)
    • loop:循环片段
    • opt:可选片段
  • 用途 :详细描述一个用例的实现过程
5. 状态图(State Machine Diagram)
  • 用途 :描述一个对象在其生命周期中的状态变化
  • 要素
    • 初始状态 (实心圆
    • 状态(圆角矩形):对象的状态名称
    • 转移 (箭头):事件(参数) [守卫条件] / 动作
    • 自身转移:事件触发后回到同一状态
    • 最终状态 (实心圆 + 外圈
  • 例子:电梯控制系统的状态图可能包括:Idle → Moving → Idle 等
  • 适用场景:一个对象有多个不同状态,且不同状态行为不同(如 Order 状态:Pending → Paid → Shipped → Delivered → Cancelled)
6. 活动图(Activity Diagram)
  • 用途:展示业务流程或工作流中的步骤序列
  • 要素
    • 开始节点 (实心圆
    • 动作节点(圆角矩形):执行的一个步骤
    • 决策 / 分支 (菱形 ):条件判断,有多个出口
    • 分叉(Fork):粗线,将一条控制流分为多条并发流
    • 汇合(Join):粗线,将多条并发流合并为一条
    • 泳道(Swimlane):垂直区域,按角色 / 部门来组织活动
    • 最终节点 (实心圆+圈
  • 状态图 vs 活动图
    • 状态图:关注一个对象的状态变化(状态 -> 事件 -> 状态)
    • 活动图:关注流程步骤(动作 -> 动作 -> 动作)
  • 活动图更接近传统流程图,但增加了并发和角色划分的能力
7. UML 图表分类总结
类型 图表名称 动态 / 静态
结构图 (Structure) 类图、对象图、组件图、部署图、包图、组合结构图 静态
行为图 (Behavior) 用例图、活动图、状态图 动态
交互图 (Interaction) 序列图、通信图、时序图、交互概览图 动态

易错点

  1. 聚合(空心菱形) vs 组合(实心菱形)看错:最简单记忆法------"空心"意味着"部分可以独立空出来"(可分离);"实心"意味着"部分被牢牢焊在整体上"(不可分离)。
  2. <<include>><<extend>> 箭头方向混淆
    • <<include>>:A <<include>> B → A 一定会调用 B。箭头从 A 指向 B。
    • <<extend>>:A <<extend>> B → A 在特定条件下扩展 B。箭头从 A(扩展)指向 B(被扩展)。
  3. 用例图中的 Actor 必须是 "人":错!Actor 可以是其他系统、硬件设备。
  4. 序列图中的消息箭头方向错误:同步消息用实心箭头,异步消息用普通空心箭头。混淆后含义完全不同。
  5. 状态图 vs 活动图混用:描述单个对象的行为 → 状态图;描述业务流程 → 活动图。不能搞反。
  6. 假设 UML 只用于 OO 开发:UML 可以与其他开发范式配合使用,但确实最常用于 OO 开发。
  7. 泛化(继承)箭头的方向子类指向父类,箭头在父类端。人总是想画反。

高频考点

  • 类图中六种关系的图形识别(必考------选择题给图判断类型)
  • 聚合 vs 组合的区分(必考)
  • 用例图中 <> 和 <> 的语义区分(必考)
  • 序列图的要素识别(生命线、激活框、消息类型)(高频选择)
  • 给定场景选择正确的 UML 图(高频选择)
  • 状态图的元素(State、Transition、Event、Action)(高频)
  • 类图的多重性含义
  • 活动图的泳道 / 分叉 / 汇合的作用
  • 结构图 vs 行为图的分类

Lecture 7 --- 面向对象分析 (OOA) 实例

快速理解

OOA 是将用户需求转化为分析模型的过程。"分析"意味着理解问题域------识别出系统中有哪些类、它们之间如何交互。本讲通过一个完整案例(如图书馆系统)演示了 OOA 的实操流程。

核心知识点

1. OOA 的基本流程
复制代码
需求描述 → 理解问题域 → 识别候选类 → 筛选类 → 确定类间关系 → 建立用例模型 → 构建分析类图
2. 理解问题域(Understanding the Problem Domain)
  • 通过与用户 / 客户交流,理解业务逻辑
  • 识别关键的业务实体(Business Entities)
  • 确定系统的范围限制
3. 识别候选类(Identifying Candidate Classes)
  • 经典方法:名词提取法(Noun Extraction)
    • 从需求文档 / 用户描述中提取所有名词名词短语
    • 这些名词就是候选类
  • 筛选标准 (排除法则):
    • 冗余类:表达同一概念的多个名词 → 保留一个
    • 模糊类:含义不清晰 → 排除或重新定义
    • 属性冒充类:实际上是另一个类的属性 → 排除(如"书名"不是类,而是 Book 的属性)
    • 实现细节类:在分析阶段不需考虑 → 推迟到设计阶段
  • 保留标准
    • 有明确的职责和行为的实体
    • 系统需要存储和管理其信息
4. 确定类之间的关系
  • 关联A 关联 B(如:Student 关联 Course)
  • 聚合A 包含 B 的集合(弱整体-部分)
  • 组合A 由 B 构成(强整体-部分)
  • 泛化A 是 B 的一种(继承)
  • 在类图上标注多重性 (1, 0..., 1... 等)
5. 构建用例模型(Use Case Modeling)
  • 识别 Actor :谁 / 什么会与系统交互?
    • 主要 Actor:使用系统主要功能的人(如借书人)
    • 次要 Actor:管理和维护系统的人(如图书管理员)
    • 外部系统 Actor:与系统交互的其他系统(如支付系统)
  • 识别用例 :Actor 与系统的每次交互就是一个用例
    • 用例命名格式:动词 + 名词(如"借阅图书""归还图书""查询图书")
6. 构建分析类图(Analysis Class Diagram)
  • 不同于设计类图------分析类图是概念层面的
  • 不需要写方法签名和具体实现细节
  • 三种分析类(Stereotypes)
    • <<boundary>> 边界类:Actor 与系统的交互界面(如:借书界面)
    • <<control>> 控制类:协调和控制系统操作(如:借书控制器)
    • <<entity>> 实体类:存储和管理的业务数据(如:Book、Member)
7. OOA 与 OOD 的区别(考试中非常非常重要 ⭐)
维度 OOA(分析) OOD(设计)
关注 "做什么"(问题域) "怎么做"(解决方案域)
抽象层次 高层概念模型 具体实现细节
产出 分析类图、用例图 设计类图、序列图
与实现的关系 独立于实现 贴近特定实现技术
关注重点 业务逻辑、实体 架构模式、设计模式
  • 简单记忆:OOA 问"What",OOD 问"How"

易错点

  1. 把所有名词都当成类:需求中的名词不一定都是类。"书名"是 Book 的属性,"学生"既是 Actor 也可能是类。需要仔细筛选。
  2. OOA 阶段过度关注实现细节:分析阶段只做"概念建模",不要考虑用什么数据库、什么框架、怎么存储数据。
  3. OOA 和 OOD 混淆 :有时在分析和设计之间来回跳。分析没有完成之前不要进入设计。记住:分析 = 理解问题,设计 = 解决问题。
  4. 边界类、控制类、实体类放错位置:例如把"数据库连接"当成实体类------数据库是设计问题,不是分析问题。
  5. 用例建模时遗漏 Actor:除了直接用户,还要考虑管理员、外部系统等。

高频考点

  • OOA 的基本步骤和核心目标(高频简答)
  • OOA 与 OOD 的区别(必考------简答或选择)
  • 候选类识别的名词提取法和筛选标准(高频简答 / 应用题)
  • 三种分析类(边界、控制、实体)的职责(中频选择)
  • 用例建模的步骤
  • 分析类图 vs 设计类图的区别

Lecture 8 --- 架构设计

快速理解

"建房子要先搭骨架还是直接砌砖?"架构设计就是软件系统的"骨架"设计。本讲介绍主流的架构模式和设计决策。

核心知识点

1. 架构设计(Architectural Design)的重要性
  • 架构 :软件系统的整体组织结构和组件之间的关系
  • 为什么重要
    • 影响系统的非功能属性(性能、安全性、可靠性、可维护性等)
    • 涉众沟通的桥梁(不同角色从架构中看到不同的内容)
    • 促进复用(架构级别的模式复用)
    • 早期架构决策一旦做出,后期很难改变
2. 架构设计的主要决策
  1. 系统的整体风格架构模式是什么?
  2. 系统如何分解为组件
  3. 组件之间如何通信
  4. 系统的数据组织方式是什么?
  5. 如何满足关键的非功能需求
3. 六大通用架构模式

(1)MVC(Model-View-Controller)

组件 职责
Model(模型) 数据和业务逻辑
View(视图) 数据展示 / 用户界面
Controller(控制器) 处理用户输入、协调 Model 和 View
  • 核心优点:关注点分离(Separation of Concerns)
  • 缺点:对于简单应用来说可能过度设计
  • 典型应用:Web 框架(Spring MVC、Ruby on Rails)、GUI 应用

(2)分层架构(Layered Architecture)

  • 每一层只调用下一层的接口
  • 典型层次:UI 层 → 业务逻辑层 → 数据访问层 → 数据库层
  • 封闭架构(Closed Architecture):每层只能调用直接下层(最常见)
  • 开放架构(Open Architecture):层可以跳过下层调用更底层(性能更好但耦合增加)
  • 优点:逐步抽象、可替换性(换数据库只需改数据访问层)
  • 缺点:每层增加开销,层数难确定

(3)客户端-服务器(Client-Server)

  • Client:请求服务(发起通信)
  • Server:提供服务(等待请求)
  • 变体:多层架构(Thin Client + Application Server + Database Server)
  • 优点:集中管理、易于扩展
  • 缺点:服务器成为潜在瓶颈和单点故障

(4)管道-过滤器(Pipe-and-Filter)

  • Filter(过滤器):对数据进行处理 / 变换的单元
  • Pipe(管道):连接过滤器的数据通道
  • 例子 :Unix 管道命令 cat file | grep pattern | sort
  • 优点
    • 松耦合(过滤器独立运行)
    • 可组合、可复用
    • 支持并发
  • 缺点:不适合交互式应用,不适合需要全局状态的处理

(5)仓库模式 / 中央数据(Repository / Shared Data)

  • 所有组件共享一个中央数据结构
  • 组件独立运行、通过中央数据通信
  • 例子:IDE(编辑器、编译器、调试器共享 AST 仓库)、AI / 编译器中的黑板系统(Blackboard)
  • 优点:数据一致性好
  • 缺点:中央仓库成为性能瓶颈和单点故障

(6)事件驱动(Event-driven Architecture)

  • 组件通过事件发布 / 订阅(Publish-Subscribe) 通信
  • 组件不直接调用对方------通过事件总线(Event Bus)解耦
  • 优点:极度松耦合和灵活
  • 缺点:调试困难、全局顺序难以保证、复杂度高
4. 架构模式对比
模式 组件通信方式 适用场景 性能特点
MVC Controller ↔ Model ↔ View Web 应用、GUI 可接受
分层 相邻层间单向调用 企业应用 层数越深越慢
Client-Server 请求-响应 / 网络 Web 系统 受限于网络
Pipe-and-Filter 数据流驱动 数据处理、编译器 可并行化
Repository 共享数据 数据密集型应用 数据访问瓶颈
Event-driven 事件发布 / 订阅 GUI、实时系统 异步、高吞吐
5. 架构设计文档
  • 架构视图(Architectural Views) :从不同角度描述架构
    • Kruchten 4 + 1 视图模型:
      • 逻辑视图(Logical View):功能需求
      • 进程视图(Process View):并发和性能
      • 开发视图(Development View):模块组织
      • 物理视图(Physical View):部署
      • 场景(Scenarios / Use Cases):将四个视图串联

易错点

  1. MVC ≠ 三层架构:MVC 是表现层的设计模式,三层架构是宏观的分层(表现层 → 业务逻辑层 → 数据访问层)。一个系统可以有三层架构,其中的表现层内部用 MVC。
  2. 认为一种架构模式走天下:实际项目中往往是多种模式的组合。比如:整体用分层,分层中的某一层内部用 MVC,组件间通信用事件驱动。
  3. 架构设计 ≠ 详细设计:架构是"骨架"(宏观),详细设计是"血肉"(微观)。考试常考区别。
  4. 管道-过滤器适合交互式应用:错,它适合批处理 / 数据流应用,不适合需要频繁用户交互的场景。
  5. 事件驱动架构的调试困难常被忽略。

高频考点

  • 六大架构模式的名称、特点和适用场景(必考------选择 / 简答 / 应用题选择模式)
  • MVC 三层各自的职责(必考选择或简答)
  • 分层架构的优缺点(高频简答)
  • 给定系统场景,选择最合适的架构模式(必考------综合应用)
  • 架构设计的主要决策(4个问题)
  • 管道-过滤器的适用场景(编译器、数据处理)

Lecture 9 --- 面向对象设计 (OOD)

快速理解

OOA 回答"系统要做什么",OOD 回答"系统怎么用代码实现"。本讲介绍 OOD 的核心活动、设计模式和责任分配原则。

核心知识点

1. OOA → OOD 的过渡
复制代码
OOA产出:分析类图、用例图 (概念层,关注"做什么")
          ↓
OOD输入:分析模型 + 非功能需求 + 技术约束
          ↓
OOD产出:设计类图(含方法签名)、序列图、接口定义 (实现层,关注"怎么做")
2. OOD 的主要活动
  1. 类设计:为每个类分配职责,设计属性和方法
  2. 协作设计:设计类之间的交互方式(用序列图建模)
  3. 设计模式应用:用成熟的设计方案解决常见的设计问题
  4. 接口设计:定义系统的对外接口
  5. 组件打包:将类组织为包 / 模块
  6. 非功能需求处理:满足性能、安全性等要求
3. 设计模式(Design Patterns)总览

设计模式 = 针对常见设计问题的可复用解决方案

(1)创建型模式(Creational)------ 处理对象创建的机制

模式 目的 例子
Singleton 确保类只有一个实例 日志管理器、配置管理器
Factory Method 在父类中定义创建对象的接口,子类决定实例化哪个类 数据库连接工厂
Abstract Factory 创建相关或依赖对象的家族,而不指定具体类 UI 组件工厂
Builder 分步骤构建复杂对象 构建复杂文档
Prototype 通过复制已有对象创建新对象 克隆图形对象

(2)结构型模式(Structural)------ 处理类 / 对象的组合

模式 目的 例子
Adapter 将一个接口转换成客户希望的另一个接口 电源适配器、新旧系统对接
Bridge 将抽象部分与实现部分分离,使它们可以独立变化 跨平台图形渲染
Composite 以树形结构表示"整体-部分"关系,使客户端统一对待单个对象和组合对象 文件系统(文件 / 目录)
Decorator 动态地给对象添加额外的职责 Java I/O Stream
Facade 为子系统提供统一的高层接口,简化使用 库的简单 API
Proxy 为另一个对象提供替身或占位符以控制对其的访问 延迟加载、访问控制

(3)行为型模式(Behavioral)------ 处理对象间的通信和责任分配

模式 目的 例子
Observer 定义一对多的依赖,当一个对象状态改变时所有依赖者自动收到通知 事件监听、推送通知
Strategy 定义一系列算法,封装每个算法,并使它们可以互换 排序策略、支付方式
Command 将请求封装为对象,支持参数化、排队和撤销 撤销 / 重做
State 允许对象在其内部状态改变时改变其行为 电梯状态
Template Method 在父类中定义算法骨架,将一些步骤延迟到子类实现 框架中的钩子方法
Iterator 提供顺序访问聚合对象元素的方法而不暴露内部表示 遍历集合
4. GRASP 原则(General Responsibility Assignment Software Patterns)

GRASP 是 责任分配(谁该做什么) 的指导原则:

原则 解释 例子
Information Expert 谁拥有完成职责所需的信息,谁负责完成 订单类负责计算总价(它拥有商品信息)
Creator 谁负责创建对象?通常由包含或紧密使用该对象的类创建 Member 创建 Loan 实例
Controller 谁处理系统事件?通常用一个控制类处理外部输入 控制器接收 GUI 请求并委派给 Model
Low Coupling(低耦合) 尽量减少类之间的依赖 通过接口而非具体类引用
High Cohesion(高内聚) 类内部的职责应高度相关 不要将"打印报表"和"管理用户"放在同一个类
Polymorphism(多态) 用多态替代条件判断(if-else / switch) 用接口+不同实现替代类型判断
Pure Fabrication 当 Expert 不适用时,创建一个新的类来承担职责 Controller 类、Service 类
Indirection 通过中间对象来解耦两个组件 适配器模式
Protected Variations 在不稳定点周围设置保护接口 接口隔离、抽象封装变化

易错点

  1. OOA 和 OOD 混为一谈:再次强调------OOA 是"分析问题",OOD 是"设计方案"。考试最爱考这俩的区别。
  2. 设计模式用错场景:例如,需要在运行时切换算法 → Strategy;需要对象状态变化时通知其他对象 → Observer;需要确保只有一个实例 → Singleton。需要根据场景匹配模式。
  3. GRASP 的 Information Expert 和 Controller 混淆:Expert 关注"谁能做",Controller 关注"谁接收外部事件"。
  4. Low Coupling 和 High Cohesion 的区别
    • Low Coupling = 类之间的依赖少(松散)
    • High Cohesion = 类内部职责集中(专注)
  5. 设计模式过度使用:不是任何问题都需要设计模式。保持简单。

高频考点

  • OOA 与 OOD 的区别(必考------简答或选择)
  • 设计模式的三大分类及每类的典型模式(高频简答)
  • 给定场景选择合适的设计模式(高频应用)
  • GRASP 原则的名称和含义(特别是 Information Expert、Low Coupling、High Cohesion)(必考)
  • 低耦合和高内聚的概念(必考)

Lecture 10 --- 面向对象设计实例

快速理解

通过一个完整案例(如 ATM / POS / 图书馆系统)从头到尾走一遍 OOD 流程,把 Lecture 9 的理论付诸实践。

核心知识点

1. OOD 实例的完整流程(从需求到设计)
复制代码
需求描述 → 用例分析(用例图) → 识别领域类(领域模型) → 
序列图(用例实现) → 提取方法签名(设计类图) → 设计优化(应用设计模式)
2. 第一步:从需求到用例
  • 阅读需求描述,标注ActorUse Case
  • 画出用例图,显示 Actor 与 Use Case 的关系
  • <<include>><<extend>> 关系捕捉用例间的依赖
3. 第二步:构建领域模型(Domain Model)
  • 识别业务实体类(Entity Classes)
  • 识别边界类(Boundary Classes,如 UI 界面)
  • 识别控制类(Control Classes,协调工作流)
  • 建立类之间的初步关系(关联、聚合、泛化)
4. 第三步:构建序列图(Sequence Diagrams)
  • 每个主要用例 → 至少一张序列图
  • 画出对象生命周期、消息交互顺序
  • 识别对象间传递的消息 → 这些消息将成为目标类的方法
  • 序列图驱动类设计------从序列图中"提取"类的方法签名
5. 第四步:设计类图(Design Class Diagram)
  • 从序列图中提取方法,赋予具体的类
  • 添加可见性修饰符(public / private / protected)
  • 确定参数和返回类型
  • 标注多重性和关系方向
  • 应用设计模式重构
6. 第五步:设计优化
  • 应用GRASP来评估责任分配是否合理
  • 应用设计模式来解决常见问题
  • 考虑非功能需求(性能约束可能影响设计决策)
7. 实例中的关键教训
  • OO 设计是一个迭代过程:先有一个初步设计,然后逐步细化优化
  • 分析和设计的分界线是模糊的:在实践中来回穿梭,但考试中要清楚区分
  • 好的设计 = 低耦合 + 高内聚 + 合适的模式

易错点

  1. 序列图中缺少返回消息:序列图中不仅要画调用消息,也要画返回消息。很多初学者的序列图中只有调用没有返回。
  2. 把领域模型当作数据库设计:领域模型是概念层次的,不需要考虑外键、主键、索引等数据库细节。
  3. 设计时过早优化:先让设计正确(功能正确),再考虑性能优化。
  4. 一个序列图试图展示所有情况:每个序列图对应一个具体场景,而不是"所有可能的场景"。
  5. 忽略 Actor → 生命线的映射:每个 Actor 在序列图中会变成一条生命线。

高频考点

  • 根据需求描述画序列图(必考------综合应用题)
  • 从用例中识别出设计类(高频应用)
  • 解释设计决策的合理性(如为什么用某个设计模式、为什么某个类承担某个职责)(高频简答)
  • 序列图中方法的提取 → 类图方法的添加
  • 类图的关系标注

Lecture 11 --- 面向对象详细设计

快速理解

在架构和 OOD 完成之后,深入到方法和属性级别的设计决策。SOLID 原则是本讲的核心。

核心知识点

1. SOLID 原则(五条面向对象设计核心原则)

S --- 单一职责原则(Single Responsibility Principle, SRP)

  • 定义:一个类只能有一个改变的理由,即一个类只承担一种职责
  • 违反 SRP 的表现:"上帝类(God Class)"------一个类什么都能干
  • 例子:不应把"报表生成"和"用户管理"放在同一个类中
  • 好处:类更容易理解、测试、维护

O --- 开闭原则(Open / Closed Principle, OCP)

  • 定义:对扩展开放(Open for Extension),对修改封闭(Closed for Modification)
  • 核心思想:新增功能时,应当通过添加新代码 (扩展)而不是修改已有代码(修改)来实现
  • 实现方式:抽象(接口、抽象类)+ 多态
  • 例子:Shape 接口 + Circle / Rectangle / Triangle 实现类。新增 Star 类不需要修改已有代码
  • 好处:降低新功能引入 bug 的风险

L --- 里氏替换原则(Liskov Substitution Principle, LSP)

  • 定义:子类对象应该能够替换父类对象,且不改变程序的正确性

  • 违反 LSP 的经典例子:Square 继承 Rectangle

    java 复制代码
    class Rectangle {
        void setWidth(int w) { this.width = w; }
        void setHeight(int h) { this.height = h; }
    }
    class Square extends Rectangle {
        @Override
        void setWidth(int w) {
            super.setWidth(w);
            super.setHeight(w);  // 保证宽高相等
        }
    }

    问题:调用 rect.setWidth(5); rect.setHeight(3); 时,如果是 Square 实例,高度变成了5,违反了用户预期。

  • LSP 的核心:子类不能违反父类定义的契约(方法的前置条件、后置条件、不变式)

  • 检测方法:"is-a" 测试------如果 B 替换 A 后系统出问题,就不满足 LSP

I --- 接口隔离原则(Interface Segregation Principle, ISP)

  • 定义:不应该强迫客户依赖它们不使用的方法

  • 核心思想:接口要小而专注(Role Interface / Pluggable Interface)

  • 违反 ISP:"胖接口(Fat Interface)"------一个接口包含太多不相关的方法

  • 例子:

    java 复制代码
    // 违反 ISP
    interface Worker {
        void work();
        void eat();
        void sleep();
    }
    // 符合 ISP
    interface Workable { void work(); }
    interface Eatable { void eat(); }
    interface Sleepable { void sleep(); }
    // Robot 只需实现 Workable,无需实现 eat() 和 sleep()
  • ISP vs SRP:SRP 关注 的职责单一,ISP 关注接口的粒度小

D --- 依赖反转原则(Dependency Inversion Principle, DIP)

  • 定义:高层模块不应依赖低层模块,两者都应依赖于抽象。抽象不应依赖细节,细节应依赖抽象。

  • 核心思想:面向接口编程(Program to an Interface, not an Implementation)

  • 违反 DIP 的例子:高层类 OrderService 直接依赖低层类 MySQLDatabase

  • 符合 DIP 的例子:

    复制代码
    OrderService → Database Interface ← MySQLDatabase / PostgreSQLDatabase
  • 依赖反转(DIP)≠ 依赖注入(DI)

    • DIP 是设计原则("要依赖抽象")
    • DI 是实现技术(构造器注入、setter 注入、接口注入)
    • DI 是实现 DIP 的一种方式
2. 设计契约(Design by Contract, DbC)
  • 提出者:Bertrand Meyer(Eiffel 语言)
  • 三要素:
元素 时机 解释 例子
前置条件(Precondition) 方法调用前 调用方必须满足的条件 num >= 0(计算平方根)
后置条件(Postcondition) 方法调用后 方法执行后保证的条件 返回值的平方等于输入
不变式(Invariant) 始终成立 对象在其整个生命周期中始终保持的条件 余额 = 收入 - 支出
  • 好处:明确契约、简化调试、文档化
3. 接口设计(Interface Design)
  • 接口 = 一组操作的集合签名
  • 设计原则:
    • 接口应当小而专注(ISP)
    • 接口方法应当清晰、明确、无歧义
    • 每个方法说明:前置条件、后置条件、参数类型、返回类型
    • 避免"标记参数"(如 boolean flag 改变行为)
4. 详细设计的产出物
  • 详细类图:含所有属性类型、方法签名、关系细节
  • 序列图:含具体方法的调用过程和参数传递
  • 状态图:对状态复杂的类(如 Order、Document)
  • 接口规格说明:每个接口的详细定义

易错点

  1. SOLID 原则之间的混淆
    • SRP(类只做一件事) vs ISP(接口不要太宽泛)------ SRP 是类层面的,ISP 是接口层面的
    • OCP(对扩展开放) vs DIP(依赖抽象)------ OCP 是目标(不改已有代码),DIP 是手段(依赖抽象)
  2. 里氏替换原则(LSP)只与继承相关:考试中给"正方形继承长方形"的经典反例让你分析为什么违反 LSP。
  3. DIP 与 DI 混淆:DIP 是原则(依赖抽象),DI 是实现(把依赖注入进来)。
  4. 设计契约三要素的顺序:前置条件(调用前必须满足)→ 方法执行 → 后置条件(执行后保证),不变式始终成立。
  5. 开闭原则不是"完全不修改":系统核心的抽象需要维护和扩展(这就是"开放"的部分),但稳定部分的实现代码不因功能扩展而修改。

高频考点

  • SOLID 五个原则的英文缩写、全称和解释(必考------简答 / 选择)
  • 里氏替换原则的经典反例(正方形 / 长方形问题)(必考)
  • 开闭原则的解释和实现方式(高频简答)
  • 依赖反转与依赖注入的区别(高频选择)
  • 设计契约三要素(前置条件、后置条件、不变式)(高频)
  • SRP vs ISP 的区别

Lecture 12 --- 结构化设计

快速理解

在面向对象之前,结构化设计是主流的软件设计方法。它以 功能(Function)数据流(Data Flow) 为中心。本讲的核心是:DFD → 结构图,以及耦合 / 内聚评估。

核心知识点

1. 结构化设计 vs 面向对象设计
维度 结构化设计 面向对象设计
核心 功能 / 过程驱动 对象 / 数据驱动
基本单位 模块(Module)、函数 类(Class)、对象
主要工具 DFD、结构图 (Structure Chart) UML 类图、序列图
设计过程 功能分解(顶层→底层) 职责分配 + 协作
数据与操作 分离(数据仓库 + 功能模块) 封装(数据和操作在一起)
评估标准 耦合度 + 内聚度 耦合度 + 内聚度(同样重要)
2. 结构化设计的主要流程
复制代码
需求 / 规格 → DFD(数据流建模) → 变换 / 事务分析 → 结构图 → 模块设计 → 耦合/内聚评估
3. 数据流图(Data Flow Diagram, DFD)

四个核心元素:

元素 图形 说明 例子
进程 (Process / Bubble) 圆形 / 椭圆 对数据进行变换 / 处理 "计算工资"、"验证订单"
数据流 (Data Flow) 箭头 数据在进程间流动,标注数据名称 "会员信息"、"订单数据"
数据存储 (Data Store) 两条平行线 / 开口矩形 存储数据的仓库 "会员数据库"、"库存文件"
外部实体 (External Entity) 矩形 系统的数据源或数据目标 "顾客"、"银行系统"

DFD 的分层抽象

  • 上下文图(Level 0):系统作为一个整体,显示与外部实体的数据流
  • Level 1:将系统分解为 3-7 个主要进程
  • Level 2:对 Level 1 中的每个进程进一步分解

DFD 规则

  • 进程必须有输入流和输出流(不能只有输入或只有输出)
  • 数据流不能直接从外部实体到外部实体
  • 数据流有方向(标注名称)
  • 系统内部进程必须命名
4. 变换分析(Transform Analysis)
  • 适用场景 :DFD 中有一个明显的变换中心(中心转换 / 核心处理逻辑)

  • 识别方法

    • 追踪输入数据流,找到"传入流"到达"变换中心"的边界
    • 追踪输出数据流,找到"变换中心"产生"传出流"的边界
    • 中间的进程就是变换中心
  • 映射为结构图

    复制代码
    结构图层次:
    ┌──────────────┐
    │   主控模块    │ ← 顶层
    ├──────┬───────┤
    │ 传入 │ 变换 │ 传出 │ ← 中层
    │ 控制 │ 控制 │ 控制 │
    ├──┬───┼──┬───┼──┬──┤
    │  │   │  │   │  │  │ ← 底层具体功能模块
  • 步骤

    1. 在 DFD 中识别传入流、变换中心、传出流
    2. 设计顶层主控模块
    3. 将传入流映射为传入分支(输入处理模块)
    4. 将变换中心映射为变换分支(核心处理模块)
    5. 将传出流映射为传出分支(输出处理模块)
    6. 逐层分解,直到每个模块只执行一个功能
5. 事务分析(Transaction Analysis)
  • 适用场景 :DFD 中有一个事务中心,根据输入类型分派到不同的处理路径

  • 识别方法:寻找"根据输入类型选择不同处理路径"的模式

  • 映射为结构图

    复制代码
    ┌────────────────────┐
    │      总控模块       │
    ├────────────────────┤
    │   事务分派器        │
    ├──┬──┬──┬──┬──┬──┤
    │A │B │C │D │E │F │ ← 各事务处理模块
    │型 │型 │型 │型 │型 │型│
    │处 │处 │处 │处 │处 │处│
    │理 │理 │理 │理 │理 │理│
  • 步骤

    1. 识别事务中心和数据输入路径
    2. 设计总控模块和事务分派器
    3. 将每个事务类型映射为一个处理分支
    4. 为每个分支设计详细模块
6. 结构图(Structure Chart)
  • 用途:展示模块间的层次结构、调用关系和数据传递
  • 基本元素
    • 模块(Module):矩形框,标注模块名
    • 调用关系:箭头连接(从调用模块指向被调用模块)
    • 数据耦合:带空心圆的小箭头(表示数据传递)
    • 控制耦合:带实心圆的小箭头(表示控制标志传递)
7. 耦合度(Coupling)------从低到高,好的到差的
耦合类型 英文 说明 好坏 例子
数据耦合 Data Coupling 模块之间只传递简单数据 ✅ 最好 calcTax(amount)
印记耦合 Stamp Coupling 传递结构体 / 记录,但只用其中一部分 ⚠️ 一般 calcPrice(Order order) 但只用了 order.date
控制耦合 Control Coupling 一个模块传递控制标志影响另一个模块的逻辑 ⚠️ 差 process(type, data) 其中 type 控制内部 if-else
公共耦合 Common Coupling 多个模块共享同一全局数据 ❌ 很差 使用全局变量 config
内容耦合 Content Coupling 一个模块直接访问另一个模块的内部 ❌ 极差 直接访问另一个模块的私有数据
8. 内聚度(Cohesion)------从高到低,好的到差的
内聚类型 英文 说明 好坏
功能内聚 Functional Cohesion 模块所有元素为完成单一功能 ✅ 最好
顺序内聚 Sequential Cohesion 模块的输出是下一个元素的输入 ✅ 好
通信内聚 Communication Cohesion 模块内元素操作同一数据 ⚠️ 可接受
过程内聚 Procedural Cohesion 模块内元素按特定执行顺序组合 ⚠️ 可接受
时间内聚 Temporal Cohesion 模块内元素仅在同一时间执行(如初始化) ❌ 差
逻辑内聚 Logical Cohesion 功能相关但逻辑不同(如一个函数同时处理多种打印) ❌ 差
偶然内聚 Coincidental Cohesion 元素之间无任何有意义的关系 ❌ 极差

好设计的目标高内聚 + 低耦合(High Cohesion, Low Coupling)

易错点

  1. DFD 不是流程图 / 活动图:DFD 展示"数据如何流动和转换",不是"控制流"(先做什么后做什么)。
  2. 变换分析 vs 事务分析混淆:变换分析 = 数据处理(输入→处理→输出),事务分析 = 分派(根据类型选择不同路径)。
  3. 耦合度排序从好到差:数据 < 印记 < 控制 < 公共 < 内容。考试中常给场景让你判断类型。
  4. 内聚度排序从好到差:功能 > 顺序 > 通信 > 过程 > 时间 > 逻辑 > 偶然。
  5. 结构图没有表达执行顺序 :结构图展示调用层次关系,不是时间序列。
  6. DFD 中进程必须同时有输入和输出:没有输入的进程不能存在(不可能凭空产生数据),没有输出的进程也是无效的。

高频考点

  • 耦合度的五种类型(从好到差排序)(必考------选择 / 简答)
  • 内聚度的七种类型(从好到差排序)(必考------选择 / 简答)
  • 变换分析和事务分析的区别(高频简答)
  • DFD 的四个基本元素和图形(高频选择)
  • 结构化设计 vs 面向对象设计对比(高频简答)
  • 结构图的模块表示和调用关系
  • DFD 的分层抽象(上下文图 → Level 1 → Level 2)

Lecture 13 --- 软件测试(一)

快速理解

测试是保证软件质量的核心手段。本讲介绍测试的基础理论和黑盒测试方法。

核心知识点

1. 测试的基本概念
  • 测试 ≠ 调试
    • 测试:发现缺陷(找到 bug)
    • 调试:定位和修复缺陷(修 bug)
  • 测试的目标:以最小成本发现尽可能多的重要缺陷
  • 测试无法穷尽:不可能测试所有可能的输入组合 → 必须使用有效策略(等价类划分、边界值分析等)
2. 验证(Verification)vs 确认(Validation)
概念 回答的问题 解释 关注
Verification(验证) "Are we building the product right?" 产品是否按规格正确构建? 过程正确性
Validation(确认) "Are we building the right product?" 是否构建了客户真正需要的产品? 需求满足度
  • 记忆技巧:Verification = "Verify the spec"(验证规格),Validation = "Validate the user needs"(确认用户需求)
  • V&V 贯穿软件生命周期
3. V-Model(V 模型)
复制代码
需求分析 →               ← 验收测试
  设计 →               ← 系统测试
    详细设计 →         ← 集成测试
      编码 → 单元测试
  • V 模型的本质:每个开发阶段都有对应的测试阶段
  • 左半边是"开发向下",右半边是"测试向上"
4. 测试层级(Testing Levels)

(1)单元测试(Unit Testing)

  • 测试对象:单个函数、方法、类
  • 执行者:开发者(最常做的测试)
  • 目标:验证代码逻辑的正确性
  • 方法:白盒测试为主
  • 工具:JUnit, pytest, Jest 等

(2)集成测试(Integration Testing)

  • 测试对象:组件之间的接口和交互
  • 执行者:开发者 + 测试团队
  • 目标:验证组件能否正确协作
  • 关注点:接口参数传递是否正确、数据是否一致、错误处理是否顺畅

(3)系统测试(System Testing)

  • 测试对象:整个完整系统
  • 执行者:独立测试团队(没有偏见,更客观)
  • 目标:验证整个系统是否满足功能需求和非功能需求
  • 测试类型:功能测试、性能测试、安全性测试、可用性测试

(4)验收测试(Acceptance Testing)

  • 测试对象:客户场景下的系统
  • 执行者:客户 / 最终用户
  • 目标:确定系统是否满足客户需求、是否可接受
  • 类型:
    • Alpha 测试:在开发环境下由用户代表执行
    • Beta 测试:在真实用户环境中执行
5. 黑盒测试(Black-box Testing)

定义 :不查看内部代码结构,仅基于需求规格设计测试用例

(1)等价类划分(Equivalence Partitioning)

  • 原理:将输入数据划分为若干等价类,同一个类中所有值的测试效果等价
  • 每个等价类只测一个代表值
等价类类型 定义 例子(年龄输入 0-150)
有效等价类 合法输入 0 ≤ age ≤ 150 的整数
无效等价类 非法输入 age < 0, age > 150, 非整数
  • 步骤
    1. 分析输入条件
    2. 划分有效等价类和无效等价类
    3. 从每个类中选择一个代表值作为测试输入
  • 关键不要忽略无效等价类------系统对非法输入也要正确处理

(2)边界值分析(Boundary Value Analysis, BVA)

  • 原理:大量 bug 发生在输入的边界附近而不是中间值
  • 方法:测试边界值及其两侧的值
  • 例子:年龄 0-150 → 测试 -1, 0, 1, 149, 150, 151
  • 一般边界值:最小值、最小值-1、最小值+1、最大值、最大值-1、最大值+1
  • 边界值分析 vs 等价类划分 :等价类划分取代表值,边界值分析取边界及附近的特殊值。两者通常配合使用
6. 测试用例设计原则
  • 好的测试用例是可复现的(相同输入 → 相同输出)
  • 每个测试用例独立(不依赖其他测试的结果)
  • 每个测试用例应当发现一类错误而不是全部错误
  • 测试用例 = 输入 + 前置条件 + 预期输出

易错点

  1. Verification vs Validation 考英文选择题 :最经典的考法。记住------Verification = 验证实现正确 (building product right),Validation = 验证需求正确(building right product)。
  2. 等价类划分时遗漏无效等价类:很多考生只划分了有效等价类,忘记了无效等价类(如负数、非数字等非法输入)。
  3. 边界值分析是否包含边界本身 :标准的 BVA 包含边界值。如 0-150,测试 -1, 0, 1, 149, 150, 151。
  4. 测试四个层级的具体测试内容搞混:单元测试(最小单元)→ 集成测试(接口)→ 系统测试(全系统)→ 验收测试(用户验收)。
  5. 系统测试和验收测试的执行者搞反:系统测试由独立测试团队做,验收测试由客户 / 用户做。

高频考点

  • Verification vs Validation 的区分(必考------给英文定义选择题或简答)
  • 测试的四个层级及其定义(高频选择)
  • 等价类划分的应用(必考------综合应用题,给场景划分类并设计测试)
  • 边界值分析的原理和应用(必考------综合应用题)
  • 黑盒测试的定义和特点(高频简答)
  • 测试用例的基本构成(输入+前置条件+预期输出)

Lecture 14 --- 软件测试(二)

快速理解

测试(二)延续测试(一),重点讲白盒测试(覆盖度分析、圈复杂度)和集成测试策略。这部分偏向技术实现层面。

核心知识点

1. 白盒测试(White-box Testing)
  • 定义:基于代码的内部结构和逻辑设计测试用例
  • 也称为:结构测试(Structural Testing)、Glass-box Testing
  • 适用场景:单元测试阶段
  • 目标:覆盖代码的不同执行路径
2. 代码覆盖度(Code Coverage)------四种主要标准

(1)语句覆盖(Statement Coverage)

  • 要求:每个语句至少执行一次
  • 最弱的覆盖标准,但是基础要求
  • 局限性:即使语句都执行了,分支条件可能没覆盖到

(2)分支覆盖(Branch Coverage)

  • 要求:每个判断的真假分支至少各执行一次
  • 也称为:决断覆盖(Decision Coverage)
  • 比语句覆盖强(但可能漏掉某些条件组合)

(3)条件覆盖(Condition Coverage)

  • 要求:每个布尔子条件的 true 和 false 至少各取一次
  • 例子:if (A || B) → 需要 A=true, A=false, B=true, B=false 各至少一次
  • 注意:条件覆盖不一定覆盖所有分支(条件覆盖的分支覆盖)

(4)路径覆盖(Path Coverage)

  • 要求:所有可能的执行路径至少执行一次
  • 最强的覆盖标准
  • 局限性:路径数量可能指数级增长("路径爆炸"),实际中不可能完全覆盖

覆盖度强弱关系

复制代码
路径覆盖 ⊃ 分支覆盖 ⊃ 语句覆盖
条件覆盖 ⊃ 语句覆盖(但条件覆盖不保证分支覆盖)
3. 圈复杂度(Cyclomatic Complexity)
  • 定义 :衡量程序模块的复杂程度

  • 三种等效计算方法

    1. CC = E - N + 2P
      • E = 流程图中边的数量
      • N = 节点的数量
      • P = 连通分量数(通常 = 1)
    2. CC = 判定节点数 + 1
      • 判定节点:if, while, for, case 等分支点
      • 最简单的计算方法
    3. CC = 封闭区域数 + 1
      • 在流程图中数封闭区域的个数
  • 用途

    • 指导需要多少测试用例(CC = 最少需要的路劲数)
    • 判断模块是否需要重构(一般认为 CC > 10 时复杂度过高)
  • 例子

    java 复制代码
    void method(boolean a, boolean b) {
        if (a && b) {   // 判定节点 1
            // 路径 1
        } else {
            // 路径 2
        }
        if (a || b) {   // 判定节点 2
            // 路径 3
        } else {
            // 路径 4
        }
    }
    • 判定节点数 = 2(两个if)
    • CC = 2 + 1 = 3
    • 最少需要 3 个测试用例才能覆盖所有分支
4. 集成测试策略

(1)大爆炸集成(Big Bang Integration)

  • 做法:所有组件开发完成后一次性集成测试
  • 优点:简单,没有额外开销
  • 缺点:错误定位极其困难(不知道是哪个组件的问题)
  • 适用:小项目

(2)自顶向下集成(Top-down Integration)

  • 做法:从顶层主控模块开始,按控制层次逐步向下集成
  • 需要的辅助性模块:Stub(桩) ------模拟未实现的下层模块
  • 优点:
    • 最早验证系统架构和顶层逻辑
    • 早期可看到系统原型
  • 缺点:
    • 底层关键功能测试滞后
    • 需要大量 Stub 的开发

(3)自底向上集成(Bottom-up Integration)

  • 做法:从底层模块开始,按调用层次逐步向上集成
  • 需要的辅助性模块:Driver(驱动) ------模拟上层调用模块
  • 优点:
    • 底层功能测试充分
    • 不需要 Stub
  • 缺点:
    • 很晚才能验证系统整体架构
    • 需要开发 Driver

(4)三明治 / 混合集成(Sandwich / Hybrid Integration)

  • 做法:同时从顶层和底层向中间进行集成
  • 本质:Top-down + Bottom-up 组合
  • 优点:较快验证系统功能
  • 缺点:较复杂

(5)持续集成(Continuous Integration, CI)

  • 做法:每次代码变更后立即进行自动化构建和集成测试
  • 是敏捷开发的核心实践之一
  • 要求:自动化构建系统、自动化测试套件
5. Stub vs Driver ------ 常考对比 ⭐
Stub(桩) Driver(驱动)
模拟下层被调模块 模拟上层调用模块
自顶向下测试使用 自底向上测试使用
就是一个"假装的下层函数" 就是一个"假装的上层调用器"
返回预设的数据 调用被测试模块的方法

记忆技巧

  • S tub = Subordinate(下属 / 下层)
  • D river = Director(导演 / 上层)
6. 回归测试(Regression Testing)
  • 定义 :对修改后的代码重新运行已有测试,确保修改没有破坏已有的功能
  • 为什么会引入回归 bug:代码之间的耦合------修改 A 不小心破坏了依赖 A 的 B
  • 自动化:回归测试应尽量自动化,否则人工重复执行成本极高
  • 时机:每次代码变更后(bug fix、功能添加、重构)

易错点

  1. 覆盖度标准之间的包含关系
    • 路径覆盖 ⊃ 分支覆盖 ⊃ 语句覆盖(是对的)
    • 条件覆盖 ⊃ 分支覆盖(不一定! 条件覆盖可能不满足分支覆盖的要求)
  2. 圈复杂度计算公式记混:最实用的是"判定节点数 + 1"。不要记错了。
  3. Stub 和 Driver 的方向搞反Stub 在下层 (被调用者),Driver 在上层(调用者)。自顶向下需要 Stub;自底向上需要 Driver。
  4. 语句覆盖 = 100% = 程序没有 bug:错!即使语句覆盖 100%,仍然可能有逻辑 bug。
  5. 大爆炸集成仅适合小项目:对于大型项目,大爆炸集成几乎不可能定位错误。

高频考点

  • 四种覆盖标准的定义和强弱对比(必考------选择 / 简答)
  • 圈复杂度的计算(三种方法)(必考------综合应用)
  • 集成测试策略对比以及 Stub / Driver 的区分(必考------选择 / 简答)
  • 回归测试的定义和目的(高频简答)
  • 持续集成的概念

Lecture 15 --- 配置管理

快速理解

"多人协作开发时,谁改了什么?谁改了哪个版本?怎么合并?"配置管理解决的就是这些问题。本讲介绍配置管理的四大活动、核心概念和版本控制基础。

核心知识点

1. 配置管理(Configuration Management, CM)的定义
  • CM 是一套管理软件变更的系统化方法
  • 目标:确保软件产品在其生命周期中的完整性、一致性和可追溯性
  • 核心问题:谁、什么时候、为什么、做了什么修改
2. 配置管理的四大活动

(1)配置识别(Configuration Identification)

  • 确定哪些软件元素需要受控管理 → 这就是配置项(Configuration Item, CI)
  • 配置项包括:代码文件、需求文档、设计文档、测试用例、构建脚本、配置文件、用户手册等
  • 每个 CI 有唯一的标识符和版本号
  • 配置项的选择是 CM 中最基础的活动

(2)配置控制(Configuration Control)

  • 管理对配置项的变更(变更管理流程)

  • 变更控制委员会(Change Control Board, CCB):评审变更请求的决策机构

  • 标准变更流程:

    复制代码
    提交变更请求 (CR) → 影响分析 → CCB 评审 → 
    批准 → 实施变更 → 验证变更 → 更新基线
    拒绝 → 终止
  • 关键点:不是所有变更都会被批准------不必要或不合理的变更应被拒绝

(3)配置状态报告(Configuration Status Accounting)

  • 记录和报告每个配置项的当前状态变更历史
  • 回答的问题:
    • 这个 CI 当前是什么版本?
    • 谁正在处理这个 CI?
    • 哪些变更请求在等待中?
    • 从某个基线开始已经做了多少变更?

(4)配置审计(Configuration Auditing)

  • 验证:实际的产品和文档是否与记录的配置一致
  • 确保"说的 = 做的"(实际产品 = 配置记录)
  • 两种审计:
    • 功能配置审计(FCA):确认功能是否满足需求
    • 物理配置审计(PCA):确认产品文档是否完整,配置是否一致
3. 核心概念
概念 定义 要点
配置项 (CI) 被配置管理控制的基本单元 代码、文档、脚本、数据均在范围内
基线 (Baseline) 经过正式评审和批准的配置快照,是后续变更的参照起点 里程碑性质、不可随意修改
版本 (Version) 配置项在特定时间点的状态 每个版本都是 CI 的特定实例
分支 (Branch) 从主线分离的独立开发线 支持并行开发
合并 (Merge) 将不同分支的变更整合 可能产生冲突,需要人工解决
标签 / 标记 (Tag / Label) 给特定版本打上标识,便于后续引用 通常用于标记 Release 版本

基线的重要性

  • 基线 = 变更控制的基准
  • 一旦确立基线,对基线的任何变更都必须走正式的变更流程
  • 典型的基线:需求基线、设计基线、产品发布基线
4. 版本控制系统(VCS)

集中式(Centralized VCS)------ 如 SVN、CVS

优点 缺点
管理集中,权限控制简单 服务器单点故障
易于管理 网络中断无法提交
学习曲线平缓 分支操作较慢且存储冗余

分布式(Distributed VCS)------ 如 Git、Mercurial

优点 缺点
每个开发者都有完整仓库副本 学习曲线较陡
支持离线操作 仓库容量大
分支 / 合并操作快速高效 权限管理相对复杂
强大的社区支持(GitHub / GitLab)
5. 分支策略(Branching Strategy)

(1)主干开发(Trunk-based Development)

  • 只有一个长期分支(trunk / main),所有开发都在主干上
  • 短生命周期功能分支,频繁合并(每日至少一次)
  • 适合 CI / CD、自动化测试成熟的项目
  • 减少合并冲突

(2)GitFlow

  • 两种长期分支:master (生产发布)和 develop(开发主线)
  • 临时分支:feature (功能开发)、release (发布准备)、hotfix (紧急修复)
    1. 从 develop 创建 feature 分支开发新功能
    2. 功能完成后合并回 develop
    3. 从 develop 创建 release 分支做发布准备
    4. release 分支合并到 master 和 develop
    5. 从 master 创建 hotfix 分支做紧急修复
    6. hotfix 合并回 master 和 develop
  • 适合有正式发布周期的项目

(3)GitHub Flow / Feature Branch

  • 简化版:master 分支始终可发布
  • 从 master 创建 feature 分支 → 开发 → PR 评审 → 合并回 master
  • 简洁,适合持续部署

易错点

  1. 配置项(CI)不仅是代码:很多考生误以为只有代码需要配置管理。实际上,需求文档、设计文档、测试用例、部署脚本等所有软件元素都是 CI。
  2. 基线 vs 版本混淆 :每个版本是 CI 的一个快照,但基线是经过正式评审的特殊版本,具有里程碑意义。不是每个版本都能称为基线。
  3. 版本控制 ≠ 配置管理:版本控制是配置管理的一个部分(主要对应配置识别和变更控制)。配置管理还包括配置审计、状态报告等。
  4. 变更不是都该批准的:不要以为所有变更请求都应该被 CCB 批准。变更需要评估影响,不合理的不批。
  5. SVN = 集中式,Git = 分布式:考试中常考这两种类型的特点对比。
  6. GitFlow 各分支的命名和用途容易混淆:master 是生产发布;develop 是集成开发;feature 是功能开发;release 是发布准备;hotfix 是紧急修复。

高频考点

  • 配置管理四大活动的名称和内容(必考------简答)
  • 配置项(CI)的定义和范围(高频选择)
  • 基线的定义和作用(高频简答 / 选择)
  • 集中式 vs 分布式版本控制系统对比(高频简答)
  • 变更管理的标准流程(高频简答)
  • 分支策略(GitFlow)
  • 配置审计的 FCA 和 PCA 两种类型

Lecture 16 --- 成本估算

快速理解

"这个项目需要多少人做多久?要花多少钱?"成本估算是项目启动前最关键也最困难的活动之一。本讲介绍几种常见的估算方法,核心是 COCOMO 模型。

核心知识点

1. 为什么软件成本估算这么难?
  • 软件是无形产品------没有物理制造过程
  • 需求的变化不确定性
  • 新技术的引入使历史数据参考价值降低
  • 团队能力、经验也有显著影响
  • 开发效率不是线性的(沟通成本随团队规模增加)
2. 主要估算方法总览
方法 原理 适用阶段 准确性 客观性
专家判断 (Expert Judgment) 请有经验的专家来估算 任何阶段 取决于专家水平 主观
类比估算 (Estimation by Analogy) 参考类似项目的实际数据 早期
算法模型 (Algorithmic Model) 使用数学公式(如 COCOMO) 有规模估算后 较高 客观
功能点分析 (Function Points) 基于功能需求估算规模 需求完成后 较高 客观
LOC 估算 (Lines of Code) 基于代码行数估算 设计 / 实现阶段 随阶段推进提高 客观
Pricing to Win 按客户出价确定"成本" 任何阶段 🚫 不推荐 操控
3. COCOMO 模型(Constructive Cost Model)

COCOMO 81:由 Barry Boehm 在 1981 年提出,有三个层次:

  • 基本 COCOMO(Basic) :仅基于**规模(KLOC)**估算
    • 不精确,但快速
  • 中级 COCOMO(Intermediate) :规模 + 15 个成本驱动因子
    • 更精确
  • 详细 COCOMO(Advanced / Detailed) :分阶段应用成本驱动因子
    • 最精确但也最复杂

三种项目类型

类型 英文 说明 a (Effort) b c (Time) d 例子
组织型 Organic 小团队、熟悉领域、开发环境好、低复杂度 2.4 1.05 2.5 0.38 简单的 MIS 系统
半分离型 Semi-detached 中等规模、团队成员经验混合、中等复杂度 3.0 1.12 2.5 0.35 数据库系统、OS 实用程序
嵌入型 Embedded 强约束(硬件、实时、安全)、高复杂度 3.6 1.20 2.5 0.32 飞行控制系统、ATM 系统

基本 COCOMO 公式:

复制代码
工作量:Effort = a × (KLOC)^b      (单位:人月,Person-Months)
工期:   Time   = c × (Effort)^d   (单位:月,Months)
人数:   Staff  = Effort / Time    (约数)

例子:估计为 10 KLOC 的组织型项目:

  • Effort = 2.4 × (10)^1.05 ≈ 2.4 × 11.22 ≈ 26.93 人月
  • Time = 2.5 × (26.93)^0.38 ≈ 2.5 × 3.53 ≈ 8.83 月
  • Staff ≈ 27 / 9 ≈ 3 人

中级 COCOMO 的 15 个成本驱动因子(只需知道有这些类别):

  • 产品属性:RELY(可靠性)、DATA(数据库大小)、CPLX(复杂度)
  • 硬件属性:TIME(时间约束)、STOR(内存约束)、TURN(周转时间)
  • 人员属性:ACAP(分析师能力)、AEXP(应用经验)、PCAP(程序员能力)等
  • 项目属性:MODP(现代编程实践)、TOOL(工具使用)、SCED(进度约束)

中级 COCOMO:Effort = a × (KLOC)^b × EAF

  • EAF(Effort Adjustment Factor)= 15 个成本驱动因子的等级值的乘积
  • 每个因子取值为:很低、低、正常、高、很高、极高

COCOMO II(1995 年更新):

  • 适应现代开发实践(重用、增量开发、快速原型)
  • 使用功能点对象点替代 KLOC 作为输入
  • 三个阶段模型(Early Design → Post-Architecture → Post-Development)
4. 功能点分析(Function Point Analysis)
  • 由 Allan Albrecht(IBM)在 1970s 提出
  • 基于功能需求估算软件规模,与实现技术无关

五个功能维度:

维度 英文缩写 说明 例子
外部输入 EI 外部实体向系统输入数据 新增订单、修改客户信息
外部输出 EO 系统向外部输出数据(含计算 / 处理) 生成报表、打印发票
外部查询 EQ 查询请求 + 返回结果(不含计算) 查询订单状态
内部逻辑文件 ILF 系统内部维护的逻辑数据集合 客户信息表、产品目录
外部接口文件 EIF 系统引用的外部数据集合 外部汇率表
  • 每个维度按复杂度(低 / 中 / 高)赋予权重
  • 总 FP = 各维度加权和 → 可转换为代码行数(按语言转换率)
  • 功能点 vs LOC
    • 功能点:与语言无关、可在早期估算、主观看程度高
    • LOC:依赖语言、难以早期估算、客观
5. 三条重要的估算法则
法则 内容 管理含义
Parkinson's Law 工作会膨胀以填满可用时间 设置合理的截止期限很重要
Brooks' Law 给延期的项目加人会使其更延期 人月不是可互换的;加人增加沟通成本而非降低工作量
Pricing to Win 按客户预算倒推成本 ⚠️ 不道德------可能牺牲质量和团队成员利益

Brooks' Law 的深层原因(记住常考 ⭐):

  1. 新人需要学习时间(ramp-up time),不仅不贡献还在消耗团队精力
  2. 沟通成本非线性增长 :n 个人的沟通链路数 = n(n−1)/2n(n-1)/2n(n−1)/2
  3. 工作不可分解:有些任务没法分配给多人并行做

易错点

  1. COCOMO 三种项目类型的特征混淆:Organic(小 / 熟悉 / 简单)→ Semi-detached(中等)→ Embedded(强约束 / 高复杂度)。考试中常给场景让你判断类型。
  2. 功能点五个维度的名称记忆顺序混乱:记住 EI(输入)、EO(输出)、EQ(查询)、ILF(内部文件)、EIF(外部文件)。
  3. LOC 估算 vs 功能点估算:LOC 依赖编程语言、可量化;功能点与技术无关、可早期估算。不是同一个东西!
  4. Brooks' Law 的精髓 :人月不可交换------给一个延期的项目加人只会让它更延期。不是"加人没用",而是"加人短期会拖慢进度"。
  5. Pricing to Win 不是合理的估算方法:这是按客户预算报价,而不是按实际工作量估算,可能导致项目亏本或质量下降。
  6. 基本 vs 中级 COCOMO 的区别:中级多了 15 个成本驱动因子(EAF 调整因子)。

高频考点

  • COCOMO 三种项目类型和各自的特征(必考------选择或简答)
  • 基本 COCOMO 公式的工作量 / 工期关系(必考------简答或计算)
  • 功能点五个维度的名称(高频简答 / 选择)
  • Brooks' Law 的解释和原因(必考------简答)
  • Parkinson's Law(高频简答-概念)
  • 各种估算方法的优缺点对比(高频选择 / 简答)
  • COCOMO 的三个层次(基本→中级→详细)
  • 中级 COCOMO 的 EAF 调整

必背速查表

1. SOLID 原则速查

缩写 全称 一句话
S Single Responsibility Principle 一个类一个职责
O Open / Closed Principle 对扩展开放,对修改封闭
L Liskov Substitution Principle 子类可替换父类
I Interface Segregation Principle 接口要小
D Dependency Inversion Principle 依赖抽象不依赖细节

2. 耦合度从好到差

数据耦合 → 印记耦合 → 控制耦合 → 公共耦合 → 内容耦合

3. 内聚度从好到差

功能内聚 → 顺序内聚 → 通信内聚 → 过程内聚 → 时间内聚 → 逻辑内聚 → 偶然内聚

4. 测试覆盖标准从弱到强

语句覆盖 → 分支覆盖 → 条件覆盖 → 路径覆盖

(注意:条件覆盖不一定满足分支覆盖)

5. 圈复杂度口诀

判定节点数 + 1 (最简单版本)

6. Stub vs Driver

Stub Driver
模拟下层(被调)模块 模拟上层(调用)模块
用于自顶向下集成测试 用于自底向上集成测试

7. Verification vs Validation

Verification Validation
"Building the product right" "Building the right product"
验证规格正确性 确认需求满足度

8. 聚合 vs 组合

聚合 (Aggregation) 组合 (Composition)
空心菱形 ◇ 实心菱形 ◆
部分可独立存在 部分随整体消灭
弱整体-部分 强整体-部分

9. 功能点五个维度

EI (外部输入)→ EO (外部输出)→ EQ (外部查询)→ ILF (内部逻辑文件)→ EIF(外部接口文件)

10. COCOMO 三种项目类型

Organic(组织型) < Semi-detached(半分离型) < Embedded(嵌入型)

(越往右规模越大、复杂度越高、约束越强)

整理完成,祝你复习顺利,考试高分!

声明:以上内容均由 Claude Code 根据课程课件进行整理,用于期末复习

相关推荐
搞科研的小刘选手3 小时前
【高届数计算机方向会议】第七届计算机视觉与数据挖掘国际学术会议(ICCVDM 2026)
人工智能·算法·计算机·数据挖掘·软件工程·视觉·信息
sxdtzhp1 天前
定时任务避峰运行:远离整点,保障系统稳定运行
运维·软件工程·定时任务·crontab
破无差1 天前
等价类划分经典案例:三角形问题
软件工程
大鹏的NLP博客1 天前
AI 正在改变软件工程:我的 AI 协同开发实践
人工智能·软件工程
小智老师PMP2 天前
零基础能不能考PMP?零基础专属学习路径+全套扶持体系
学习·算法·职场和发展·软件工程·求职招聘·敏捷流程
Dola_Zou2 天前
工业软件防破解避坑指南:CodeMeter 全流程入门与选型(下)
人工智能·安全·自动化·视觉检测·软件工程
呼Lu噜2 天前
生命周期模型概述(软考教材版)
学习·软件工程
折哥的程序人生 · 物流技术专研2 天前
AI 编程与行业赋能|专栏总目录(持续更新)
开发语言·人工智能·软件工程·ai编程
石逸凡2 天前
从「1+1+N」到「N+N」---软件研发Harness代理工程的新跃迁
人工智能·软件工程