跳到主要内容

软件工程

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 面向对象设计​

类:

  1. 实体类,对应数据表,如:学生类、课程类等
  2. 控制类,用于控制用例工作的类,如身份验证器
  3. 边界类,位于系统与外界的交界处,用于封装在用例内、外流动的信息或数据流,比如窗体、菜单、报表、二维码、打印机、显示器

多态:

不同的对象接收到同一消息产生不同的反应

设计原则:

  1. 单一职责原则: 设计功能单一的类
  2. 开放-封闭原则: 对扩展开放,对修改关闭
  3. 里氏替换原则: 子类可以替换父类
  4. 依赖倒置原则: 要依赖于抽象,而不是具体实现,要针对接口编程、而不是针对实现编程
  5. 接口隔离原则: 使用多个专门的接口比使用单一的总接口好
  6. 组合重用原则: 尽量使用组合,而不是继承关系来达到复用目标
  7. 迪米特法则(最少知识原则): 一个对象应当对其他对象有尽可能少的了解

2.4 界面设计​

  1. 置于用户控制之下: 允许终端和撤销,不强迫用户
  2. 减少用户的记忆负担: 直觉型的捷径,现实隐喻
  3. 保持界面的一致性: 系统内保持一致

3. 测试​

3.1 测试方法​

静态测试(人工)​

  • 手工测试: 在不运行代码的情况下,通过审查、走查等方式检查代码和文档的正确性。
  • 桌前检查、代码审查、代码走查

动态测试(计算机运行)​

  • 在运行代码的情况下,通过执行测试用例来验证系统的功能和性能

  • 分类:

    • 白盒测试: 验证代码的逻辑和结构是否正确,覆盖所有路径和条件

      • 测试用例基于代码的内部结构,关注代码的执行路径

      • 测试方法

        • 控制流测试(语句覆盖、判定覆盖、条件覆盖、判定/条件覆盖、组合覆盖、路径覆盖)

        • 数据流测试

        • 程序变异测试(错误驱动测试)

    • 黑盒测试(功能测试): 验证系统的功能是否符合需求,不考虑内部结构和实现细节

      • 测试用例基于需求规格说明书,关注输入和输出

      • 测试方法

        • 等价类划分

        • 边界值分析

        • 错误推测法与因果图分析

    • 灰盒测试: 结合黑盒测试和白盒测试的特点,部分了解系统内部结构

      • 测试用例基于部分内部结构和外部功能

3.2 测试阶段​

  • 单元测试,测试计划需在详细测试阶段完成

    • 测试内容: 函数或方法、模块测试、模块功能、性能、接口等
    • 由开发人员完成
  • 集成测试,测试计划需在概要设计阶段完成

    • 测试内容: 验证多个模块或组件之间的接口和交互是否正确

    • 通常在单元测试之后进行,关注模块间的集成点

    • 测试方式

      • 一次性组装(风险高)
      • 增量式组装(更全面)
        • 自顶向下,需要桩模块
        • 自底向上,需要驱动模块
  • 系统测试,测试计划需要在需求分析阶段完成

    • 测试内容: 验证整个系统的功能、性能和安全性是否符合需求规格说明

    • 在集成测试之后进行,测试整个系统的完整性和一致性。

    • 分类

      • 负载测试

        • 不把系统搞挂的测试,使系统能够在最大的压力下可以正常运行,从而获取系统的指标。
        • 不断增加请求压力,直到服务器某个资源项达到饱和(如 CPU 利用率 90%+)或某个指标达到安全临界值(比如监控告警阈值)。负载测试包含并发用户数、持续运行时间、数据量等,其中并发用户数是负载压力的重要指标。
      • 压力测试

        • 给软件不断加压,强制其在超过安全负载的情况下运行,直到系统崩溃或不能再处理任何请求,观察它可以运行到何种程度,从而发现性能缺陷。
        • 它是把系统搞挂的测试
        • 以负载测试或者并发测试为依据,给软件不断加压,强制其在极限环境运行,确定系统瓶颈或不能接受的性能点
      • 强度测试

        • 【系统资源受限】的系统运行下限
        • 得到负载测试和压力测试各项指标的临界值
      • 容量测试

        • 确定系统最大承受量,譬如系统最大用户数,最大存储量,最多处理的数据流量等。
  • 确认测试,测试计划在需求分析阶段完成

    • 测试系统与用户的需求是否一致,强调用户参与
    • 分类
      • 内部确认测试
      • α测试/β测试
      • 验收测试

