需求分析概述与面向对象建模

需求分析的根本任务

需求分析承担着两项核心任务:建立分析模型创建解决方案。这一阶段是连接用户需求与软件实现的关键桥梁。

建立分析模型

模型是对事物的抽象,帮助我们在创建系统之前更好地理解它。建模的核心方法包括:

  • 抽象(Abstraction):聚焦重要信息,忽略次要内容,将认知保持在适当层次
  • 分解(Decomposition):「分而治之」,将复杂问题拆解为更易管理的子问题
  • 投影(Projection):从多个视角观察同一系统,即多视点方法

三种模型的层次关系

  • 业务模型:使用问题域概念,非形式化,便于用户理解但不够精确
  • 分析模型:介于两者之间,半形式化,既能被用户理解又具备一定严谨性
  • 计算模型:使用软件构建单位,形式化,精确但用户难以理解

需求分析阶段主要建立的是分析模型——它采用计算模型的组元形式,但以业务模型的方式表现。

创建解决方案

解决方案的创建是一个创造性过程,受到多重因素影响:

外因 内因
问题背景 技术背景
需求本身 知识背景
可用技术与方法 经验与习惯

最终的解决方案往往来源于这些因素交织产生的创造性灵感

需求分析的活动

需求分析包含三个主要活动**:需求细化**、确定优先级需求协商

需求细化

需求细化的目标是将用户视角的需求转化为技术视角的系统需求:

  • 明确用户需求的隐含因素
  • 将业务语言转化为技术语言
  • 将高层次非功能需求分解为具体约束
  • 发现并补充细节需求

每条细化后的需求应记录以下属性:

属性 说明
标识符(ID) 唯一标识
源头(Source) 可追溯的需求来源
理由(Rational) 需求被提出的目的
优先级(Priority) 重要程度
成本(Cost) 预估实现代价
风险(Risk) 实现过程中的潜在风险
可变性(Volatility) 未来变更的可能性

确定需求优先级

常用的优先级确定方法:

累计投票法:涉众对需求进行投票,票数反映优先级。

区域划分法:基于「重要性」与「紧急性」两个维度划分四象限:

---
config:
  quadrantChart:
    chartWidth: 600
    chartHeight: 500
    titlePadding: 15
    titleFontSize: 22
    quadrantPadding: 8
    quadrantTextTopPadding: 10
    quadrantLabelFontSize: 14
    quadrantInternalBorderStrokeWidth: 1
    quadrantExternalBorderStrokeWidth: 2
    xAxisLabelPadding: 8
    xAxisLabelFontSize: 14
    xAxisPosition: "bottom"
    yAxisLabelPadding: 8
    yAxisLabelFontSize: 14
    yAxisPosition: "left"
    pointTextPadding: 6
    pointLabelFontSize: 12
    pointRadius: 6
  themeVariables:
    quadrant1Fill: "#FF6B6B"
    quadrant2Fill: "#4ECDC4"
    quadrant3Fill: "#FFD166"
    quadrant4Fill: "#06D6A0"
    quadrant1TextFill: "#FFFFFF"
    quadrant2TextFill: "#FFFFFF"
    quadrant3TextFill: "#333333"
    quadrant4TextFill: "#FFFFFF"
    quadrantPointFill: "#1A1A2E"
    quadrantPointTextFill: "#1A1A2E"
    quadrantXAxisTextFill: "#333333"
    quadrantYAxisTextFill: "#333333"
    quadrantInternalBorderStrokeFill: "#E0E0E0"
    quadrantExternalBorderStrokeFill: "#333333"
    quadrantTitleFill: "#1A1A2E"
---
quadrantChart
    title 需求优先级矩阵
    x-axis "低紧急性" --> "高紧急性"
    y-axis "低重要性" --> "高重要性"
    quadrant-1 "高优先级(紧急且重要)"
    quadrant-2 "中优先级(重要不紧急)"
    quadrant-3 "低优先级(不重要不紧急)"
    quadrant-4 "中优先级(紧急不重要)"
    "关键缺陷修复": [0.85, 0.85]
    "核心功能迭代": [0.25, 0.80]
    "界面美化": [0.20, 0.25]
    "临时支持请求": [0.75, 0.30]
    "安全漏洞": [0.90, 0.90]
    "技术债务": [0.15, 0.60]
    "文档更新": [0.30, 0.40]

