软件工程
1. 需求工程
1.1 需求开发
1.1.1 需求获取
用户访谈、联合讨论会(JRP)、现场观察、原型
1.1.2 需求分析
结构化分析
核心是数据字典
分类:
功能建模(DFD)
数据建模(ER 图)
行为建模(STD)
面向对象分析
用例模型: 用例图
分析模型: 类图
UML
1.1.3 需求定义
严格定义法: 适用于所有需求都能够被预先定义的情况
原型法: 并非所有的需求都能在开发之前被准确说明
1.1.4 需求验证
方法: 需求评审/测试
要求用户参与,签字
1.2 需求管理
1.2.1 变更控制
变更控制委员会(CCB): 项目经理、客户方、开发团队、监理方
版本控制
需求跟踪: 建立与维护"需求-设计-编码-测试"之间的一致性;把需求落实到后续各个步骤
需求状态跟踪
2. 软件设计
2.1 软件架构设计
2.2 结构化设计
概要设计: 确定模块之间的调用关系,关注模块间的接口
详细设计: 模块内的设计,比如确定算法
设计原则:
高内聚,低耦合
多扇入、少扇出
2.3 面向对象设计
类:
- 实体类,对应数据表,如:学生类、课程类等
- 控制类,用于控制用例工作的类,如身份验证器
- 边界类,位于系统与外界的交界处,用于封装在用例内、外流动的信息或数据流,比如窗体、菜单、报表、二维码、打印机、显示器
多态:
不同的对象接收到同一消息产生不同的反应
设计原则:
- 单一职责原则: 设计功能单一的类
- 开放-封闭原则: 对扩展开放,对修改关闭
- 里氏替换原则: 子类可以替换父类
- 依赖倒置原则: 要依赖于抽象,而不是具体实现,要针对接口编程、而不是针对实现编程
- 接口隔离原则: 使用多个专门的接口比使用单一的总接口好
- 组合重用原则: 尽量使用组合,而不是继承关系来达到复用目标
- 迪米特法则(最少知识原则): 一个对象应当对其他对象有尽可能少的了解
2.4 界面设计
- 置于用户控制之下: 允许终端和撤销,不强迫用户
- 减少用户的记忆负担: 直觉型的捷径,现实隐喻
- 保持界面的一致性: 系统内保持一致
3. 测试
3.1 测试方法
静态测试(人工)
- 手工测试: 在不运行代码的情况下,通过审查、走查等方式检查代码和文档的正确性。
- 桌前检查、代码审查、代码走查
动态测试(计算机运行)
-
在运行代码的情况下,通过执行测试用例来验证系统的功能和性能
-
分类:
-
白盒测试: 验证代码的逻辑和结构是否正确,覆盖所有路径和条件
-
测试用例基于代码的内部结构,关注代码的执行路径
-
测试方法
-
控制流测试(语句覆盖、判定覆盖、条件覆盖、判定/条件覆盖、组合覆盖、路径覆盖)
-
数据流测试
-
程序变异测试(错误驱动测试)
-
-
-
黑盒测试(功能测试): 验证系统的功能是否符合需求,不考虑内部结构和实现细节
-
测试用例基于需求规格说明书,关注输入和输出
-
测试方法
-
等价类划分
-
边界值分析
-
错误推测法与因果图分析
-
-
-
灰盒测试: 结合黑盒测试和白盒测试的特点,部分了解系统内部结构
- 测试用例基于部分内部结构和外部功能
-
3.2 测试阶段
-
单元测试,测试计划需在详细测试阶段完成
- 测试内容: 函数或方法、模块测试、模块功能、性能、接口等
- 由开发人员完成
-
集成测试,测试计划需在概要设计阶段完成
-
测试内容: 验证多个模块或组件之间的接口和交互是否正确
-
通常在单元测试之后进行,关注模块间的集成点
-
测试方式
- 一次性组装(风险高)
- 增量式组装(更全面)
- 自顶向下,需要桩模块
- 自底向上,需要驱动模块
-
-
系统测试,测试计划需要在需求分析阶段完成
-
测试内容: 验证整个系统的功能、性能和安全性是否符合需求规格说明
-
在集成测试之后进行,测试整个系统的完整性和一致性。
-
分类
-
负载测试
- 不把系统搞挂的测试,使系统能够在最大的压力下可以正常运行,从而获取系统的指标。
- 不断增加请求压力,直到服务器某个资源项达到饱和(如 CPU 利用率 90%+)或某个指标达到安全临界值(比如监控告警阈值)。负载测试包含并发用户数、持续运行时间、数据量等,其中并发用户数是负载压力的重要指标。
-
压力测试
- 给软件不断加压,强制其在超过安全负载的情况下运行,直到系统崩溃或不能再处理任何请求,观察它可以运行到何种程度,从而发现性能缺陷。
- 它是把系统搞挂的测试
- 以负载测试或者并发测试为依据,给软件不断加压,强制其在极限环境运行,确定系统瓶颈或不能接受的性能点
-
强度测试
- 【系统资源受限】的系统运行下限
- 得到负载测试和压力测试各项指标的临界值
-
容量测试
- 确定系统最大承受量,譬如系统最大用户数,最大存储量,最多处理的数据流量等。
-
-
-
确认测试,测试计划在需求分析阶段完成
- 测试系统与用户的需求是否一致,强调用户参与
- 分类
- 内部确认测试
- α测试/β测试
- 验收测试
3.2 测试阶段
4. 维护
4.1 维护类型
-
更正性维护: 也称为纠错性维护,是指在系统运行过程中发现并修正系统中遗留的错误。这种维护通常在系统发生异常或故障时进行。更正性维护的核心是纠正错误,确保系统能够正常运行
-
适应性维护: 为了使系统适应环境的变化而进行的维护工作。这种维护的核心是环境变化,即当外部环境或内部条件发生变化时,对系统进行相应的修改。例如,硬件升级或操作系统更新时,需要对软件进行适应性调整。
-
预防性维护: 预防性维护是为了提高系统的可靠性和可维护性,主动进行的维护工作。这种维护的核心是预防,即在系统尚能正常运行时,进行必要的调整和改进,以应对未来可能发生的变化。例如,增加通用报表生成功能,以适应未来报表格式的变化。
-
完善性维护: 也称为改善性维护,是为了扩充系统功能和改善性能而进行的修改。这种维护的核心是用户需求,即根据用户的反馈和需求,对系统进行功能扩展和性能优化。例如,增加新的功能模块或提高处理效率。
4.2 遗留系统处置
- 改造: 高水平、高价值,相当于优化
- 继承: 低水平、高价值,继承数据模型和功能模型,系统用新技术重新开发
- 继承: 高水平、低价值,低价值体现为"信息孤岛"
- 淘汰: 低水平、低价值
5. 开发方法
结构化开发方法
- 自顶向下,逐步分解
- 强调整体性、全局性
- 工程化文档化
- 严格分阶段,阶段有成果
面向对象开发方法
- 自底向上开发方法
- 更好的复用性
- 关键在于建立 1 个合理、全面、统一的模型
- 分析设计实现三阶段
- 符合人的思维习惯
面向服务开发方法
- 粗粒度、松耦合、标准化、构件化
- 3 个抽象级别: 操作(低) -> 服务(中) -> 业务流程(高)
原型法
- 用于需求不明确
- 仅用于需求阶段,而不是全流程
- 按功能划分: 水平原型(界面)、垂直原型(复杂算法)
- 按最终结果划分: 抛弃式原型、演化式原型
逆向工程
概念: 从产品反推设计与分析
阶段: 原系统的维护阶段、新系统的需求阶段
层级:
- 实现级: 抽象语法树、符号表、过程的设计
- 结构级: 反应程序分量之间相互依赖关系的信息;如调用图、结构图、程序和数据结构
- 功能级: 程序段功能与程序段之间的关系,如数据与控制流模型
- 领域级: 反应程序分量或程序诸实体与应用领域概念之间对应关系的信息,如实体关系模型、UML 模型
再工程: 在逆向工程所获取的信息的基础上修改或重构已有的系统,产生新系统
净室工程
1.强调数学模型的使用
2.一般使用验证而非测试
6. 开发模型
瀑布模型
特点:
- 阶段清晰,前一阶段错误会延续到下一阶段
- 各阶段有产物
- 自顶向下,逐步分解求精
- 适用于需求明确的场景
原型
特点:
现构建简易系统,适用于需求不明确的场景,用于获取需求
分类:
- 快速原型: 获取需求之后抛弃原型
- 演化模型: 将原型演化为最终软件产品
螺旋模型
-
以原型为基础,加上瀑布模式,迭代
-
引入了风险分析
-
适用于庞大、复杂并具有高风险的系统
阶段:
- 目标设定
- 风险分析
- 开发和有效性验证
- 评审(客户评价)
基于构件的开发模型(CBSD)
阶段:
-
需求分析和定义
-
软件架构设计
-
构件库建立
-
应用软件构建
-
测试和发布
标准:
- COM/DCOM
- Corba
- EJB
敏捷开发
敏捷宣言:
- 个体和交互胜过过程和工具
- 可工作的软件胜过大量的文档
- 客户合作胜过合同谈判
- 响应变化胜过遵循计划
特点:
小步快跑,快速迭代,适合于小型项目(实际工作中可将大型项目拆分为小项目)
方法:
极限编程(XP): 核心是沟通、简单、反馈和勇气,提倡测试先行
自适应开发(ASD): 核心是三个非线性的、重复的开发阶段(猜测、合作和学习)
水晶方法(Crystal): 不同类型的项目需要不同的方法,强调特异性
SCRUM: 敏捷项目管理
特征驱动开发(FDD): 编程开发人员分为首席程序员和“类”程序员
精益软件开发(Lean)
开放式源码: 开发人员在地域上分布很广
动态系统开发(DSDM): 强调以业务为核心、快速而有效地进行系统开发
统一过程(UP/RUP)
特点:
- 用例驱动
- 以架构为中心
- 迭代与增量
阶段划分
- 初始: 建议业务模型并明确项目边界
- 精化: 完成架构设计
- 构建: 开发剩余构件、将构件集成为产品并测试
- 移交: 确保软件对最终用户是可用的
快速应用开发(RAD)
瀑布模型+CBSD
适用于模块化程度高
7. UML
事物
- 结构事物: 静态部分,包括类、接口、协作、用例、活动类、构件、节点
- 行为事物: 动态部分,包括消息、动作次序、连接
- 分组事物: 组织部分,包括包、构件
- 注释事物: 解释部分
关系
类关系
- 依赖: 依赖是两个事物之间的语义关系,其中 1 个事物变化会影响到另 1 个事物的语义
- 关联: 描述一组对象之间结构关系,分为聚合关系(整体与部分的生命周期不同),组合关系(整体与部分生命周期相同)
- 泛化: 一般与特殊的关系
- 实现: 类实现接口,接口指定了由实现类保证执行的契约
用例关系
- 包含:
- 扩展:
- 泛化: 特殊与一般的关系
静态图/结构图
- 类图: 描述一组类、接口、协作和它们之间的关系
- 对象图: 描述一组对象及它们之间的关系
- 包图: 描述由模型分解而成的组织单元,及其之间的依赖关系
- 构件图: 描述一个封装的类和它的接口、端口及构件与连接件的结构图
- 组合结构图: 描述结构化类的内部结构
- 制品图: 描述计算机中一个系统的物理结构、制品包括文件、数据库等
- 部署图: 软件与硬件的映射关系
动态图/行为图
- 用例图: 描述一组用例、参与者及它们之间的关系,展示外部参与者与系统的交互
- 交互图
- 顺序图: 强调消息的时间次序
- 通信图: 强调收发消息的对象或参与者的组织结构
- 定时图: 强调消息跨越不同的对象或参与者的实际时间
- 交互概览图
- 状态图: 描述一个状态机,它由状态、转移、事件和活动组成
- 活动图: 类似于流程图,强调交互行为,能表示并发