3.2 测试阶段​

4. 维护​

4.1 维护类型​

  • 更正性维护: 也称为纠错性维护,是指在系统运行过程中发现并修正系统中遗留的错误。这种维护通常在系统发生异常或故障时进行。更正性维护的核心是纠正错误,确保系统能够正常运行

  • 适应性维护: 为了使系统适应环境的变化而进行的维护工作。这种维护的核心是环境变化,即当外部环境或内部条件发生变化时,对系统进行相应的修改。例如,硬件升级或操作系统更新时,需要对软件进行适应性调整。

  • 预防性维护: 预防性维护是为了提高系统的可靠性和可维护性,主动进行的维护工作。这种维护的核心是预防,即在系统尚能正常运行时,进行必要的调整和改进,以应对未来可能发生的变化。例如,增加通用报表生成功能,以适应未来报表格式的变化。

  • 完善性维护: 也称为改善性维护,是为了扩充系统功能和改善性能而进行的修改。这种维护的核心是用户需求,即根据用户的反馈和需求,对系统进行功能扩展和性能优化。例如,增加新的功能模块或提高处理效率。

4.2 遗留系统处置​

  • 改造: 高水平、高价值,相当于优化
  • 继承: 低水平、高价值,继承数据模型和功能模型,系统用新技术重新开发
  • 继承: 高水平、低价值,低价值体现为"信息孤岛"
  • 淘汰: 低水平、低价值

5. 开发方法​

结构化开发方法​

  1. 自顶向下,逐步分解
  2. 强调整体性、全局性
  3. 工程化文档化
  4. 严格分阶段,阶段有成果

面向对象开发方法​

  1. 自底向上开发方法
  2. 更好的复用性
  3. 关键在于建立 1 个合理、全面、统一的模型
  4. 分析设计实现三阶段
  5. 符合人的思维习惯

面向服务开发方法​

  1. 粗粒度、松耦合、标准化、构件化
  2. 3 个抽象级别: 操作(低) -> 服务(中) -> 业务流程(高)

原型法​

  1. 用于需求不明确
  2. 仅用于需求阶段,而不是全流程
  3. 按功能划分: 水平原型(界面)、垂直原型(复杂算法)
  4. 按最终结果划分: 抛弃式原型、演化式原型

逆向工程​

概念: 从产品反推设计与分析

阶段: 原系统的维护阶段、新系统的需求阶段

层级:

  1. 实现级: 抽象语法树、符号表、过程的设计
  2. 结构级: 反应程序分量之间相互依赖关系的信息;如调用图、结构图、程序和数据结构
  3. 功能级: 程序段功能与程序段之间的关系,如数据与控制流模型
  4. 领域级: 反应程序分量或程序诸实体与应用领域概念之间对应关系的信息,如实体关系模型、UML 模型

再工程: 在逆向工程所获取的信息的基础上修改或重构已有的系统,产生新系统

净室工程​

1.强调数学模型的使用

2.一般使用验证而非测试

6. 开发模型​

瀑布模型​

特点:

  1. 阶段清晰,前一阶段错误会延续到下一阶段
  2. 各阶段有产物
  3. 自顶向下,逐步分解求精
  4. 适用于需求明确的场景

原型​

特点:

现构建简易系统,适用于需求不明确的场景,用于获取需求