Top-N 法:选取优先级最高的 N 个需求,N 的取值受实现代价总和约束。

数据量化法:通过公式计算优先级:

优先级=价值成本×成本权值+风险×风险权值\text{优先级} = \frac{\text{价值}}{\text{成本} \times \text{成本权值} + \text{风险} \times \text{风险权值}}

用户故事地图:基于延迟成本进行判断——延迟成本相同时短任务优先,工作量相同时高延迟成本优先。

需求协商

当需求存在冲突时,需要通过协商达成一致:

  1. 明确冲突的因素,避免情绪化
  2. 明确冲突的解决空间
  3. 确定最佳解决方案,实现多方共赢

需求分析技术的演进

---
config:
  theme: base
  themeVariables:
    # 1950's 传统分析 - 复古棕色
    cScale0: "#8B7355"
    cScaleLabel0: "#FFFFFF"
    # 1970's 结构化分析 - 科技蓝色
    cScale1: "#2E5A88"
    cScaleLabel1: "#FFFFFF"
    # 1980's 信息工程 - 数据绿色
    cScale2: "#4A7C59"
    cScaleLabel2: "#FFFFFF"
    # 1990's 面向对象 - 现代紫色
    cScale3: "#6A4C93"
    cScaleLabel3: "#FFFFFF"
    # 时间线样式
    timelineFontSize: "16px"
    timelineColor: "#333333"
    timelineLineColor: "#CCCCCC"
---
timeline
    title 系统分析方法演进历史
    
    section 1950's
        传统分析
            : 依赖个体才智
            : 无结构、不可重复
            : 风格:非正式、个人化
    
    section 1970's
        结构化分析
            : 数据流图(DFD)
            : 实体关系图(ERD)
            : 状态转移图
            : 风格:流程化、结构化
    
    section 1980's
        信息工程
            : 以数据为中心
            : ERD 为核心
            : 风格:数据驱动、集成化
    
    section 1990's
        面向对象分析
            : UML 统一建模语言
            : 类图、用例图、交互图
            : 风格:对象化、标准化

面向对象分析

核心思想

面向对象思想源于对现实世界复杂系统的观察:

  • 复杂系统由简单部分组合而成,组合过程具有层次性
  • 每个最小部分独立负责一系列相关任务
  • 组合内部各部分的关系比内外部关系更紧密
  • 各部分通过一致的接口进行组合

映射到软件世界:

  • 计算实体:对象
  • 层次关系:继承、关联、聚合、组合
  • 组合接口:对象暴露的公共接口

UML 建模体系

UML 为面向对象分析提供了完整的建模工具集:

模型类型 主要图形 用途
用例模型 用例图 描述系统功能与参与者
对象模型 类图/领域模型 描述系统静态结构
行为模型 顺序图、状态图、活动图 描述系统动态行为

对象模型

对象的基本概念

对象是在应用中具有明确角色的独立可确认实体,包含三个要素:

  • 标识:唯一标识自己
  • 状态:对象的属性及其取值
  • 行为:对象响应消息或状态变化时采取的行动

常见的对象来源:

  • 与系统交互的外部实体(人、设备、其他系统)
  • 问题域中的事物(报表、信号)
  • 系统上下文中的事件(控制行为、资源变化)
  • 用户扮演的角色(管理员、普通用户)
  • 相关的组织单位(部门、团队)
  • 问题发生的地点(车间、办公室)

不是对象的事物

  • 无法界定的事物
  • 纯粹的值(如单独的数字)
  • 纯粹的行为(无状态支撑)

类与分类

是共享相同属性和行为的对象集合,为所属对象提供:

  • 接口(Interface):对外的统一协议
  • 实现(Implementation):生成机制和行为模式

分类的两种驱动方式:

方式 理论基础 特点
数据驱动 经典分类理论 具有相同属性的对象归为一类
职责驱动 概念聚类 依据相似性而非完全相同性分类

关联

关联表示类之间的语义联系,是对对象实例间潜在关系的描述。

关联的表示要素:

  • 关联名称与方向
  • 角色名
  • 多重性(基数)
  • 可见性
  • 限定符

