目录
总结:软件工程概述
1. 软件的本质
- 定义:
- 软件是可执行的指令(程序)、操作信息的数据以及描述程序操作和使用的文档。
- 特点:
- 无形,需通过运行了解功能、特性、质量。
- 脑力劳动密集,复杂、昂贵、易出错。
- 不因时间老化,但需维护和技术更新。
- 依赖特定计算机系统环境。
- 可复制和复用。
- 软件危机:
- 开发速度跟不上需求,设计拙劣、资源不足导致维护困难。
- 软件失败可能造成经济损失或灾难。
2. 什么是软件工程
- 定义:
- 1968年NATO会议提出,解决软件危机。
- Fritz Bauer:经济地获得可靠、高效运行软件的工程化原则。
- IEEE:系统化、规范、可量化的开发、运行、维护软件的方法及研究。
- 目标:
- 指导开发、运行、维护,满足工程约束,确保软件质量。
- 质量是根本目标,贯穿程序和文档,体现技术追求和职业道德。
- 基本原则(Barry Boehm, 1983):
- 分阶段生命周期管理。
- 阶段评审、产品控制。
- 采用现代程序设计技术。
- 结果可审查、团队精简、持续改进实践。
- 核心实践原则(David Hooker):
- 为用户提供价值。
- 保持简单(KISS原则)。
- 维护清晰架构愿景。
- 考虑未来用户和维护者。
- 设计适应未来变化。
- 计划复用。
- 深思熟虑后再行动。
3. 为什么要学习软件工程
- 分解复杂问题为可管理模块。
- 工程化方法高效构建可靠软件。
- 培养逻辑思维和结构化思考能力,适用于技术与非技术领域。
4. 过程、方法和工具
- 层次化技术:
- 过程:支持软件生命周期所有活动。
- 方法:提供“如何做”的技术。
- 工具:提供自动化或半自动化支持。
- 软件生命周期(SLC):
- 包含问题定义、可行性分析、需求分析、设计、编码、测试、验收、维护、废弃等阶段。
- 每阶段有明确任务,产生工作产品,经审核后进入下一阶段。
- 活动由动作构成,动作由任务构成(例:需求获取任务包括联系、讨论、记录、审阅)。
- 主要活动(过程框架):
- 沟通、策划、建模、构建、部署。
- 保护伞活动:
- 项目跟踪、测量、技术评审、质量保证、风险管理、配置管理、可复用管理。
5. 软件工程过程模型
- 瀑布模型:
- 按阶段顺序展开,问题需返回上一阶段修改。
- 问题:难以遵守顺序、客户需求不清晰、线性导致阻塞、客户晚见成果。
- 增量模型:
- 分步交付功能,逐步完善。
- 演化模型:
- 螺旋模型:迭代开发,结合风险评估。
- 快速原型:快速构建抛弃型或演化型原型,便于验证需求。
- 螺旋模型:迭代开发,结合风险评估。
- 统一过程模型(RUP):
- 用例驱动、架构中心、迭代增量开发。
- 最佳实践:迭代开发、管理需求、组件架构、可视化建模、验证质量、控制变更。
6. 软件工程方法
- 经典方法(生命周期方法学/结构化范型):
- 使用结构化分析、设计、实现,辅以工具支持。
- 面向对象方法:
- 模拟现实系统,映射问题域,强调对象及关系。
- 面向方面方法:
- 处理系统性关注点(Crosscutting Concern),通过方面定义需求,运行/编译时应用。
- 基于构件方法(CBSD):
- 强调组装已有构件(COTS或自开发),降低开发和维护成本。
- 基于知识的软件工程:
- 运用知识工程,从知识化需求到实现,AI辅助开发有潜力。
7. 软件工程工具
- 计算机辅助软件工程(CASE):
- 使用计算机工具支持开发、维护、管理。
- 本课重点工具:UML。
8. 软件工程知识体系(SWEBOK)
- 定义:
- IEEE制定的软件工程核心知识框架,涵盖15个领域(需求、设计、构建、测试、维护、配置管理等)。
- 2024年9月25日发布SWEBOK 4.0,新增软件架构、运营、安全。
- 特点:
- 非教条,需根据项目特点、团队文化灵活调整。
- 职业道德规范(SEEPP):
- 符合公众利益、客户雇主利益。
- 确保高质量行业标准、独立判断。
- 道德开发管理、弘扬职业正义、尊重公众利益。
- 平等对待同行、终身学习、倡导道德工作方式。
- 软件工程师品质(Erdogmus, 2009):
- 责任感、需求敏锐、坦诚、抗压、公平、注重细节、务实。
9. 其他
- 重型化问题:
- 文档撰写和评审耗时,需求变更频繁,降低效率。
- 文档重要但无成就感,需平衡文档与代码(敏捷方法应对)。
总结:项目计划
1. 启动一个软件项目
- 明确目标与范围:
- 目标:定义项目目的,不涉及实现方式。
- 范围:规定软件基本功能。
- 候选解决方案:
- 提供可行性分析基础,定义交付期限、预算、人员能力、技术界面等约束。
- 技术与管理要求:
- 明确技术和管理需求,确保项目方向清晰。
2. 制定项目计划
- 资源估算:
- 估算人力、物力、财力、信息资源及项目持续时间。
- 进度安排:
- 分配资源,建立项目组织,分配任务。
- 风险分析:
- 包括风险识别、估计、优化、驾驭策略、解决、监督,贯穿软件工程过程。
- 质量管理:
- 制定质量管理指标。
- 预算与成本:
- 编制预算,估算成本。
- 环境准备:
- 准备基础设施和环境。
3. 计划的追踪与控制
- 监督实施:
- 管理人员监督过程,提供内部与外部报告。
- 调整资源:
- 根据中间里程碑进度误期,重新分配资源和任务。
- 评审与评价:
- 评审计划完成度,检查计划与项目一致性。
4. 编写管理文档
- 文档检查:
- 检查结果与记录的完整性。
- 存档:
- 编写文档并存档,确保可追溯。
5. 项目管理中人的因素
- 4Ps(或3Ps):
- 人:招聘、培训、绩效管理、团队文化。
- 产品:目标、范围、解决方案、约束。
- 过程:任务、里程碑、工作产品、质量保证。
- 项目:规划、监控、控制。
- 利益相关者(Stakeholder):
- 高级管理者、项目/技术管理者、开发人员、客户、最终用户。
- 软件项目团队范型(Constantine, 1993):
- 封闭、随机、开放、同步结构。
- 团队分类:
- 控制集权/层次式(CC)、控制分权/主程序员式(CD)、民主分权式(DD)。
- 控制集权/层次式(CC)、控制分权/主程序员式(CD)、民主分权式(DD)。
- 主程序员制团队组成:
- 高级工程师、支持工程师、技术人员、专家、支持人员、软件管理员。
- 团队毒素(Jackman, 1998):
- 狂乱环境、重大挫折、协调差的过程、角色不清、重复错误、个性差异。
- 团队凝聚力:
- 团结紧密的团队整体力量大于个体总和,凝聚力提升成功率。
- 人员与工作量:
- 增加人手可能延误进度(Brooks法则:晚期项目加人使之更晚)。
6. 度量与估算
- 度量重要性:
- 度量是工程学科基础,需用数字表达了解程度(Lord Kelvin)。
- 面向规模的度量:
- 基于代码行(Loc/Kloc),指标包括:
- 每千行代码错误数、成本、文档页数。
- 每人月错误数、代码行、文档成本。
- 基于代码行(Loc/Kloc),指标包括:
- 面向功能的度量:
- 功能点(FP)公式:FP = CT × (0.65 + 0.01 × ΣFi)。
- CT:用户输入、输出、查询、文件、外部接口数。
- Fi:14项调整因子(如备份、数据通信)。
- 功能点(FP)公式:FP = CT × (0.65 + 0.01 × ΣFi)。
- 软件质量度量:
- McCall模型、Boehm模型:层级质量属性(高层、中层、原始)。
- ISO/IEC 9126(已被ISO/IEC 25010:2011取代)。
- 估算方法:
- 基于类似项目、分解技术、经验模型。
- 需经验、历史数据、定量数据和勇气,接受不确定性。
- 估算完成软件开发所需资源:
- 硬件及软件工具处于资源金字塔的底层,提供支持开发工作的基础
- 可复用软件资源, 能够极大地降低开发成本,并提早交付时间。
- 在金字塔的顶端是主要的资源:人员。
- 分解技术:
- 按过程活动、功能模块、技术架构、交付物划分。
- 应定义最好与最坏情况。
- 三点估算:
- 期望值EV = (Sopt + 4Sm + Spess) / 6(乐观值、可能值、悲观值)。
- 经验模型:
- 形式:E = A + B × (ev)^C(E:工作量,ev:估算变量)。
- Putnam软件方程式:
- E = (Loc^3 × B) / (P^3 × t^4)。
- B:技术因子,P:生产率参数,t:持续时间。
- CoCoMO模型:
- 基本形式:E = aKLOC^b,D = cE^d。
- 包含中级、高级模型及CoCoMO II。
- 其他估算方法:
- 德尔菲法(专家匿名调查)、敏捷估算。
7. 风险管理
- 风险定义:
- 不确定性或损失的不确定性,可用概率和大数法则分析。
- 风险管理三部分:
- 风险识别、排序(估测)、缓解(管理效果评价)。
- 风险分类:
- 纯粹/投机风险、静态/动态风险、财产/人身/责任风险。
- 项目风险:威胁计划,涉及预算、进度、人力、资源、客户、需求,复杂性、规模、不确定性。
- 技术风险:威胁质量与交付,涉及设计、实现、接口、验证、维护,二义性、技术不确定性、陈旧/先进技术。
- 商业风险:威胁生存能力,包括市场风险、战略不符、销售困难、管理支持不足、预算/人力不足。
- 风险预测(估算):
- 评估风险可能性、后果、对项目/产品影响,标注精确度。
- 定义中止线,管理中止线以上风险。
- 风险缓解、监控、管理(RMMM):
- 原则:最小成本获最大保障。
- 策略:回避、预防、自留、转移风险。
8. 项目计划内容
- 项目愿景与范围:
- 愿景(或者视图):
- 回答“要解决的问题是什么?”。
- 抓住问题本质,客观、明确、完整,严格评审。
- 描述产品作用、特性、假设、依赖,统一涉众方向。
- 范围:
- 定义项目需求界限,明确当前解决的部分。
- IEEE愿景与范围文档:
- 包含业务需求(背景、机遇、目标、市场需求、价值、风险)。
- 项目视图(陈述、特性、假设、依赖)。
- 范围与局限性(首次/后续发行范围、专用性)。
- 业务环境(客户概貌、优先级)。
- 产品成功因素。
- 愿景(或者视图):
- 可行性分析:
- 回答“是否有行得通的解决办法?”。
- 技术可行性:
- 分析性能、可靠性、可维护性,所需设备、技术、方法。
- 评估技术风险、成本影响,参考类似系统经验。
- 经济可行性:
- 估算成本(软硬件、开发、安装、维护、培训)。
- 成本-效益分析:收入、节省费用、时间表、货币时间价值、投资回收期/率。
- 法律可行性:
- 考虑合同、责任、侵权、规范,避免法律问题。
- 用户使用可行性:
- 评估行政管理制度、用户素质、培训要求。
- 项目计划步骤:
- 检查愿景与范围。
- 确定人员分工。
- 估算工作量与活动持续时间。
- 平衡活动顺序与时间,制定进度计划表。
- 确认并基线化计划。
- 进度计划方法:
- 里程碑计划、甘特图(1917年Gantt发明)、时标网络计划。
9. 文档重要性
- 作用:
- 标志开发阶段成果。
- 提供进展信息,便于管理检查。
- 记录技术信息,协调开发、使用、修改。
- 提供运行、维护、培训信息,促进各方沟通。
- 向潜在用户展示功能与性能。
- 基本文档:
- 软件需求规格说明书、设计说明书。
- 验证与确认计划、报告。
- 用户文档。
- 其他文档:
- 计划、进展报表、评审报表、总结。
- 参考标准:
- GB8566、GB8567、GB/T8566、GB/T11457、GB/T12504、GB/T12505。
总结:需求分析
1. 什么是需求
- 定义(IEEE97):
- 用户解决问题或达成目标所需的条件或能力。
- 系统/部件满足合同、标准、规范等所需的条件或能力。
- 上述条件的文档说明。
- 需求层次:
- 业务需求:组织目标。
- 用户需求:用户使用场景。
- 功能需求:系统具体功能。
- 非功能需求:性能、可靠性等。
- 特点:
- 描述系统“做什么”,不涉及“如何做”。
- 需求工程活动:
- 计划与问题识别。
- 评审软件范围。
- 确定综合要求、实现条件、标准。
- 获取需求与协商。
- 分析与建模(结构化/面向对象)。
- 剔除不合理功能,补充必要部分。
- 编写规约,复审。
2. 如何获取需求
- 沟通:
- 与决策领导、使用部门、具体用户、维护人员充分交流,理解问题和要求。
- 技术:
- 阅读相关文档。
- 市场调查:了解市场需求及类似系统。
- 咨询领域专家。
- 现场考察:观察操作环境、过程、要求。
- 原型开发:验证需求。
- 注意:
- 需求因人而异且会变化。
- 质量功能部署(QFD):
- 识别三类需求:
- 正常需求:基本功能。
- 期望需求:提升满意度。
- 兴奋需求:超出预期。
- 方法:客户访谈、观察、调查、历史数据,生成客户意见表,复审后提取期望与兴奋需求。
- 识别三类需求:
- KANO模型:
- 分类:
- 基本(必备)型:必须满足。
- 期望(意愿)型:性能与满意度线性相关。
- 兴奋(魅力)型:意外惊喜。
- 无差异型:无关紧要。
- 反向型:导致不满。
- 体现性能与满意度的非线性关系。
- 分类:
- 不合格需求原因:
- 忽略用户分类、用户参与不足。
- 需求变化/增加、模糊、不必要、过于精简。
3. 需求分析与建模
- 指导原则(Davis, 1995):
- 先理解问题。
- 开发原型展示人机交互。
- 记录需求起源与原因,确保可追踪。
- 使用多视图(数据、功能、行为模型),减少遗漏与不一致。
- 赋予优先级。
- 通过技术复审消除模糊性。
- 建模方法:
- 结构化方法。
- 面向对象方法。
- 常用模型:
- 数据流图(DFD):
- 表达数据传递与加工的逻辑功能、流向、变换。
- 元素:
- 外部实体:矩形。
- 加工:圆圈。
- 数据流:箭头。
- 数据存储:双实线。
- 分层:第1层(总体)、第2层(加工展开)。
- 一层
- 二层
- 一层
- 其他画风
- 表达数据传递与加工的逻辑功能、流向、变换。
- 实体关系图(ERD):
- 描述数据对象、属性、对象间关系。
- 元素:
- 数据对象:矩形。
- 关系:菱形框连接线。
- 多重性:标明一对一、一对多、多对多。
- 属性:命名、描述、引用;关键属性加下划线。
- 画风:Crow's Foot Notation。
- 描述数据对象、属性、对象间关系。
- 数据字典(DD):
- 定义数据元素与结构(含义、类型、大小、格式、单位、精度、取值范围)。
- 内容:
- 基本信息:名称、别名、描述。
- 定义:长度、类型、结构。
- 使用特点:取值范围、频率、方式。
- 控制信息:来源、用户、权限。
- 数据组合:
- 顺序:固定次序。
- 选择:选一。
- 重复:多次重复。
- 示例:
- 顺序:请求的化学制品 = 化学制品标识号 + 数量 + 数量单位 + (供应商名称)。
- 选择:数量单位 = [“克”|“千克”|“个”]。
- 重复:请求 = 请求标识号 + 产品编号 + 1:10 {请求的化学制品}。
- 其他模型:
- 状态变迁图(可用UML状态机图替代)。
- 判定表/树、IPO表/图、思维导图、鱼骨图、UML。
- 数据流图(DFD):
4. 需求分析文档(SRS)
- 定义:
- 软件需求规格说明书(Software Requirement Specification),描述软件功能与性能。
- 目标:
- 建立客户与开发者协议。
- 全面描述功能,帮助客户验证需求。
- 提高开发效率,减少返工。
- 提供成本计价与进度计划基础。
- 为验证与确认提供基准。
- 支持软件移植与维护。
- 作为持续改进基础。
- 基本要求:
- 描述功能与性能。
- 使用确定方法叙述,不涉及设计、验证、项目管理细节。
- 特性:
- 无歧义性:每项需求只有一种解释。
- 完整性:
- 包含所有功能、性能、约束、属性、接口需求。
- 定义所有输入数据响应。
- 填写完整图表、术语、单位。
- 可验证性:每项需求可验证。
- 一致性:需求间无矛盾。
- 可修改性:
- 结构清晰(目录、索引、交叉引用)。
- 避免冗余,减少错误。
- 可追踪性:需求来源清晰,便于引用与维护。
- 运行与维护适用性:支持局部与大范围修改,清晰记录功能来源。
- 可读性建议(Somerville & Sawyer, 1997):
- 统一编号节、小节、需求。
- 使用可视化强调标志(黑体、下划线、斜体)。
- 创建目录与索引。
- 为图表指定标识号。
- 其他建议:
- 使用自然语言,避免技术术语。
- 提供背景铺垫,增强因果联系。
- 定义专有名词。
- 逻辑清晰、结构合理、重点突出、排版工整。
- 使用图表配合文字。
- 管理版本,记录修订(颜色标示变更)。
- 避免流水账。
总结:软件设计
1. 什么是设计
- 定义:
- 设计是为构建有意义的秩序的有意识努力(Victor Papanek)。
- 应用技术和原则,详细定义设备、处理或系统以实现物理实现(TAY59)。
- SWEBOK v4.0:理解需求(做什么)并制定解决方案(如何做)。
- 过程:
- 从需求(功能、行为、信息描述)转化为设计(数据、总体结构、过程设计)。
- 包含编码、集成、确认、测试。
- 阶段:
- 传统分法:总体设计(架构设计)、详细设计(数据、接口、过程设计)。
- SWEBOK v4.0:架构设计、高层设计、详细设计。
2. 设计阶段
- 架构设计:
- 目标:建立系统顶层结构。
- 内容:
- 定义子系统、关键构件、关键类职责及协作。
- 描绘物理运行环境部署模型。
- 提供全局性、基础性技术解决方案(技术基础设施)。
- 高层设计:
- 设计内容:
- 系统响应的外部事件/消息。
- 系统生成的事件/消息。
- 事件/消息的数据格式、协议规范。
- 输入/输出事件顺序与计时关系。
- 端到端事务/事件线程跟踪。
- 数据持久性(存储与管理)。
- 设计内容:
- 详细设计:
- 设计内容:
- 细化系统组件为模块/程序单元(含现成框架/组件)。
- 分配设计责任。
- 模块间交互、范围、可见性。
- 组件模型、状态、转换。
- 数据与控制依赖关系。
- 数据组织、打包、实现。
- 用户界面、算法、数据结构。
- 设计内容:
- 工作产品:
- 设计描述/规范(文本、图表、模型、原型),构成软件实现蓝图。
- 特点:
- 设计是迭代过程。
3. 设计概念
- 抽象(Abstraction):
- 处理复杂问题的基本方法,忽略低层细节,聚焦一般性问题。
- 类型:
- 过程抽象:命名隐含功能的指令序列(如“开门”)。
- 数据抽象:冠名数据集合,包含属性(如“门”的类型、重量)。
- 关注点分离(Separation of Concerns, SOC):
- 分而治之,将复杂问题分解,分别研究各关注点,综合解决方案。
- 求精/分解/模块化(Refinement/Modularization):
- 自顶向下细化设计,逐步提供细节。
- 模块化使程序可理性管理。
- 信息隐蔽/封装(Information Hiding/Encapsulation):
- 模块隐藏设计决策,仅暴露必要信息,降低模块间依赖。
- 功能独立(Functional Independence):
- 模块专注单一子功能,简单接口。
- 衡量标准:
- 内聚(Cohesion):模块内功能强度。
- 耦合(Coupling):模块间依赖程度。
- 高内聚低耦合是设计目标。
- 复用(Reuse):
- 降低开发与维护成本。
- 复用对象:代码、领域知识、经验、设计、架构、需求、文档。
- 形式:架构、模式、机制、惯用法。
- 重构(Refactoring):
- 不改功能,调整代码,改善质量、性能、架构,增强扩展性与维护性。
- 检查冗余、低效算法、不当数据结构等,优化设计。
- 质量指导原则:
- 模块化、层次结构、独立功能模块。
- 降低模块与外部复杂连接。
- 包含数据与过程抽象。
- 支持可重复方法。
- 优雅处理异常,平滑降级,永不“彻底崩溃”。
- 设计方法:
- 模块化程序开发、结构化自顶向下设计、面向对象设计、体系结构、设计模式、面向方面、模型驱动开发、测试驱动开发。
4. 架构设计
- 定义:
- 程序构件(模块)的层次结构、交互方式、数据结构(UML 1.4)。
- 可递归分解为部分,通过接口、关系、约束交互。
- 常见架构模式(Buschmann, 1996):
- 分层、管道和过滤、黑板、代理、MVC、微内核。
- 架构风格(模式):
- 仓库体系结构:
- 中心数据结构 + 独立处理部件(如银行数据库系统)。
- 黑板:
- 元素:知识源(独立知识)、黑板数据(层次化解决问题)、控制(状态驱动)。
- 应用:信号处理、检索、自动化、语音/模式识别、智能控制。
- 管道和过滤器:
- 模块接收输入、处理、输出数据流。
- 调用返回:
- 自顶向下结构化,数据流图映射为结构图。
- 层次体系结构:
- 分层提供/使用服务(应用层、任务层、数据存储层)。
- MVC:
- 模型(数据)、视图(显示)、控制器(交互)。
- 示例:JSP + Servlet + JavaBean。
- 分布式体系结构:
- 同构/异构节点通过网络协议交换数据(如B/S、C/S)。
- 同构/异构节点通过网络协议交换数据(如B/S、C/S)。
- 仓库体系结构:
- 架构与框架:
- 架构:抽象,定义整体结构与协作。
- 框架:具体技术实现,同一架构可有多种框架。
- 类比:架构如类,框架如对象。
5. 详细设计
- 内容:
- 界面设计(UI、交互、接口)。
- 过程设计。
- 子系统/软构件设计。
- 数据设计。
- 界面设计(UI):
- 设计人机交互、操作逻辑、界面美观。
- 黄金规则(Theo Mandel, 1997):
- 用户控制权,灵活交互,可中断/撤销。
- 隔离内部细节,直接操作屏幕对象。
- 减轻记忆负担,提供可视提示、默认设置、快捷方式。
- 基于真实世界象征,渐进揭示信息。
- 保持界面一致,符合用户期望。
- 数据设计:
- 选择数据对象的逻辑表示(数据结构)。
- 标识作用于数据结构的程序模块,约束影响域。
- 存储管理:
- 文件管理系统:成本低、操作简单,需额外代码提升抽象。
- 关系/面向对象数据库管理系统。
- 关系数据库设计:
- 数据建模(ER模型)。
- 逻辑设计(规范关系模式)。
- 物理设计(工具实现)。
- 部署与维护(DBMS细节)。
6. 设计文档
- 重要性:
- 促使缜密思考,收集反馈,完善设计。
- 便于交付、交接,沉淀与传承知识。
- 建议:
- 建模:用图表表达,易于解析。
- 用数字:提供具体数据(如数据库行数、延迟),反映问题规模。
- 保持简单(KISS):
- 简单语言、短句、列表、具体示例。
- 避免学术化写作,注重清晰与反馈。
- 怀疑测试:预想审阅者疑问,提前解决。
- 假期测试:确保文档清晰,他人可按意图实施。
- 知识共享非主要目标,但有助于评估清晰度。
7. 设计原则与设计模式
- 面向对象设计原则:
- 是指导思想,价值观,高质量软件基础,设计模式出发点。
- SOLID原则:
- 单一职责(SRP):一个类/模块负责单一功能。
- 开闭(OCP):对扩展开放,对修改关闭。
- 里氏替换(LSP):子类可替换父类。
- 接口隔离(ISP):客户端不依赖无关接口。
- 依赖倒置(DIP):高层模块不依赖低层,依赖抽象。
- 迪米特法则(LOD):最少知识原则,减少对象间交互。
- 设计模式:
- 解决常见问题的通用方法,描述问题、背景、解决方案(Christopher Alexander, 1977)。
- 包含背景(可重现情形)、问题(目标与约束)、解决方案(经典设计规则)。
- GoF 23种设计模式:
- 创建型:
- 单例:唯一实例,全局访问。
- 原型:克隆新实例。
- 工厂方法:子类决定产品。
- 抽象工厂:创建产品族。
- 建造者:分步构建复杂对象。
- 结构型:
- 代理:控制对象访问。
- 适配器:接口转换。
- 桥接:抽象与实现分离。
- 装饰:动态增加职责。
- 外观:简化子系统接口。
- 享元:共享细粒度对象。
- 组合:树状层次结构。
- 行为型:
- 模板方法:定义算法骨架,子类重定义步骤。
- 策略:封装可替换算法。
- 命令:封装请求。
- 职责链:请求沿链传递。
- 状态:状态改变行为。
- 观察者:一对多通知。
- 中介者:简化对象交互。
- 迭代器:顺序访问聚合对象。
- 访问者:为集合元素提供多访问方式。
- 备忘录:保存/恢复对象状态。
- 解释器:定义语言文法与解释。
- 创建型:
- 设计努力:
- 杰出设计看似简单,但需极大努力(Michael Abrash)。
总结:OOAD & UML
1. 面向对象分析与设计(OOAD)
- 面向对象(Object Oriented):
- 相对于面向过程,将数据和方法组织为整体,贴近事物自然运行模式。
- 通过抽象现实世界建模,是编程技术发展的产物。
- 对象(Object):
- 数据与动作的结合体,能操作并记录操作结果。
- 特点:
- 明确边界(封装)。
- 唯一标识。
- 类(Class):
- 共享相同属性、操作、关系、语义的对象的抽象。
- 对象是类的实例。
- OOAD:
- 分析与设计中映射问题域中的对象/实体(如顾客、汽车)。
- 优点:构建与现实世界对应的模型,保持结构、关系、行为模式。
- 对象是某一个人,类是人这个笼统的概念。通过对人的实例化可以得到一个对象。
2. 认识 UML
- 定义:
- 统一建模语言(Unified Modeling Language),用于可视化、规格说明、构造、文档化软件密集型系统。
- 规则:
- 命名、范围、可见性、完整性、执行。
- 公共机制:
- 规格说明、修饰、通用划分。
- 扩展机制:
- 构造型(stereotype)也被叫做版型或衍型:引入新建模元素。
- 标记值(tagged value):扩展构造型特性。
- 约束(constraint):增加/修改规则。
- 外廓(profile):预定义构造型、标记值、约束,适用于特定领域。
- 视图(Views):
- 从不同阶段、视角、层次描述系统:
- 用户模型(用例建模)。
- 结构模型(静态结构:类、对象、关系)。
- 行为模型(动态行为)。
- 实现模型(系统结构与行为)。
- 环境模型(运行环境结构与行为)。
- 4+1 视图(Philippe Kruchten, 1995,RUP采纳):
- 用例视图 + 逻辑视图、进程视图、部署视图、实现视图。
- 从不同阶段、视角、层次描述系统:
3. 用例模型
- 用例(Use Case):
- 描述系统如何响应外界请求,通过用户场景获取需求。
- 提供场景,说明系统与用户/其他系统交互,达成业务目标。
- 使用用户/领域专家语言,避免技术术语,由开发者和用户共同创作。
- 主要用于定义功能性需求。
- 参与者(Actor):
- 系统外通过边界与系统交互的事物(如用户、硬件、其他系统)。
- 用小人表示,代表抽象角色(非具体实体,如猪圈系统中的“猪”仍用小人)。
- 识别参与者问题:
- 谁使用主要功能?支持日常工作?维护系统?与硬件/系统交互?对结果感兴趣?定时触发?
- 系统边界:
- 区分自动化与手工/外部系统任务。
- 用矩形框表示(可省略),用例在边界内,参与者在边界外。
- 参与者关系:
- 特殊化/一般化、特化/泛化(继承关系)。
- 用例获取:
- 需求分析阶段产生,随工作深入补充。
- 问题:
- 参与者需要哪些功能?读/写/修改哪些信息?需要哪些事件提醒?哪些功能可自动化?
- 系统输入输出?当前系统问题?
- 用例间关系(UML 2):
- 泛化:子用例继承并特化父用例行为。
- 扩展(Extend):扩展用例为基用例增加行为,基用例独立。
- 包含(Include):基用例复用被包含用例行为,插入公共步骤。
- 注意:
- 用例是完整交互,粒度适中,无先后顺序。
- 慎用泛化、扩展、包含,避免扩展嵌套。
- 用例图(Use Case Diagram):
- 描述用例与参与者关联(association)。
- 箭头表示通信发起方,非数据/业务流。
- CRUD 问题:
- 增删改查(Create, Read, Update, Delete)掩盖业务,忽略用户目的。
- 建议:
- 简单CRUD用“管理××”用例。
- 复杂交互独立为用例。
- 用例详述:
- 方式:文字、活动图、顺序图。
- 文档大纲:
- 用例名、简述、主要参与者、涉众及利益。
- 前置/后置条件、事件流(基本路径、备选路径)。
- 补充约束、字段列表、业务规则、非功能需求、设计约束。
- 待解决问题、相关图。
- 事件流注意:
- 用用户语言,描述交互信息而非系统运作。
- 避免模糊表达(如“例如”)。
- 不涉及界面/内部处理细节。
- 明确开始/结束,注重备选事件流。
4. 交互图
- 类型:
- 顺序图:强调消息时间顺序。
- 通信图:强调对象间结构组织。
- 两者等价,可互转。
- 顺序图(Sequence Diagram):
- 描述对象间动态交互,突出消息时间顺序。
- 元素:
- 参与者/对象:顶部(已有对象)或中间(创建对象)。
- 命名:objectName:ClassName、:ClassName、objectName。
- 原型化角色不加下划线。
- 生命线(Lifeline):表示对象存在时间。
- 激活:拓宽生命线为矩形,表示对象执行任务。
- 撤销:生命线终点加“X”,通常响应消息。
- 消息(Message):
- 对象间通信,含顺序号(可选)、返回箭头(可选)。
- 类型:同步(synchronous)、异步(asynchronous)。
- 监护条件(Guard Condition):[条件],条件真时发送。
- UML 1:用“*”表示重复消息;UML 2:用交互片段。
- 交互片段:描述分支、循环、并发。
- 嵌套:主图引用子图(ref标签),子图可为状态机/活动图。
- 参与者/对象:顶部(已有对象)或中间(创建对象)。
- 通信图(Communication Diagram):
- 描述对象间消息连接关系,突出协作。
- 元素:
- 参与者/对象:与顺序图相同,无法表示创建/撤销。
- 链接:对象间语义关系。
- 消息:同顺序图,需顺序号,含监护条件/迭代标记。
- 对比:
- 顺序图:适合流程可视化、实时规约、复杂场景。
- 通信图:适合协作可视化、头脑风暴。
5. 架构模型
- 包图(Package Diagram):
- 包为容器,描述包间依赖关系。
- 构造型:导入(import,公共命名空间)、访问(access,私有命名空间)。
- 部署图(Deployment Diagram):
- 描述硬件/软件物理配置及系统架构。
- 节点:物理设备(计算机、外部设备),连接说明方式。
- 分配构件/设计元素到节点,表明运行位置。
- 构件图(Component Diagram):
- 描述软件构件及依赖关系,便于分析修改影响。
- 构件类型:源代码、二进制、可执行、文档。
- 特点:
- 类似类(实现接口、依赖/泛化/关联、参与交互)。
- 差异:类为逻辑抽象,构件为物理抽象;构件通过接口访问。
- 进程与线程建模:
- 进程:重量级并发流。
- 线程:轻量级并发流。
- UML:独立控制流建模为主动对象(Active Object),主动类(Active Class)为其类。
6. 对象与类
- 类模型:
- 类、对象、关联是面向对象核心。
- 类图(静态结构)、对象图(实例)揭示系统结构。
- 分析类:
- 需求分析阶段:
- 边界类:系统与参与者边界。
- 控制类:控制逻辑。
- 实体类:信息。
- 早期概念模型,演化为设计阶段的类。
- 需求分析阶段:
- 类设计:
- 可见范围:
- 私有(仅包内)、公开。
- 尽量隐藏,遵循信息隐蔽。
- UML 可见性:公有(+)、私有(-)、保护(#)、包(~)。
- 属性:
- 用业务领域名词命名。
- 可见性:public(全可见)、protected(本类及子类)、private(本类)。
- 遵循信息隐蔽,缩小作用范围。
- 操作:
- 来源:交互图消息、功能实现、管理功能(构造/析构)、复制、其他机制(垃圾收集/测试)。
- 通常只写名称,表达意图。
- 操作建模:用活动图或流程图(如login()方法)。
- 可见范围:
- 类间关系(语义强度从高到低):
- 继承(泛化,Generalization):
- 子类继承父类属性/操作/关联,可替换父类。
- 多态:子类覆盖父类操作。
- 组合(Composition):
- 强归属,部分不能脱离整体。
- 聚合(Aggregation):
- 整体拥有部分,较弱归属。
- 关联(Association):
- 对象间结构联系,可为二元或多元。
- 包含名称(动词短语)、角色名(名词,可带可见性)、多重性(、1..、1-40等)。
- 自关联:同一类对象间联系。
- 依赖(Dependency):
- 非结构化、短暂,使用另一类操作/变量,变化影响依赖方。
- 实现(Realization):
- 类/构件实现接口合约,画为虚线空心三角箭头。
- 原则:
- 自然抽象:反映需求与实现。
- 强内聚、松耦合:优先低强度关系。
- 继承(泛化,Generalization):
- 特殊类:
- 关联类:兼具类与关联特性,连接多类并有属性/操作。
- 抽象类:无直接实例,名称斜体或加<<abstract>>。</abstract>
- 模板类:参数化类,定义类家族,需实例化绑定参数。
- 对象图:
- 对类图实例建模,实例(对象)与链(对象间语义联系,画为直线)。
7. 状态机
- 动态可视化:
- 活动图:强调控制流。
- 状态机图:强调状态与转移。
- 活动图(Activity Diagram):
- 描述活动/动作流程,强调执行序列与条件。
- 用途:工作流建模、类操作建模。
- 元素:
- 活动/动作:
- 活动:有子结构,持续时间。
- 动作:瞬间完成,不可分解。
- 表示法相同,活动可含子活动图。
- 控制节点:
- 决策/合并节点、分叉/汇合节点。
- 起点(唯一,控制流离开)、终点(可多个,控制流进入)。
- 对象节点:活动图中的对象,连接到产生/使用活动。
- 活动边:
- 节点间转换流,可加监护条件或else。
- 控制流与对象流(UML 1虚线,UML 2无区别)。
- 活动分区(Partition):
- 按组织单位/角色(业务模型)或类(设计模型)划分,俗称泳道。
- 扩展区域(Region):对集合执行的活动片段,输入/输出为值集合。
- 活动/动作:
- 状态机图(State Machine Diagram):
- 描述对象生命期,状态与转移的有向图。
- 状态机:对象响应事件的状序列及响应。
- 状态:
- 对象生命期中的条件,满足条件/执行活动/等待事件。
- 由属性值及链决定。
- 转移:
- 状态间关系,因事件或条件进入另一状态。
- 类型:触发器转移(事件触发)、无触发器转移(状态活动完成)。
- 初始/最终状态:
- 初始:对象创建进入,唯一。
- 最终:生命结束,可选,可多个。
- 复杂状态:
- 入口/出口动作、状态活动、内部转移、延迟事件、子状态机。
- 事件:
- 触发状态转移的激励:
- 信号(异步通信,建模为构造型,如对象创建/撤销)。
- 调用、时间推移(after/at)、状态改变(when)。
- 错误:建模为信号,附加到操作。
- 触发状态转移的激励:
- 子状态:
- 组件状态内的变化(子状态/子状态机)。
- 同步状态:连接并发区域的缓冲区。
- 历史状态:记录中断前的最后子状态。
- 选择依据:
- 跨用例/线程:活动图。
- 单个用例多对象:顺序图。
- 单个对象:状态机图。
8. 其他四种图
- 组合结构图(Composite Structure Diagram):
- 从类结构内部审视构件类。
- 交互纵览图(Interaction Overview Diagram):
- 活动图中用顺序图/通信图替换活动。
- 计时图(Timing Diagram):
- 描述对象随时间变化的状态/值及时间约束。
- 适用于消息、事件、内部变化、时间流逝。
- 外廓图(Profile Diagram):
- UML扩展机制集合,补充/细化建模需求。
9. 其他模型
- 非OOAD常用模型:
- 数据流图(DFD)、实体关系图(ERD)、流程图(FD)、结构图(SD)等。
总结:实现
1. 编码
- 定义:
- 生产性:根据设计规格说明书和模型,生成符合要求的程序代码。
- 创作性:依赖程序员的经验、技能、素养及测试水平,发挥主观能动性。
- 程序设计语言:
- 分类:机器语言、汇编语言、高级语言(结构化、面向对象)。
- 趋势:低代码、AI辅助编程。
- 语言选择:
- 考虑应用领域、硬件、开发人员熟练度、用户要求,而非仅追随潮流。
- 编码要求:
- 不仅要求语法正确、无错误,还需良好结构与设计风格。
- 遵循语言约定、组织代码规范,使用IDE自动缩进/格式化,保持一致性。
- 编码规范:
- 数据声明:
- 按类型规范化(常量、简单变量、复杂类型)。
- 多变量声明按字母顺序。
- 复杂数据结构加注释。
- 标识符命名:
- 准确描述实体,面向问题(“什么”而非“怎样”)。
- 长度适中,避免极短(如x)或过长。
- 禁止用汉语拼音。
- 语句结构:
- 清晰、直接的流程控制,简化布尔表达式,用括号提高可读性。
- 避免为效率或炫技牺牲清晰度。
- 注释:
- 序言性(整体说明)、解释性(具体解释)。
- 避免错误注释。
- 书写格式:
- 使用空格、空行分隔程序段。
- 适当缩进,体现层次关系。
- 数据声明:
- 风格重要性:
- 良好风格提高可读性、减少错误、代码更短小。
- 忽视风格可能导致高昂维护成本。
2. 测试
- 定义:
- Myers:为发现错误而执行程序/系统的过程。
- IEEE:通过人工/自动手段运行/检测系统,验证是否满足需求或找出预期与实际差异。
- 目的:
- 发现错误以修正。
- 提供质量总体评估。
- 局限:
- 无法证明产品正常运行,仅能发现错误。
- 测试原则(Davie, 1995):
- 追溯用户需求,优先发现需求不符的严重错误。
- 提前计划测试,代码生成前即可设计。
- Pareto原则:80%错误源于20%模块。
- 从小规模(单元)到大规模(系统)测试。
- 穷举测试不可行,需覆盖逻辑与条件。
- 独立第三方测试更有效,发现错误最大化。
- 非所有错误都修复(时间、风险、成本考量),但需避免错误决策。
- 保存测试计划、用例、错误统计、分析报告。
- 测试用例:
- 定义:输入 + 输出 + 测试环境,满足特定目标。
- 难点:用少量数据有效揭示缺陷。
- 测试方法:
- 静态测试:不运行程序,审查代码/文档。
- 动态测试:运行程序发现错误。
- 功能测试:验证功能可执行并找错误。
- 结构测试:确保内部操作符合规约,构件充分利用。
- 黑盒测试:
- 方法:等价类划分、边界值分析、因果图、错误推测、失败条件测试。
- 等价类划分:将输入分为有效/无效类,选代表值测试。
- 边界值分析(BVA):测试边界值或附近值,可补充等价类。
- 白盒测试:
- 基本路径测试(Tom McCabe, 1976):基于逻辑复杂性,定义基本执行路径,确保每条语句至少执行一次。
- 测试过程:
- 阶段:单元测试、集成测试、确认测试(验收)、系统测试。
- 测试文档:
- 计划:测试计划、设计说明、用例说明、规格说明。
- 报告:测试项传递报告、测试日志、测试事件报告、测试总结报告。
- 调试:
- 在成功测试后开始,定位错误位置、原因并修正。
- 是软件工程中最困难的工作。
3. 软件维护
- 定义:
- 软件部署至退役期间的所有改动工作。
- 分类:
- 纠错性维护(Corrective):修正使用中发现的错误。
- 适应性维护(Adaptive):适应硬件/软件环境变化(如操作系统、中间件)。
- 完善性维护(Perfective):根据用户建议改进,占维护工作量一半以上,随时间递减。
- 预防性维护(Preventive):提高可维护性/可靠性,为未来维护准备(如添加注释)。
- 维护成本:
- 占软件总成本约80%,逐年上升。
- 无形成本:
- 无法及时满足合理改动需求,导致用户不满。
- 改动引入新故障,降低质量。
- 抽调开发人员维护,干扰开发进程。
- 需降低维护代价以提高效益。
4. 再工程
- 重构(Refactoring):
- 不改功能,重组代码,提高可维护性,支持变更。
- 若文档缺失/不一致,可通过重构获取文档(逆向工程形式)。
- 逆向工程(Reverse Engineering):
- 通过分析现有程序/结果,推导实现方法。
- 用途:推导设计、文档化,便于维护;网络安全(如破解权限)。
- 方法:反汇编、反编译、动态跟踪。
- 再工程(Reengineering/Renovation):
- 调查现有系统,重构为新代码。
- 公式:再工程 = 逆向工程 + 正向工程。
- 目标:解决“坏文档”“坏程序”的重用问题,重构为武器。
总结:项目管理
1. 配置管理
- 定义(Babich, 1986):
- 协调软件开发,减少误解的技术。
- 通过标识、组织、控制修改,最大限度减少错误,提高生产率。
- 软件配置管理(SCM):
- 贯穿软件过程的保护性活动,管理软件配置项(SCI)。
- SCI:计算机程序(源代码/可执行)、文档(技术/用户)、数据(内部/外部)。
- 活动:
- 标识变化。
- 控制变化。
- 确保变化正确实现。
- 向相关人员报告变化。
- 基线(Baseline)(IEEE Std. 610.12-1990):
- 经正式复审批准的规约/产品,作为进一步开发基础,仅通过正式变更控制过程修改。
- 项目储存库中工件版本的“快照”,记录变更差值,直至下一基线。
2. 质量管理
- 软件质量定义:
- 软件与明示/隐含需求一致的程度。
- 具体包括:符合功能/性能需求、开发标准、隐含专业特性。
- 质量度量:
- McCall 质量模型:层级质量属性。
- ISO/IEC 9126(已由ISO/IEC 25010:2023取代):
- 功能适用性:满足明示/暗示需求。
- 性能效率:时间/吞吐量内有效利用资源(CPU、内存等)。
- 兼容性:与其他产品交换信息或共享环境。
- 交互能力:用户通过界面完成任务。
- 可靠性:规定时间内无故障运行。
- 安全性:保护数据,限制访问,抵御攻击。
- 可维护性:高效修改。
- 灵活性:适应需求/环境变化。
- 无害性:避免危害人身/财产/环境。
- GB/T 16260.1:功能性、可靠性、易用性、效率、维护性、可移植性。
- FURPS+:
- 功能性:特性、功能、安全性。
- 易用性:人性化、帮助、文档。
- 可靠性:稳定性、可恢复性。
- 性能:速度、资源消耗、响应时间。
- 可支持性:可维护性、可测试性、可扩展性。
- +:实现(资源/工具)、接口、操作、包装、授权。
- 软件质量保证(SQA):
- 贯穿软件过程的保护性活动,确保标准、步骤、实践正确采用。
- 使软件过程对管理者可见,通过评审/审计验证合规。
- 任务:
- 审计与评审:检查工作产品、工具、设备是否符合标准。
- 报告:记录并发布结果。
- 处理不符合问题:及时反馈问题至相关人员及高层。
3. 标准
- 认证(ISO/IEC):
- 第三方证实产品/服务符合标准/规范的活动。
- 产品质量认证:依据标准和技术要求,颁发证书/标志。
- 质量体系认证:针对企业质量体系,颁发认证证书。
- 国际标准化组织(ISO):
- 制定国际标准。
- 国家标准(GB):
- 强制性:由国务院行政主管部门起草、审查,国务院批准发布。
- 推荐性:由国务院标准化行政主管部门制定发布。
- 指导性技术文件:为快速发展技术领域提供参考。
- 软件能力成熟度模型(CMM/CMMI):
- CMM:描述软件过程成熟度,1-5级。
- CMMI:能力成熟度模型集成,扩展CMM,监控开发与维护过程。
4. 敏捷
- 定义:
- 相对于“非敏捷”,强调适应性而非预见性。
- 灵活响应客户需求,保持价值、质量、商业规则。
- 敏捷软件开发宣言:
- 价值观:
- 个体和互动 > 流程和工具。
- 工作的软件 > 详尽文档。
- 客户合作 > 合同谈判。
- 响应变化 > 遵循计划。
- 重视左项,但右项仍有价值。
- 价值观:
- 特点:
- 敏捷是一种态度,而非固定过程。
- 包含价值观、原则、实践,提高开发质量与速度,避免过度简化。
- 补充传统方法。
- 敏捷方法:
- 极限编程(XP)、Scrum、看板(Kanban)、透明水晶(Crystal)。
5. 课程整体总结
- 一、软件工程概述:
- 软件:指令、数据、文档。
- 软件危机:开发跟不上需求,维护困难。
- 软件工程:经济获得可靠高效软件的工程化方法。
- 目标:确保质量。
- 三层结构:过程(生命周期活动)、方法(技术指导)、工具(自动化支持)。
- 过程模型:瀑布、增量、螺旋、快速原型、统一过程(RUP)。
- 二、项目计划 & 七、项目管理:
- 度量与估算:代码行(Loc)、功能点(FP)、三点估算、CoCoMO、Putnam。
- 配置管理:管理SCI,控制基线变更。
- 质量保证:SQA审计、报告、问题处理。
- 认证:ISO、GB、CMMI。
- 敏捷:适应变化,强调互动、协作。
- 三、需求分析:
- 需求:业务、用户、功能、非功能。
- 需求工程阶段:计划、范围评审、获取、分析建模、规约、复审。
- 获取方法:沟通、文档、市场调查、原型、QFD、KANO。
- 结构化模型:数据流图(DFD)、实体关系图(ERD)、数据字典(DD)。
- 需求文档(SRS):无歧义、完整、可验证、一致、可修改、可追踪。
- 四、设计:
- 概念:抽象、求精、模块化、信息隐藏、内聚/耦合、复用、重构。
- 架构风格:仓库、黑板、管道过滤器、调用返回、层次、MVC、分布式。
- 详细设计:界面、数据、过程、算法。
- 原则与模式:SOLID(单一职责、开闭、里氏替换、接口隔离、依赖倒置)、GoF 23种设计模式(创建、结构、行为)。
- 五、OOAD & UML:
- OOAD:映射现实世界对象,构建自然模型。
- UML图:
- 用例图:参与者、用例、关系(泛化、扩展、包含)。
- 类图:类、对象、关系(继承、组合、聚合、关联、依赖、实现)。
- 交互图:顺序图(时间顺序)、通信图(结构组织)。
- 状态机图:状态、转移、活动图(控制流)。
- 其他:包图、部署图、构件图、组合结构图、交互纵览图、计时图、外廓图。
- 六、实现:
- 编码:规范命名、结构、注释、格式,追求可读性。
- 测试:
- 目标:发现错误、评估质量。
- 原则:追溯需求、提前计划、Pareto、从小到大、独立第三方。
- 方法:黑盒(等价类、边界值)、白盒(基本路径)。
- 过程:单元、集成、确认、系统。
- 维护:纠错、适应、完善、预防,成本占80%。
- 再工程:重构、逆向工程(推导实现)、再工程(逆向+正向)。
6. 祝福
- 祝逢考必过!