目录
一、软件需求与需求获取
1. 软件需求的定义
软件开发的目标——满足顾客的需求
软件需求(Software Requirements):
- 用户解决问题以达到特定目标所需的能力
- 系统或系统构件要满足的合同、标准、规范或其他正式文档所需具备的能力 ——IEEE, 1997
软件需求:以一种清晰、简洁、一致且无二义性的方式,描述用户对目标软件系统在功能、行为、性能、设计约束等方面的期望,是在开发过程中对系统的约束
需求是质量的基础。
2. 需求的分类
业务需求(Business Requirements):客户对于系统的高层次目标要求(high-level objectives) ,定义了项目的远景和范畴(vision and scope)
- 业务:属于哪类业务范畴?应完成什么功能?为何目的?
- 客户:软件为谁服务?目标客户是谁?
- 特性:区别于其他竞争产品的特性是什么?
- 价值:价值体现在哪些方面?
- 优先级:功能特性的优先级次序是什么?
用户需求(User Requirements):从用户角度描述的系统功能需求与非功能需求,通常只涉及系统的外部行为而不涉及内部特性
功能需求(Functional Requirements, FR):系统应该提供的功能或服务,通常涉及用户或外部系统与该系统之间的交互,不考虑系统内部的实现细节
非功能需求(Non-Functional Requirements, NFR):从各个角度对系统的约束和限制,反映了客户对软件系统质量和性能(quality and performance)的额外要求,如响应时间、数据精度、可靠性等
非功能特性 | 度量指标 |
速度 | 每秒处理的事务 用户的响应时间 屏幕的刷新速度 |
存储空间 | 内存空间占用量 硬盘空间占用量 |
可用性 | 培训时间 帮助页面数 |
可靠性 | 平均失败时间 系统无效的概率 失败发生率 |
容错性 | 失败后的重启次数 事件引起失败的比例 失败时数据崩溃的可能性 |
约束条件(Constraints):系统设计和实现时必须满足的限制条件,对其进行权衡或调整是相当困难的,甚至是不可能的
业务规则(Business Rule):对某些功能的可执行性或内部执行逻辑的一些限定条件
- 通常表达为“如果…,那么…”的形式
- 通常是一些容易发生变化的功能
外部接口需求(External Interface Requirement):描述系统与其所处的外部环境之间如何进行交互,包括:用户接口需求(UI)、硬件接口需求、软件接口需求、通信接口需求
3. 好的需求与坏的需求
好的需求应具备的特征:
- 完整性:每一项需求都必须将所要实现的功能描述清楚
- 正确性:每一项需求都必须准确地陈述其要开发的功能
- 可行性:每一项需求都必须是在已知系统和环境的权能和限制范围内可以实施的
- 必要性:每一项需求都应把客户真正所需要的和最终系统所需遵从的标准记录下来
- 划分优先级:给每项需求、特性或使用实例分配一个实施优先级以指明它在特定产品中所占的分量
- 无二义性:对所有需求说明的读者都只能有一个明确统一的解释
- 可验证性:检查一下每项需求是否能通过设计测试用例或其它的验证方法,如用演示、检测等来确定产品是否确实按需求实现
不合格需求的原因:
- 无足够用户参与
- 用户需求的不断增加
- 模棱两可的需求
- 不必要的特性
- 过于精简的规格说明
- 忽略了用户分类
- 不准确的计划
4. 需求工程
需求工程(Requirement Engineering, RE)
- 应用已证实有效的技术、方法进行需求分析,确定客户需求,帮助分析人员理解问题并定义目标系统的所有外部特征的过程
- 通过合适的工具和模型系统地描述待开发系统及其行为特征和相关约束,形成需求文档,并对用户不断变化的需求演进给予支持
- 分析并记录软件需求,把需求分解成一些主要的子系统和任务,把这些子系统或任务分配给软件;通过一系列重复的分析、设计、比较研究、原型开发过程把这些系统需求转换成软件的需求描述和一些性能参数
需求获取(Requirement Elicitation):通过与用户的交流,对现有系统的观察及对任务进行分析,从而开发、捕获和修订用户的需求
- 对用户进行分类
- 聆听每一类用户的需求
- 分析和整理所获取的需求
- 形成文档化的描述
- 签字确认
需求分析(Requirement Analysis):对收集到的需求进行提炼、分析和审查,为最终用户所看到的系统建立概念化的分析模型
- 定义系统的边界
- 建立软件原型
- 分析需求可行性
- 确定需求优先级
- 建立需求分析模型
- 创建数据字典
需求规格说明(Software Requirement Specification, SRS):
- 需求开发的结果
- 精确的、形式化的阐述一个软件系统必须提供的功能、非功能、所要考虑的限制条件等
- 作为用户和开发者之间的一个契约
- 是用户、分析人员和设计人员之间进行理解和交流的依据
需求验证(Requirement Verification):以需求规格说明为输入,通过评审、模拟或快速原型等途径,分析需求规格的正确性和可行性,发现存在的错误或缺陷并及时更改和补充
需求管理(Requirement Management)
- 定义需求基线(迅速制定需求文档的主体)
- 评审提出的需求变更、评估每项变更的可能影响从而决定是否实施它
- 以一种可控制的方式将需求变更融入到项目中
- 使当前的项目计划与需求一致
- 估计变更需求所产生影响并在此基础上协商新的承诺(约定)
- 让每项需求都能与其对应的设计、源代码和测试用例联系起来以实现跟踪
- 在整个项目过程中跟踪需求状态及其变更情况
5. 需求获取方法
需求获取(requirement elicitation)的目标:收集未来系统和正在使用的系统的信息,并从这些信息中提取用户和系统需求,为下一步的需求分析提供素材
需求获取面临的挑战
问题 | 解决方案 |
“Yes, But”综合症:直到开发人员将用户描述的东西交给他们,用户才认为他们知道自己要什么 | 尽早提供可选择的启发技术:应用用例、角色扮演、开发原型等方法 |
“Undiscovered Ruins”综合症:用户不知道自己需要什么,或知道但不知如何表达 | 将用户当作领域专家来认识和激励,尝试其他交流和启发技术 |
“User and Developer”综合症:分析员认为自己比用户更了解用户的需求 | 把分析员放在用户的位置上,试着角色扮演一小时或一天 |
需求获取技术
- 收集现有书面资料
- 面对面访谈——需求获取中最直接的方法:用户面谈(interviewing)
- 需求研讨会
- 现场观察/体验
- 头脑风暴
需求获取的主要工作——对客户输入进行分类
- 业务需求:描述客户可以从产品中得到的资金、市场或其它业务利润的需求
- 业务规则:一些活动只能在特定的条件下,由一些特定的人来完成时,该用户可能在描述一个业务规则
- 功能需求:客户所说的诸如“用户应该能<执行某些功能>”或者“系统应该<具备某些行为>”,这是最可能的功能需求
- 非功能需求:按照一些条件判断系统运作情形或其特性,而不是针对系统特定行为的需求包括安全性、可靠性、互操作性、健壮性、易使用性、可维护性、可移植性、可重用性、可扩充性等
- 外部接口需求:这类需求描述了系统与外部的联系。软件需求规格说明必须包括用户接口和通信机制、硬件和其它软件系统需求部分。
- 约束条件:是指一些合理限制设计者和程序员选择的条件,它们代表了另一种类型的非功能需求,必须把这些需求写入软件需求规格说明
- 数据定义:当客户描述一个数据项或一个复杂的业务数据结构的格式、允许值或缺省值时,他们正在进行数据定义。
二、用户故事与用例建模
1. 敏捷开发中的用户故事
用户故事:对软件用户(或所有者)有价值的功能性的简明、书面描述
从用户的角度来描述用户渴望得到的功能:角色(谁要使用这个功能)、目标/活动(需要完成什么样的功能)、商业价值(为什么需要这个功能,这个功能带来什么样的价值)
三个组成部分:
- 卡片(Card):用户故事一般在小卡片上写着故事的简短描述,工作量估算等
- 交谈(Conversation):用户故事背后的细节来源于和客户或者产品负责人的交流沟通
- 确认(Confirmation):通过验收测试确认用户故事被正确完成
用户故事的描述
As a [user role] I want to [goal] so I can [reason]
作为一个<角色>, 我想要<活动>, 以便于<商业价值>
- Who (user role) -- 角色:谁要使用这个功能?
- What (goal) -- 功能:需要完成什么样的功能?
- Why (reason) --价值:为什么需要这个功能,功能带来什么样的价值?
用户故事卡正面:Conversation, 用户故事的反面:Confirmation
好的用户故事应具备的特征:INVEST
- Independent – 尽可能独立
- Negotiable – 可讨论的:它不是一个合同,没有详细的规约,后续开发阶段可以不断协商和改进
- Valuable – 对用户/客户有价值的,以用户可理解的语言书写,是系统的“特性”而非“开发任务”
- Estimatable – 其工作量可以估计
- Small – 小,而不是大
- Testable – 可测试的、可验证的
用户故事的验收测试:在每个用户故事背后,列出未来用户测试时可能使用的“测试用例”,作为该故事是否已被完整实现的基本标准。对应于敏捷开发的一个基本思想:在写代码之前先写测试(Test-Driven Development, TDD)
2. 面向对象方法中的用例
需求分析技术:用例
用例(Use Case):表示系统所提供的服务或可执行的某种行为,定义了系统是如何被参与者所使用的,描述了参与者为了使用系统所提供的某一完整功能而与系统之间发生的一段“对话”
用例——站在用户角度定义软件系统的外部特征
四大特征:
- 行为序列(sequences of actions):一个用例由一组可产生某些特定结果的行为构成,这些行为是不可再分解的(接收用户输入、执行、产生结果)
- 系统执行(system performs):系统为外部角色提供服务
- 可观测到的、有价值的结果(observable result of value):用例必须对用户产生价值
- 特定的角色(particular actor):某人、某台设备、某外部系统、等等,能够触发某些行为
用例方法的基本思想:从用户的角度来看,他们并不想了解系统的内部结构和设计,他们所关心的是系统所能提供的服务,也就是被开发出来的系统将是如何被使用的
用例模型主要由以下模型元素构成:
- 参与者(Actor) :存在于被定义系统外部并与该系统发生交互的人或其他系统,代表系统的使用者或使用环境
- 用例(Use Case):表示系统所提供的服务或可执行的某种行为
- 通讯关联(Communication Association) :用于表示参与者和用例之间的对应关系,它表示参与者使用了系统中的哪些服务(用例)、系统所提供的服务(用例)是被哪些参与者所使用的
通讯关联表示的是参与者和用例之间的关系:
- 箭头表示在这一关系中哪一方是对话的主动发起者,箭头所指方是对话的被动接受者
- 如果不想强调对话中的主动与被动关系,可以使用不带箭头的关联实线
- 通讯关联不表示在参与者和用例之间的信息流,并且信息流向是双向的,它与通讯关联箭头所指的方向没有关系
3. 用例建模的基本过程
Step 1:识别并描述参与者(actor);
Step 2:识别用例(use case),并给出简要描述;
Step 3:识别参与者与角色之间的通讯关联(Association);
Step 4:给出每一个用例的详细描述
Step 5:细化用例模型
特殊的参与者:系统时钟
有时候需要在系统内部定时的执行一些操作,如检测系统资源使用情况、定期生成统计报表等等
但这些操作并不是由外部的人或系统触发的。对于这种情况,可以抽象出一个系统时钟或定时器参与者,利用该参与者来触发这一类定时操作。从逻辑上,这一参与者应该被理解成是系统外部的,由它来触发系统所提供的用例对话
用例的注意事项
- 用例必须是由某一个actor触发而产生的活动,即每个用例至少应该涉及一个actor
- 如果存在与actor不进行交互的用例,需要将其并入其他用例,或者是检查该用例相对应的参与者是否被遗漏
- 反之,每个参与者也必须至少涉及到一个用例,如果发现有不与任何用例相关联的参与者存在,仔细考虑该参与者是如何与系统发生对话的,或者由参与者确定一个新的用例,或者该参与者是一个多余的模型元素,应该将其删除
事件流分为常规流和备选流两类:
- 常规流:描述该用例最正常的一种场景,系统执行一系列活动步骤来响应参与者提出的服务请求
- 每一个步骤都需要用数字编号以清楚地标明步骤的先后顺序
- 用一句简短的标题来概括每一步骤的主要内容
- 对每一步骤,从正反两个方面来描述
- 参与者向系统提交了什么信息
- 对此系统有什么样的响应
- 备选流:负责描述用例执行过程中异常的或偶尔发生的一些情况
- 备选流的描述格式可以与基本流的格式一致,也需要编号并以标题概述其内容
- 起点:该备选流从事件流的哪一步开始
- 条件:在什么条件下会触发该备选流
- 动作:系统在该备选流下会采取哪些动作
- 恢复:该备选流结束之后,该用例应如何继续执行
- 备选流的描述格式可以与基本流的格式一致,也需要编号并以标题概述其内容
用例描述举例
用例之间的关系:
包含
拓展
泛化
用例的粒度
用例识别的标准:actor与系统之间的一次独立交互。如果多次交互总是同时发生且不会单独发生,可合并为一个用例
用例也可称为user story,将来使用时可看作一个独立存在的功能体。如果用例过大,可进行拆分。
用例是actor与系统的交互:actor对系统发出的请求,系统对actor请求的响应。actor与actor在现实当中的交互不应包含在use case中。
系统自己做的事情,不是单独的用例:系统的行为受到actor的触发
4. 用例模型的提交物
- 用例模型
- 每个用例的详细描述
- 术语表:所用到的术语说明
- 补充规约:非功能性需求的说明
5. 活动图 & 泳道图
UML活动图(Activity Diagram)提供一种可视化的流程图方式,对use case的事件流进行直观展示,以便于读者更好的理解。同时,UML活动图也可以用来描述多个用例之间所形成的大粒度流程
两种形式:
- 传统的活动图:只涉及一个参与者
- 泳道图(swim-lane diagram):侧重于描述多个参与者的活动之间的交互关系
三、需求的结构化分析
1. 结构化方法 vs 面向对象方法
结构化方法
- 复杂世界 → 复杂处理过程(事情的发生发展)
- 设计一系列功能(或算法)以解决某一问题
- 寻找适当的方法存储数据
面向对象方法
- 任何系统都是由能够完成一组相关任务的对象构成
- 如果对象依赖于一个不属于它负责的任务,那么就需要访问负责此任务的另一个对象(调用其他对象的方法)
- 一个对象不能直接操作另一个对象内部的数据,它也不能使其它对象直接访问自己的数据
- 所有的交流都必须通过方法调用
结构化开发方法
- 起源时间:20世纪60年代产生软件危机,70年代出现“结构化开发方法”
- 思想方法:自顶向下、问题分解、分而治之、由分到合;软件/程序 = 数据结构 + 算法,软件结构化、模块化、层次化
- 表达模型:分析模型(系统流程图、数据流图、 ERD、数据字典);设计模型(系统结构图、程序流程图、ERD)
- 分析与设计线索:面向过程(处理) – 过程驱动;面向数据 – 数据驱动
- 优点:思维自然,符合人们思考问题的方式;总体可控性强;适合偏重数学计算方面的项目
- 缺点:不容易描述客观世界的需求;耦合性相对高
- 从功能的观点设计系统。自顶向下,逐步分解和细化,将大系统分解为若干模块,主程序调用这些模块实现完整的系统功能
面向对象开发方法
- 起源时间:20世纪80年代(70年代开始OOP)
- 思想方法:从客观世界的具体事物出发构建系统;自底向上,先考虑“对象”,再考虑“关系”
- 表达模型:类层次结构图(对象的属性、行为、继承、消息连接等)
- 优点:符合自然世界的状态,描述自然,思维简单;适合复杂的事务处理、大量信息处理类的项目;耦合性容易降低,容易复用
- 缺点:OO模型表达系统需求分析和设计不够充分
基于UML的面向对象开发方法
- 起源时间:20世纪90年代末
- 思想方法:开发一整套系统分析与设计模型及描述方法,从形式上和概念上统一描述软件系统
- 表达模型:用例图、活动图、状态图、序列图(协作图)、类图、组件图、包图、部署图等
- 优点:统一标准;容易交流;建模工具较多;适合大型信息系统发
- 缺点:模型不容易掌握
2. 需求的结构化分析方法
结构化分析方法(SA):将待解决的问题看作一个系统,从而用系统科学的思想方法(抽象、分解、模块化)来分析和解决问题。起源于结构化程序设计语言(事先设计好每一个具体的功能模块,然后将这些设计好的模块组装成一个软件系统) ,以动词性的“功能”为核心展开分解
核心思想:自顶向下的分解(top-down)
结构化分析:帮助开发人员定义系统需要做什么(处理需求),系统需要存储和使用哪些数据(数据需求),系统需要什么样的输入和输出以及如何把这些功能结合在一起来完成任务
- 数据流图(DFD图)
- 实体-关系图(ERD,IDEF1X图)
3. 数据流图(DFD)
数据流图(DFD):用处理、外部实体、数据流以及数据存储来表示系统需求的图表
名称 | 描述 | 图片 |
处理 | 一步步地执行指令,将输入转换成输出(由人、机器或两者共同完成该处理任务) | ![]() |
数据流 | 从一处流向另一处的数据,如处理的输入或输出 | ![]() |
外部实体 | 系统之外的数据源或目的地 | ![]() |
数据存储 | 存放起来以备将来使用的数据。通常与ERD图中的数据实体相对应 | ![]() |
实时连接 | 当处理执行时,外部实体与处理之间来回通信(如信用卡验证) | ![]() |
从外部实体出发的“数据流”可以是:
- 外部实体发出的“处理请求”,即一个事件
- 外部实体给出的“输入数据”
指向“外部实体”的“数据流”一般是“处理”的反馈或处理结果
抽象层次:把系统分解成一个逐步细化的分层集合的建模技术
关联图:在单个处理符号中概括系统内所有处理活动的DFD
关联图在表达系统边界时用处很大。系统的范围是通过单个的处理和外部实体所表示的事物来定义的。数据存储不画在关联图中是因为它本身被认为是系统内部的内容
当一个系统响应事件较多时,常常将系统分成多个子系统,并为每个子系统创建一张关联图
DFD片段:用一个单一处理符号表示系统响应一个事件的DFD
在DFD片段中,展示了处理、外部实体和内部数据存储之间的交互细节。每个DFD片段仅显示要响应该事件的相关的那些数据存储。一个DFD片段是为事件表中的每一个事件创建的
DFD的0层图:将一个系统或子系统的所有DFD片段组合到一个单个的DFD图中,这样的DFD图称为事件分离的系统模型/0层图
0层DFD图:“处理”的编号为i
DFD的层次
分解“处理”-- 理解“处理”的细节:一个DFD片段中的处理也可以包含多个更小的处理,有时分析员需要将该DFD片段进一步细化,生成更详细层次的DFD图
1层DFD图:将0层DFD中的处理进一步细化等到的DFD图, “处理”的编号为“i.j”
2层DFD图:将1层DFD中的处理进一步细化等到的DFD图,“处理”的编号为“i.j.k”
DFD质量评估
高质量的DFD:可读性强、内部一致、能够准确描述系统需求
措施:
- 最小化复杂度——就是使每幅DFD图尽量简单易懂,避免信息超量(信息超量:当太多的信息同时显现时所发生的难以理解的情况)
- 措施:
- 采用分层结构将DFD划分为小的且相对独立的子集
- 这样可以逐级阅读、考察DFD
- 构造DFD图的7±2规则:
- 单个DFD中不应有超过7±2个处理
- 单个DFD中不应超过7±2个数据流进出同一个处理/数据存储
- 接口最小化:
- DFD中各个元素之间的连接数越少越好
- 措施:
- 保证数据流一致性
- 数据流一致性表现在三个方面:
- 一个“处理”和该“处理”被详细分解后在数据流内容上应该一致
- 对一个“处理”,有数据流入则必须有相对应的数据流出
- 对一个“处理”,有数据流出则必须有相对应的数据流入
- 黑洞 --- 带有输入数据的但并不用其产生输出数据的处理或数据存储
- 奇迹 --- 没有足够数据元素作为输入或产生来源的一个处理或数据存储
- 数据流一致性表现在三个方面:
总结:
- 在关联图中不画数据存储
- 数据流不反映处理顺序,显示数据通过系统的流程,因此“处理”可以并行工作
- “处理/数据存储”既要有输入,又有输出
- 若输入数据流不完全用来产生输出数据流,称之为黑洞
- 若输出数据流不完全依赖于输入数据流,称之为奇迹
4. 数据字典(DD)
数据字典是数据分析的描述模型,包括:数据项定义,数据结构定义,数据流描述,数据存储描述
- 数据项定义:定义特定数据项的组成和意义
- 数据项:数据的基本单位
- 数据结构定义:定义有数据项组成的表达数据的基本数据
- 数据结构:由数据项组成,它给出了数据基本结构单位
- 数据流描述:描述数据流的数据构成,并指明其来源或去向
- 数据流是数据元素的集合,数据流定义就是列出其包含的所有数据项
- 数据存储描述:描述保存在存储介质上的数据文件或数据库表的格式和内容
- 数据存储:数据结构保存或停留之处,数据文件或数据库表
- 广义的数据字典,也可以包含对“处理”的描述
- 数据处理:给出处理的流程和说明信息
5. 数据分析(ERD、IDEF1X)
实体关系图(ERD)
关联实体 – 解决上述问题的人为增加的数据实体,它一定包含两端数据实体的关键字
实体关系图(IDEF1X)
含有*..*关系的实体关系图(IDEF1X形式)
四、面向对象的分析
1. 面向对象的分析方法概述
需求分析(Requirement Analysis):对收集到的需求进行提炼、分析和审查,为最终用户所看到的系统建立概念化的分析模型
需求分析的基本思想:抽象、分治、投影、建模
主要使用5种图描述完整的系统需求:用例图、类图、时序图、协作图、状态图
面向对象的分析模型由三个独立的模型构成:
- 功能模型:从用户的角度获取功能需求,由用例模型表示
- 静态结构模型(分析对象模型):描述系统的概念实体,由类图表示
- 动态行为模型:描述对象之间的交互行为,由时序图和协作图表示
面向对象分析的过程
- 第一阶段:业务领域分析--用例模型
- 第二阶段:发现和定义对象和类
- 第三阶段:识别对象的外部联系
- 第四阶段:建立系统的静态结构模型
- 第五阶段:建立系统的动态行为模型
2. 建立静态结构模型
Step 1:从用例模型入手,识别分析类;
Step 2:描述各个类的属性;
Step 3:定义各个类的操作;
Step 4:建立类之间的关系;
Step 5:绘制类图(class diagram)
分析类:概念层次上的内容,用于描述系统中较高层次的对象。分析类直接与应用逻辑相关,而不关注于技术实现的问题
分析类的类型:
实体类:表示系统存储和管理的持久性信息
边界类:表示参与者与系统之间的交互
控制类:表示系统在运行过程中的业务控制逻辑
边界类
描述外部的参与者与系统之间的交互
目的:将用例的内部逻辑与外部环境进行隔离,使得外界的变化不会影响到内部的逻辑部分
类型:用户界面、系统接口、设备接口
对用户界面来说:描述用户与系统的交互信息(传入哪些信息/指令,传出哪些信息/指令),而不是用户界面的显示形式(如按钮、菜单等)
对系统接口/设备接口来说:描述通信协议,但不必说明协议如何实现的
控制类
描述一个用例所具有的事件流的控制行为, 本身并不处理具体的任务,而是调度其他类来完成具体的任务。实现了对用例行为的封装,将用例的执行逻辑与边界和实体进行隔离,使得边界类和实体类具有较好的通用性
实体类
描述必须存贮的信息及其相关行为
对系统的核心信息建模,通常这些信息需要长久的保存
通常对应现实世界中的“事物”
三种分析类之间是“关联”关系(association)
三种分析类之间是多对多(m:n)关系:
Step 1:识别分析类
识别边界类
- 通常,一个参与者与一个用例之间的交互或通信关联对应一个边界类
- 边界类应关注于参与者与用例之间交互的信息或者响应的事件,不要描述窗口组件等界面的组成元素
- 在分析阶段,力求使用用户的术语描述界面
- 边界类实例的生命周期并不仅限于用例的事件流,如果两个用例同时与一个参与者交互,那么它们有可能会共用一个边界类,以便增加边界类的复用性
识别控制类
- 控制类负责协调边界类和实体类,通常在现实世界中没有对应的事物
- 负责接收边界类的信息,并将其分发给实体类
- 控制类与用例存在着密切的关系,它在用例开始执行时创建,在用例结束时取消
- 一般来说,一个用例对应一个控制类
- 当用例比较复杂时,特别是产生分支事件流的情况下,一个用例可以有多个控制类
- 在有些情况下,用例事件流的逻辑结构十分简单,这时没有必要使用控制类,边界类可以实现用例的行为。例如:图书管理系统中的“登录”用例
- 如果不同用例包含的任务之间存在着比较密切的联系,则这些用例可以使用一个控制类,其目的是复用相似部分以便降低复杂性。通常情况下,应该按照一个用例对应一个控制类的方法识别出多个控制类,再分析这些控制类找出它们之间的共同之处
识别实体类
- 名词驱动的识别方法
- 实体类的识别质量在很大程度上取决于分析人员书写文档的风格和质量
- 自然语言是不精确的,因此在分析自然语言描述时应该规范化描述文档中的一些措辞,尽量弥补这种不足
- 在自然语言描述中,名词可以对应类、属性或同义词等多种类型,开发人员需要花费大量的时间进行筛选
- “角色”(actor)是否一定是实体类?NO。除非系统需要在各用例中管理和维护该角色的信息(不是指ID和密码),否则只需将其作为actor,无需作为实体类
Step 2:描述分析类的属性
- 按照一般常识,找出对象的某些属性——人员的姓名、性别、年龄、地址等
- 认真研究问题域,找出对象的某些属性——商品的条形码、学生的学号等
- 根据系统责任的要求,找出对象的某些属性:比如权限
- 考虑对象需要系统保存的信息,找出对象的相应属性:比如工作进度
- 对象为了在服务中实现其功能,需要增设一些属性:比如临时数据
- 识别对象需要区别的状态:比如订单状态
- 确定属性表示整体与部分结构和实例连接:比如父节点的ID
描述边界类
- 对UI类型的边界类:
- 需要actor输入的各个数据
- 系统反馈给actor的各个数据
- 需要临时保存的、用于在边界类和控制类之间传递的临时数据(例如登录次数)
- 对API类型的边界类:
- 需要向外部系统(软件/硬件)传递的数据
- 需要从外部系统(软件/硬件)接收的数据
描述控制类
- 从UI接收的数据
- 为进行事件流执行所需的临时数据
- 需要调用的实体类
- 经过计算之后、需要发送给UI的数据
描述实体类
- 基本属性:按照一般常识,找出实体类的基本属性
- 状态属性:识别对象需要区别的状态,考虑是否需要增加一个属性来区别这些状态
- 关联属性:确定属性表示整体与部分结构和实例连接
- 派生属性:通过计算其他属性的值所得到的新属性(例如实发工资、扣税)
Step 3:定义分析类的操作
- 将用例行为分配到相应的分析类之后,系统的一些分析类具有相应的职责;可通过动词分析获得操作
- 操作的四种类型:
- 以某种方式操作数据(例如:增加、删除、重新格式化、选择等)
- 执行计算的操作
- 请求某个对象的状态的操作
- 监视某个对象发生某个控制事件的操作
边界类的操作:
- 提供给用户的、可在UI上进行的各类操作
- 对从控制类返回的数据进行各类临时处理而进行的操作
- 提供给其他系统的API
控制类的操作:
- 对从边界类接收到的数据进行各类临时处理而进行的操作
- 向实体类所发出的调用操作
- 对从实体类接收到的数据进行临时处理而进行的操作
实体类的操作:
- 对属性进行CRUD的操作
- 对状态进行更新的操作
- 辅助操作
Step 4:建立类之间的关系
五种关系:
- 泛化(generalization)
- 关联(association)
- 组合(composition)
- 聚合(aggregation)
- 依赖(dependency)
Step 5:绘制类图
两种类图:
- 分析类图:描述各边界类、实体类、控制类之间的关联关系,无需刻画属性与操作集
- 领域类图:可以不包含边界类与控制类,侧重描述各实体类之间的五种关系,需要给出详细的属性与操作集合。在不加说明的情况下,领域类图更有价值
3. 建立动态行为模型
动态行为模型可用两个新视图描述:
- 时序图/顺序图(Sequence Diagram)
- 协作图(Collaboration Diagram)
时序模型与用例模型的关系
- 用例事件流中:
- 用户请求XX——对应于actor向边界类发出的指令
- 系统响应XX——于边界类向控制类、实体类发出的指令、执行的反馈结果
- 用例事件流描述用自然语言,但时序图将其转化为类之间的函数调用与消息传递,是对事件流的“可实现化的描述”