特殊的关联类型:

  • 聚合:整体与部分的关系,部分可独立存在
  • 组合:更强的整体-部分关系,部分不能独立存在

领域模型

领域模型是需求分析阶段的核心产物,其特点:

  • 类多为概念类,代表现实世界事物
  • 关联通常不标记方向和可见性
  • 只显示重要属性,不约束类型
  • 不显式标记方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
┌─────────────┐         ┌─────────────┐
│ Sale │ 1 * │SalesLineItem│
├─────────────┤─────────├─────────────┤
│ date │ │ quantity │
│ time │ └─────────────┘
└─────────────┘ │
│ 1 │ *
│ │
▼ 0..1 ▼ 1
┌─────────────┐ ┌─────────────┐
│ Payment │ │ Item │
├─────────────┤ └─────────────┘
│ amount │
└─────────────┘
classDiagram
    class Sale {
        date
        time
    }
    
    class SalesLineItem {
        quantity
    }
    
    class Payment {
        amount
    }
    
    class Item
    
    Sale "1" -- "*" SalesLineItem : contains
    Sale "0..1" -- "1" Payment : paid by
    SalesLineItem "*" -- "1" Item : records

领域模型建模步骤

  1. 发现候选对象

    • 概念类分类列表法:按预定义分类(人、地点、事物、事件等)查找
    • 名词分析法:从文本中提取名词和名词短语
  2. 判定结果类

    • 既有状态又有行为 → 独立对象
    • 只有状态无行为 → 考虑作为属性
    • 只有行为无状态 → 可能存在需求遗漏
  3. 建立关联:保证协作所需的可见性,适度使用问题域关联

  4. 添加重要属性:协作的条件、输入、结果或过程记录

行为模型:顺序图

顺序图基础

顺序图以一组对象为中心,描述特定上下文中对象间的消息交换,通常对应单个用例的典型场景。

基本元素:

  • 对象:带生命线的矩形
  • 消息:对象间的交互(同步、异步、返回)
  • 激活态:对象执行操作的时间段
  • 创建/销毁:对象的生命周期事件

系统顺序图

将整个系统视为黑箱,强调外部参与者与系统的交互:

sequenceDiagram
    participant 收银员
    participant 系统

    收银员->>系统: 开始新的销售处理
    loop 还有下一项
        收银员->>系统: 输入物品项
        系统-->>收银员: 物品描述、价格、总价
    end
    收银员->>系统: 结束销售处理
    系统-->>收银员: 总价

组合片段

用于表达复杂的控制逻辑:

片段类型 用途
opt 可选执行(单一条件)
alt 多分支选择
loop 循环执行
break 中断序列
par 并行执行
ref 引用其他图

建模步骤

  1. 确定上下文环境
  2. 找出参与交互的对象
  3. 建立交互图框架(对象平行排列,添加生命线)
  4. 添加消息,描述交互行为和顺序
  5. 为分支和异常场景添加组合片段

行为模型:状态图

状态机理论

状态机理论的核心观点:

  • 系统总是处于某一状态中,且同一时刻只能处于一种状态
  • 没有外部事件触发时,系统保持当前状态
  • 有效触发事件发生时,系统从一种状态转移到另一种状态

有限状态机的形式化定义

有限自动机是一个五元组 (Q,Σ,δ,q0,F)(Q, \Sigma, \delta, q_0, F)

  • QQ:有限状态集
  • Σ\Sigma:有限输入字母表
  • δ:Q×ΣQ\delta: Q \times \Sigma \rightarrow Q:转移函数
  • q0Qq_0 \in Q:初始状态
  • FQF \subseteq Q:接受状态集

状态图元素

  • 状态:系统的稳定配置
  • 转换:状态间的迁移
  • 事件:触发转换的外部刺激
  • 监护条件:转换发生的前提条件
  • 行为:转换时执行的动作

高级特性:

  • 组合状态:包含子状态的复合状态
  • 并发状态:同时处于多个正交状态
  • 历史状态:记忆上次离开时的子状态

建模步骤

  1. 确定状态主体(类、用例或整个系统)
  2. 识别所有状态,标记初始和结束状态
  3. 建立状态转换,明确触发事件和监护条件
  4. 补充详细信息(入口/出口动作、内部活动等)