分类:

  1. 快速原型: 获取需求之后抛弃原型
  2. 演化模型: 将原型演化为最终软件产品

螺旋模型​

  1. 以原型为基础,加上瀑布模式,迭代

  2. 引入了风险分析

  3. 适用于庞大、复杂并具有高风险的系统

    阶段:

    1. 目标设定
    2. 风险分析
    3. 开发和有效性验证
    4. 评审(客户评价)

基于构件的开发模型(CBSD)​

阶段:

  1. 需求分析和定义

  2. 软件架构设计

  3. 构件库建立

  4. 应用软件构建

  5. 测试和发布

    标准:

    1. COM/DCOM
    2. Corba
    3. EJB

敏捷开发​

敏捷宣言:

  1. 个体和交互胜过过程和工具
  2. 可工作的软件胜过大量的文档
  3. 客户合作胜过合同谈判
  4. 响应变化胜过遵循计划

特点:

小步快跑,快速迭代,适合于小型项目(实际工作中可将大型项目拆分为小项目)

方法:

极限编程(XP): 核心是沟通、简单、反馈和勇气,提倡测试先行

自适应开发(ASD): 核心是三个非线性的、重复的开发阶段(猜测、合作和学习)

水晶方法(Crystal): 不同类型的项目需要不同的方法,强调特异性

SCRUM: 敏捷项目管理

特征驱动开发(FDD): 编程开发人员分为首席程序员和“类”程序员

精益软件开发(Lean)

开放式源码: 开发人员在地域上分布很广

动态系统开发(DSDM): 强调以业务为核心、快速而有效地进行系统开发

统一过程(UP/RUP)​

特点:

  1. 用例驱动
  2. 以架构为中心
  3. 迭代与增量

阶段划分

  1. 初始: 建议业务模型并明确项目边界
  2. 精化: 完成架构设计
  3. 构建: 开发剩余构件、将构件集成为产品并测试
  4. 移交: 确保软件对最终用户是可用的

快速应用开发(RAD)​

瀑布模型+CBSD

适用于模块化程度高

7. UML​

事物​

  • 结构事物: 静态部分,包括类、接口、协作、用例、活动类、构件、节点
  • 行为事物: 动态部分,包括消息、动作次序、连接
  • 分组事物: 组织部分,包括包、构件
  • 注释事物: 解释部分

关系​

类关系​

  • 依赖: 依赖是两个事物之间的语义关系,其中 1 个事物变化会影响到另 1 个事物的语义
  • 关联: 描述一组对象之间结构关系,分为聚合关系(整体与部分的生命周期不同),组合关系(整体与部分生命周期相同)
  • 泛化: 一般与特殊的关系
  • 实现: 类实现接口,接口指定了由实现类保证执行的契约

用例关系​

  • 包含:
  • 扩展:
  • 泛化: 特殊与一般的关系

静态图/结构图​

  • 类图: 描述一组类、接口、协作和它们之间的关系
  • 对象图: 描述一组对象及它们之间的关系
  • 包图: 描述由模型分解而成的组织单元,及其之间的依赖关系
  • 构件图: 描述一个封装的类和它的接口、端口及构件与连接件的结构图
  • 组合结构图: 描述结构化类的内部结构
  • 制品图: 描述计算机中一个系统的物理结构、制品包括文件、数据库等
  • 部署图: 软件与硬件的映射关系

动态图/行为图​

  • 用例图: 描述一组用例、参与者及它们之间的关系,展示外部参与者与系统的交互
  • 交互图
    • 顺序图: 强调消息的时间次序
    • 通信图: 强调收发消息的对象或参与者的组织结构
    • 定时图: 强调消息跨越不同的对象或参与者的实际时间
    • 交互概览图
  • 状态图: 描述一个状态机,它由状态、转移、事件和活动组成
  • 活动图: 类似于流程图,强调交互行为,能表示并发

8. 设计模式​