软件工程
00:00
软件工程:需求分析、设计模式、敏捷开发、测试策略与项目管理
1. 软件工程概述
1.1 软件危机
1968年 NATO 会议提出”软件危机”概念:
- 软件项目经常超时、超预算
- 软件质量低劣、维护困难
- 缺乏系统化的开发方法
1.2 软件生命周期
需求分析 → 系统设计 → 详细设计 → 编码实现 → 测试 → 部署 → 维护
1.3 软件过程模型
| 模型 | 特点 | 适用场景 |
|---|---|---|
| 瀑布模型 | 线性顺序,文档驱动 | 需求明确的项目 |
| 增量模型 | 分批交付,逐步完善 | 大型项目 |
| 螺旋模型 | 风险驱动,迭代 | 高风险项目 |
| 喷泉模型 | 面向对象,迭代 | OO项目 |
| 敏捷模型 | 快速迭代,拥抱变化 | 需求变化频繁 |
2. 需求工程
2.1 需求分类
- 功能需求:系统应该做什么
- 非功能需求:系统应该做到什么程度
- 性能需求:响应时间、吞吐量
- 安全需求:认证、授权、加密
- 可靠性需求:MTBF、MTTR
- 可用性需求:并发用户数
2.2 需求获取方法
| 方法 | 优点 | 缺点 |
|---|---|---|
| 访谈 | 深入了解 | 耗时 |
| 问卷 | 覆盖面广 | 深度不足 |
| 观察 | 真实场景 | 受霍桑效应影响 |
| 原型 | 直观验证 | 可能偏离实际 |
2.3 用例建模
用例图要素:
- 参与者(Actor):与系统交互的外部实体
- 用例(Use Case):系统提供的功能
- 关系:包含(include)、扩展(extend)、泛化(generalization)
2.4 需求规格说明
SRS(Software Requirements Specification)应满足:
- 完整性:覆盖所有需求
- 一致性:需求之间不矛盾
- 可验证性:每条需求可测试
- 可追踪性:需求可追溯到来源
3. 软件设计
3.1 设计原则(SOLID)
| 原则 | 含义 |
|---|---|
| 单一职责(SRP) | 一个类只有一个变化原因 |
| 开闭原则(OCP) | 对扩展开放,对修改关闭 |
| 里氏替换(LSP) | 子类可替换父类 |
| 接口隔离(ISP) | 客户端不应依赖不需要的接口 |
| 依赖反转(DIP) | 依赖抽象而非具体实现 |
3.2 设计模式分类
创建型模式:
| 模式 | 意图 |
|---|---|
| 单例(Singleton) | 确保类只有一个实例 |
| 工厂方法(Factory Method) | 由子类决定创建哪个对象 |
| 抽象工厂(Abstract Factory) | 创建一族相关对象 |
| 建造者(Builder) | 分步骤构建复杂对象 |
| 原型(Prototype) | 通过克隆创建对象 |
结构型模式:
| 模式 | 意图 |
|---|---|
| 适配器(Adapter) | 接口转换 |
| 桥接(Bridge) | 分离抽象与实现 |
| 组合(Composite) | 树形结构统一处理 |
| 装饰器(Decorator) | 动态添加职责 |
| 外观(Facade) | 简化子系统接口 |
| 代理(Proxy) | 控制对象访问 |
行为型模式:
| 模式 | 意图 |
|---|---|
| 观察者(Observer) | 一对多依赖通知 |
| 策略(Strategy) | 算法族可互换 |
| 模板方法(Template Method) | 定义算法骨架 |
| 命令(Command) | 请求参数化 |
| 迭代器(Iterator) | 顺序访问集合 |
| 状态(State) | 状态驱动行为 |
3.3 架构模式
| 模式 | 特点 | 适用场景 |
|---|---|---|
| 分层架构 | 关注点分离 | 企业应用 |
| MVC | 模型-视图-控制器 | Web应用 |
| 微服务 | 独立部署、松耦合 | 大型系统 |
| 事件驱动 | 异步消息通信 | 实时系统 |
| CQRS | 读写分离 | 高并发系统 |
4. 敏捷开发
4.1 敏捷宣言
- 个体和互动 高于 流程和工具
- 工作的软件 高于 详尽的文档
- 客户合作 高于 合同谈判
- 响应变化 高于 遵循计划
4.2 Scrum 框架
| 角色 | 职责 |
|---|---|
| Product Owner | 管理产品待办列表 |
| Scrum Master | 促进 Scrum 实践 |
| Development Team | 自组织开发 |
| 事件 | 时长 | 目的 |
|---|---|---|
| Sprint | 1~4周 | 迭代开发 |
| Sprint计划 | 4h | 确定Sprint目标 |
| 每日站会 | 15min | 同步进展 |
| Sprint评审 | 4h | 展示成果 |
| Sprint回顾 | 3h | 持续改进 |
4.3 看板方法
- 可视化工作流
- 限制在制品(WIP)
- 管理流动
- 显式化策略
- 实施反馈环
4.4 极限编程(XP)
| 实践 | 说明 |
|---|---|
| 结对编程 | 两人一台电脑 |
| 测试驱动开发 | 先写测试再写代码 |
| 持续集成 | 频繁集成到主干 |
| 重构 | 改善代码结构 |
| 简单设计 | 只实现当前需要 |
5. 软件测试
5.1 测试层次
| 层次 | 目标 | 方法 |
|---|---|---|
| 单元测试 | 验证模块功能 | 白盒测试 |
| 集成测试 | 验证模块间接口 | 灰盒测试 |
| 系统测试 | 验证系统功能 | 黑盒测试 |
| 验收测试 | 验证用户需求 | 黑盒测试 |
5.2 白盒测试
语句覆盖:每条语句至少执行一次。
分支覆盖:每个分支至少执行一次。
路径覆盖:每条路径至少执行一次。
条件覆盖:每个条件的真假至少各取一次。
覆盖强度:路径 > 分支 > 语句
5.3 黑盒测试
等价类划分:将输入分为有效和无效等价类。
边界值分析:测试边界附近的值。
因果图:分析输入条件之间的逻辑关系。
正交实验法:减少测试用例数量。
5.4 测试金字塔
/ E2E测试 \ 少量,慢
/ 集成测试 \ 适量
/ 单元测试 \ 大量,快
5.5 度量指标
6. 软件度量
6.1 面向规模度量
6.2 面向对象度量(CK度量集)
| 度量 | 含义 |
|---|---|
| WMC | 类的方法权重总和 |
| DIT | 继承深度 |
| NOC | 子类数量 |
| CBO | 耦合度 |
| RFC | 方法调用数 |
| LCOM | 方法内聚度 |
6.3 功能点分析
其中 UFP 为未调整功能点,VAF 为价值调整因子。
7. 软件维护
7.1 维护类型
| 类型 | 占比 | 说明 |
|---|---|---|
| 完善性维护 | 50%~66% | 增强功能 |
| 适应性维护 | 18%~25% | 适应环境变化 |
| 纠错性维护 | 17%~21% | 修复缺陷 |
| 预防性维护 | 4% | 提高可维护性 |
7.2 技术债务
技术债务是选择快速方案而非更好方案所产生的额外工作:
管理策略:定期重构、代码审查、自动化测试。