通过状态图发现需求缺陷

  • 无法进入或无法跳出的状态 → 行为缺失
  • 转移路线不确定 → 监护条件数据缺失或行为需细化
  • 应有的转移或状态未体现 → 需求内容需修正

对象约束语言 OCL

OCL(Object Constraint Language)是一种无副作用的规约语言,用于丰富 UML 模型的语义。

OCL 的定位

  • 以表达式方式定义对模型元素的约束
  • 不修改任何模型元素的表述
  • 是建模语言而非编程语言,注重简洁性和抽象性

主要应用

不变量(Invariant):类元需要始终保持为真的约束

1
2
3
context Flight
inv: duration < 4
inv: origin <> destination

前置条件与后置条件:操作执行前后必须满足的约束

1
2
3
context LoyaltyAccount::burn(i: Integer)
pre: points >= i and i >= 0
post: points = points@pre - i

监护条件:状态转移发生的前提条件

[i > 0]  -- 只有当 i > 0 时才进行转移

操作契约示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
操作:enterItem(ItemID, quantity)
引用:销售处理

前置条件:
- 有一个销售 si 正在进行
- 有一个物品项列表 sli 存在
- si 和 sli 建立了关联
- quantity 介于 [Minimum...Maximum]
- ItemID 可以和某个物品描述实例关联

后置条件:
- 创建了一个商品实例 spi
- spi 和 sli 建立了关联
- spi.quantity 被置为参数 quantity
- spi.itemID 被置为参数 itemID

CRC 方法

CRC(Candidates, Responsibilities, Collaborators)是处理复杂系统时进行面向对象分析的有效手段。

CRC 卡结构

graph LR
    subgraph "CRC 卡结构"
        A["候选对象名称"] --> B["职责 Responsibilities"]
        A --> C["协作者 Collaborators"]
        
        B --> D["• 对象执行的行为<br/>• 对象维护的状态"]
        C --> E["• 需要协作的对象"]
    end
    
    style A fill:#4a6fa5,stroke:#333,stroke-width:2px,color:#fff
    style B fill:#6d9eeb,stroke:#333,stroke-width:1px,color:#fff
    style C fill:#6d9eeb,stroke:#333,stroke-width:1px,color:#fff
    style D fill:#e6f2ff,stroke:#4a6fa5,stroke-width:1px
    style E fill:#e6f2ff,stroke:#4a6fa5,stroke-width:1px

CRC 方法流程

flowchart LR
    A[🎯 确定主题] 
    B[🔍 识别候选对象<br/>建立CRC卡]
    C[📋 发现系统职责]
    D[⚖️ 分配职责到对象]
    E[🤝 建立对象协作关系]
    F[✨ 细化CRC卡]
    G[🚀 基于CRC卡的设计]
    
    A -->|开始分析| B
    B -->|识别对象| C
    C -->|明确职责| D
    D -->|职责分配| E
    E -->|建立关系| F
    F -->|迭代优化| G
    
    style A fill:#ff6b6b,stroke:#333,stroke-width:2px,color:#fff
    style B fill:#4ecdc4,stroke:#333,stroke-width:2px,color:#fff
    style C fill:#45b7d1,stroke:#333,stroke-width:2px,color:#fff
    style D fill:#96ceb4,stroke:#333,stroke-width:2px,color:#fff
    style E fill:#feca57,stroke:#333,stroke-width:2px,color:#fff
    style F fill:#ff9ff3,stroke:#333,stroke-width:2px,color:#fff
    style G fill:#54a0ff,stroke:#333,stroke-width:2px,color:#fff
    
    %% 添加连接线样式
    linkStyle default stroke:#5d6d7e,stroke-width:2px,fill:none

CRC 卡的优势在于其简洁灵活,可以随时移动、修改或丢弃,特别适合在复杂系统中进行对象发现和设计思想挖掘。

本章要点总结

面向对象分析以 UML 为基础,综合运用多种分析技术:

模型 核心技术 主要作用
对象模型 领域模型/概念类图 发现数据方面的需求缺陷
用例模型 用例图、用例描述 捕获功能需求
行为模型 顺序图、状态图 发现行为和状态方面的缺陷
约束规约 OCL 精确定义业务规则

成功的面向对象分析不仅需要掌握这些技术,更需要理解如何综合运用它们来发现和弥补需求中的缺陷与不足。