软件需求与需求获取
一. 软件需求的定义
对用户需求的管理水平是决定软件成败的重要原因!
错误需求的扩散效应:错误的需求会导致之后的设计和编码等工作都是错误的

错误需求的修复代价:随着需求、设计、编码、测试、执行的过程代价增高(需求在出错之后会严重影响随后实现的系统)
根本原因:需求的鸿沟(期望差异)——开发者开发的与用户所想得到的软件存在着巨大期望差异!
!!!软件需求的定义: 以一种清晰、简洁、一致且无二义性的方式,描述用户对目标软件系统在功能、行为、性能、设计约束等方面的期望,是在开发过程中对系统的约束
需求是质量的基础
- 为软件项目的成本、时间、风险估计提供准确的依据
- 减少开发工作量,避免将时间与资源浪费在设计与实现错误的需求上
- 通过提供需求文档和需求基线,来有效的管理系统演化与变更
- 作为客户与开发团队之间正式合同的一部分
- 为最终的验收测试提供标准和依据
二. 需求的分类

业务需求(Business Requirements):客户对于系统的高层次目标要求,定义了项目的远景和范畴。
- 业务、客户、特性、价值、优先级
用户需求(User Requirements):从用户角度描述的系统功能性需求与非功能需求,通常只涉及系统的外部行为而不涉及内部特性。
功能需求(Functional Requirements, FR):系统应该提供的功能或服务,通常涉及用户或外部系统与该系统之间的交互,不考虑系统内部的实现细节。
非功能需求(Non-Functional Requirements, NFR):从各个角度对系统的约束和限制,反映了客户对软件系统质量和性能的额外要求,如响应时间、数据精度、可靠性等。(NFR检验非常困难,一般采用一些可度量的特性进行描述)

约束条件(Constraints):系统设计和实现时必须满足的限制条件,对其进行权衡或调整是相当困难的。
业务规则(Business Rule):对某些功能的可执行性或内部执行逻辑的一些限定条件。
外部接口需求:描述系统与其所处的外部环境之间如何进行交互,包括:用户接口需求UI、硬件接口需求、软件接口需求、通信接口需求。
三. 好的需求与坏的需求
1. 好需求的特性
- 完整性:所要实现的功能描述清楚
- 正确性:准确地陈述其要开发的功能
- 可行性:在已知系统和环境的权能和限制范围内可以实施的
- 必要性:把客户真正所需要的和最终系统所需遵从的标准记录下来
- 划分优先级
- 无二义性
- 可验证性:检查一下每项需求是否能通过设计测试用例或其它的验证方法
2. 不合格需求的原因
- 无足够用户参与
- 用户需求不断增加:结构紊乱,代码补丁使整个程序难以理解和维护;项目过大超过计划和预算范围。
- 模棱两可的需求
- 不必要的特性:画蛇添足,需求规格说明未涉及;缺乏实用价值的功能。
- 过于精简的规格说明
- 忽略了用户分类
- 不准确的计划
四. 需求工程(Requirement Engineering, RE)
需求工程的总体流程

1. 需求获取 Requirement Elicitation
通过与用户的交流,对现有系统的观察及对任务进行分析,从而开发、获取和修订用户的需求
- 对用户进行分类
- 聆听每一类用户需求
- 分析整理所获取的需求
- 形成文档化的描述
- 签字确认
2. 需求分析 Requirement Analysis
对收集到的需求进行提炼、分析和审查,为最终用户所看到的系统建立概念化的分析模型
- 定义系统边界
- 建立软件原型
- 分析需求可行性
- 确定需求优先级
- 建立需求分析模型
- 创建数据字典
3. 需求规格说明 Software Requirement Specification, SRS
- 需求开发的结果
- 精确的、形式化地阐述一个软件系统必须提供的功能、非功能、所要考虑的限制条件等
- 作为用户和开发者之间的一个契约
- 是用户、分析人员和设计人员之间进行理解和交流的依据
4. 需求验证 Requirement Verification
以需求规格说明为输入,通过评审、模拟或快速原型等途径,分析需求规格的正确性和可行性,发现存在的错误或缺陷并及时更改和补充
5. 需求管理 Requirement Management
五. *软件需求与软件工程其他要素的关系
六. *与需求工程有关的潜在风险
七. 需求获取方法
需求获取的目标
收集未来系统和正在使用的系统的信息,并从这些信息中提取用户和系统需求
为下一步的需求分析提供素材

八. 需求获取所面临的挑战
九. 需求获取技术
需求获取的关键:沟通和交流
要避免的问题:交流障碍、沟通不全、意见冲突
所要必备的条件:较高的技术水平、丰富的实践经验、较强的人际沟通能力
1. 收集现有书面资料
- 收集现有的报表、表格和过程描述
- 收集现有的工作流程图
- 分发和收集需求调查表
2. 面对面访谈
访谈问题分类
- 上下文无关的问题(context-free questions):充分理解用户的问题,不涉及具体的解决方案
- 解决方案相关的问题(solution-context questions):通过这类问题,探寻特定的解决方案并得到用户认可
3. 需求研讨会 Workshop
JAD会议室
联合应用设计会议(Joint Application Design, JAD):让所有相关人员一起参加某个单一会议来定义需求或设计系统
短暂而紧凑的时间,一般1至2天
4. 现场观察/体验
被动观察:用户实地工作,需求分析人员在旁边看
主动体验:需求分析人员直接参与用户的实际工作
5. 头脑风暴
8-12人
适用场合:产品型系统,需要具有创新性特征,尚未投放市场,无明确的客户
十. 需求获取的主要内容
对用户输入进行分类
- 业务需求:描述客户可以从产品中得到的资金、市场或其它业务利润的需求
- 业务规则:一些活动只能在特定的条件下,由一些特定的人来完成时,该用户可能在描述一个业务规则
- 功能需求
- 非功能需求
- 外部接口需求
- 约束条件
- 数据定义
用户故事与用例建模
一. 敏捷开发中的“用户故事”(User Story)
1. 用户故事
用户故事——对软件用户(或所有者)有价值的功能性的简明、书面描述
从用户的角度来描述用户渴望得到的功能: 角色(谁要使用这个功能)、目标/活动(需要完成什么样的功能)、商业价值(为什么需要这个功能,这个功能带来什么样的价值)
用户故事的三个组成部分
- 卡片 Card:用户故事一般在小卡片上写着故事的简短描述,工作估计量等
- 交谈 Conversation:用户故事背后的细节来源于和客户或者产品负责人的交流沟通
- 确认 Confirmation:通过验收测试确认用户故事被正确完成
用户故事板
用户故事的描述:角色、功能、价值,(作为一个<角色>,我想要<活动>,以便于<商业价值>)
2. INVEST 好的用户故事应具备的特征
- Independent 尽可能独立
- Negotiable 可讨论的:不是合同、没有详细规约,后续开发阶段可以不断协商和改进
- Valuable 对用户/客户有价值:用户可理解的语言,是系统”特性“而不是”开发任务“
- Estimable 工作量可估算
- Small 小
- Testable 可测试的
- 对应敏捷开发的一个基本思想:写代码之前先写测试(Test-Driven Development, TDD)
3. 用户故事支持敏捷迭代计划
一个用户故事,使用Story Point(故事点,一个达到共识的基本时间单位,例如1天)估算工作量
团队成员分别估计,差异较大时面对面讨论,发现分歧,形成共识
形成故事清单
对用户故事排列优先级
安排负责人
汇聚为迭代计划并发布
开发过程中监控进度
二. 面向对象方法中的“用例”(Use Case)
1. 用例 Use Case
用例:表示系统所提供的服务或可执行的某种行为,定义了系统是如何被参与者所使用,描述了参与者为了使用系统所提供的某一完整功能而与系统之间发生的一段”对话“。
用例:站在用户角度定义软件系统的外部特征。
四大特性
- 行为序列:一个用例由一组可产生某些特定结果的行为构成,这些行为是不可分解的
- 系统执行:系统为外部角色提供服务
- 可观测到的、有价值的结果:用例必须对用户产生价值
- 特定角色:某人、某台设备、某外部系统等等,能够触发某些行为
2. 用例方法的基本思想
完全站在用户的角度上,从系统外部来描述功能
从用户的角度来看,他们并不想了解系统的内部结构和设计,他们所关心的是系统所能提供的服务,也就是被开发出来的系统将是如何被使用的
用例模型的元素构成
- 参与者 Actor:系统外部,与系统发生交互的人或其他系统,代表系统的使用者或使用环境
- 用例 Use Case:代表系统所提供的服务或可执行的某种行为
- 通讯关系 Communication Association:参与者与用例之间的对应关系,表示参与者使用了系统中哪些用例、系统所提供的服务(用例)是被哪些参与者使用的(不表示在参与者和用例之间的信息流)
三. 用例建模的基本过程
Step 1:识别并描述参与者(actor);
- 使用、获取提供信息、访问外部硬件、维护管理此系统、系统交互
- 特殊的参与者:系统时钟(定时操作,从逻辑上,这一参与者应该被理解成是系统外部的,由它来触发系统所提供的用例对话)
Step 2:识别用例(use case),并给出简要描述;
- 根据参与者确认系统的用例,看各参与者需要系统提供什么样的服务
- 注意事项:每个用例至少涉及一个actor,每个参与者也必须至少涉及一个用例
Step 3:识别参与者与角色之间的通讯关联(Association);
Step 4:给出每一个用例的详细描述
- 单纯的用例图不能描述完整的信息,需要用文字描述不能反映在图形上的信息
- 事件流:数字编号表明步骤,简短概况每一步主要内容(参与者提交信息、系统响应)
- 常规事件流:描述该用例最正常的一种场景,系统执行一系列活动步骤来响应参与者提出的服务请求
- 备选事件流:负责描述用例执行过程中异常的或偶尔发生的一些情况

Step 5:细化用例模型
- 参与者与参与者之间的泛化
- 用例与用例之间的包含<
> - 用例与用例之间的扩展<
>(实际上相当于一个用例的“备选流”) - 用例与用例之间的泛化(子用例继承了父用例所有的结构、行为和关系)
利用这些关系来调整已有的用例模型,把一些公共的信息抽取出来复用,使得用例模型更易于维护
需要注意的问题
- 用例的粒度
- 用例识别的标准:actor与系统之间的一次独立交互,多次交互同时且不会单独发生可以合并为一个用例
- 用例也可称为user story,将来使用时可看作一个独立存在的功能体
- 用例过大,可以拆分
- 用例是actor与系统的交互
- actor对系统的请求,系统对actor的请求
- actor与actor在现实当中的交互不应包含在use case中,如讨价还价、处理纠纷
- actor与系统的区分
- 系统自己做的事情,不是单独的用例:系统的行为受到actor的触发(可能是系统时钟)
四. 用例模型的提交物
用例模型
每个用例的详细描述
术语表:所用到的术语说明
补充规约:非功能性需求的说明

五. 活动图 & 泳道图
活动图(Activity Diagram)提供一种可视化的流程图方式,对use case的事件流进行直观展示(同时,活动图也可以用来描述多个用例之间所形成的大粒度流程)
泳道图(swim-lane diagram):侧重于描述多个参与者的活动之间的交互关系
需求的结构化分析
一. 结构化方法vs面向对象方法

结构化方法:从功能的观点设计系统,自顶向下、分而治之,将大系统分解为若干模块
面向对象方法:自底向上,先考虑对象,再考虑关系
基于UML的面向对象方法:开发一整套系统分析与设计模型及描述方法,从形式上和概念上统一描述软件系统
二. 需求的结构化分析方法
结构化分析方法(SA):将待解决的问题看作一个系统,从而用系统科学的思想方法(抽象、分解、模块化)来分析和解决问题(核心思想:自顶向下的分解)
结构化分析:帮助开发人员定义系统需要做什么(处理需求),系统需要存储和使用哪些数据(数据需求),系统需要什么样的输入和输出以及如何把这些功能结合在一起来完成任务
- 基于数据流的需求分析建模——DFD
- 数据分析建模——ERD/IDEF1X
三. 数据流图(DFD, Data Flow Diagram)
数据流图:用处理、外部实体、数据流以及数据存储来表示系统需求的图表

DFD图可以描述高层次的具有高度概括的系统处理,也可以描述低层次的具有更详细分解的系统处理
抽象层次:把系统分解成一个逐步细化的分层集合的建模技术


1. 关联DFD图
关联图:在单个处理符号中概括系统内所有处理活动的DFD
表示系统边界时用处很大
系统的范围是通过单个的处理和外部实体所表示的事物来定义的
数据存储不画在关联图中是因为它本身被认为是系统内部的内容
当一个系统响应事件较多时,常常将系统分成多个子系统,并为每个子系统创建一张关联图
2. DFD片段
DFD片段:用一个单一处理符号表示系统响应一个事件的DFD
展示了处理、外部实体和内部数据存储之间的交互细节
3. DFD的层次
一个系统或子系统的所有DFD片段组合到一个单个的DFD图中,这样的DFD图称为事件分离的系统模型/0层图
分解”处理“——理解”处理“的细节()
0层DFD图编号:i
1层DFD图编号:i.j
2层DFD图编号:i.j.k
4. DFD的质量评估
高质量DFD:可读性强、内部一致、能够准确描述系统需求
措施:最小化复杂度,保证数据流一致性
最小化复杂度
- 每幅DFD图尽量简单易懂,避免信息超量——太多信息同时显示时所发生的难以理解的情况
- 采用分层结构将DFD划分为小的且相对独立的子集
- 构造DFD图的7±2规则(单个DFD不超过7±2个处理、不超过7±2个数据量进出同一个处理/数据存储)
- 接口最小化:DFD各个元素之间的连接越少越好(低耦合)
保证数据流一致性
- 一个”处理“和该”处理“被详细分解后在数据流内容上应该一致
- 对一个”处理“,有数据流入则必须有相应的数据流出
- 对一个”处理“,有数据流出则必须有相应的数据流入
黑洞
带有输入数据但不用其产生输出数据的处理或数据存储(有入无出)
奇迹
没有足够数据元素作为输入或产生来源的一个处理或数据存储(无足够入,包括无入)
数据流典型错误

总结
- 关联图中不画数据存储
- 数据流不反应处理顺序,显示数据通过系统的流程,因此”处理“可以并行工作
- ”处理/数据存储“既要有输入,又有输出(黑洞、奇迹)
5. DFD细节内容
在传统方法中,DFD图在一个图中描述了三种元素:
处理——每个最底层“处理”需要详细描述其细节
数据流——”数据流”包含的数据元素需要定义
数据存储——“数据存储”需要在ERD中定义
数据流和数据存储就是狭义的数据字典DD
处理的细节描述
- 处理细分解、层层分解
- 结构化语言/伪代码
- 结构化语言:自然语言和形式语言之间的语言(短句、多层缩进、无确定语法、可分层和嵌套、结构化编程技术和叙述性语言结合)

- 决策表/决策树
四. 数据字典(DD)
数据字典是数据分析的描述模型,包括:数据项定义、数据结构定义、数据流描述、数据存储描述
- 数据项定义:定义特定数据项的组成和意义
- 数据项是数据的基本单位
- 包含:数据项名、数据项说明、数据类型、长度、取值范围、语法定义、与其他数据项的关联
- 数据结构定义:定义有数据项组成的表达数据的基本数据
- 数据结构由数据项构成,是数据基本结构单位
- 包含:数据结构名、数据结构说明、数据结构组成:{数据项/数据结构}、数据结构约束
- 数据流描述:描述数据流的数据构成,并指明其来源或去向
- 数据流是数据结构在系统中的流通途径
- 包含:数据流名、数据流说明、来源、去向、组成:{数据结构}、平均流量、高峰流量
- 数据流是数据元素的集合,数据流定义就是列出其包含的所有数据项
- 数据元素还需进一步的定义:说明类型、长度等,一般在设计阶段详细定义
- 代数公式方式定义数据流

- 数据存储描述:描述保存在存储介质上的数据文件或数据库表的格式和内容(颗粒度比数据项和数据结构大)
- 数据存储:数据结构保存或停留之处,数据文件或数据库表
- 包含:数据存储名、数据存储说明、输入的数据流、输出的数据流、数据存储组成:{数据结构}、数据量、存储频度、存储方式
- 广义的数据字典也包含对”处理“的描述。
- 数据处理:给出处理的流程和说明信息
- 包含:数据处理名、数据处理说明、输入数据:{数据结构}、输出数据:{数据结构}、处理过程简要描述
五. 数据分析(ERD、IDEF1X)什么区别????
1. 实体关系图——ERD
传统的系统开发方法都将重点集中在数据存储需求上
数据存储需求包括数据实体、数据实体的属性以及它们之间的关系


2. 实体关系图——IDEF1X


面向对象的分析
一. 面向对象的分析方法概述
1. 需求分析的本质
需求分析(Requirement Analysis):对收集到的需求进行提炼、分析和审查,为最终用户所看到的系统建立概念化的分析模型
本质:
分析模型的目标:描述客户需要什么(软件的信息、功能和行为),为软件设计奠定基础(结构、接口、软件设计),定义软件完成后可以被确认的一组需求
需求分析的基本思想:
- 抽象——透过现象看本质(具体事物中发现其本质性特征和方法的过程)
- 分治——分而治之,整体/部分关系,降低问题复杂性
- 投影——不同视角看问题
- 建模——需求描述模型化(形式化的数学模型、非形式化的图形化模型)
2. 面向对象分析
面向对象的分析模型由三个独立的模型构成:如下图所示,功能模型——用例模型,静态结构模型——类图(系统概念实体),动态行为模型——时序图和协作图。箭头表示驱动,或者说画图顺序。


面向对象分析的过程
- 第一阶段:业务领域分析:业务范围,确定系统边界,确定系统需求——用例模型
- 第二阶段:发现和定义对象和类:确定内部特征(属性和服务操作),现实到概念模型的抽象
- 第三阶段:识别对象的外部联系:识别对象与对象、类与类之间的各种外部联系
- 第四阶段:建立系统的静态结构模型:图形和文字,如绘制类图、对象图、系统与子系统结构图等,编制相应的说明文档
- 第五阶段:建立系统的动态行为模型:图形和文字,如绘制活动图、交互图、状态图等,编制相应的说明文档

二. 建立静态结构模型
分析类
- 分析类是概念层次上的内容,用于描述系统中较高层次的对象
- 分析类直接与应用逻辑相关,而不关注技术实现的问题
- 分析类的类型:
- 实体类:表示系统存储和管理的持久性信息


- 必须存贮的信息及其相关行为,通常这些信息需要长久保存
- 对应现实世界中的事物

- 边界类:表示参与者与系统之间的交互


- 将用例的内部逻辑与外部环境进行隔离,使得外界的变化不会影响到内部的逻辑部分
- 类型:用户界面、系统接口、设备接口
- 对用户界面来说:用户与系统的交互信息,而不是用户界面的显示形式(按钮、菜单等)
- 对系统接口/设备接口来说:描述通信协议,不必说明协议如何实现

- 控制类:表示系统在运行过程中的业务控制逻辑


- 用例所具有的事件流的控制行为, 本身并不处理具体的任务,而是调度其他类来完成具体的任务
- 实现了对用例行为的封装,将用例的执行逻辑与边界和实体进行隔离,使得边界类和实体类具有较好的通用性

- 实体类:表示系统存储和管理的持久性信息
三种分析类多对多的关联关系

Step 1:识别分析类
方法:重用和修改现有的模型,使用分类列表(不同领域不同的分类列表),对用例文本进行“语法分析”(名词/名词短语,动词映射为类的操作、形容词/名词映射为类的属性)
- 边界类:
- 一个参与者与一个用例之间的交互或通信关联对应一个边界类
- 一般是界面、接口
- 关注于参与者与用例之间交互的信息或者响应的事件,不要描述界面组成元素

- 控制类:
- 协调边界类和实体类,通常在现实世界中没有对应的事物
- 负责接收边界类的信息,并将其分发给实体类
- 一般来说,一个用例对应一个控制类(但是一个用例可以有多个控制类,如分支事件流情况下;有的情况没必要使用控制类;有些用例可以使用一个控制类)

- 实体类:
- 名词驱动的识别方法
- 对用例文本进行“语法分析”(名词/名词短语,动词映射为类的操作、形容词/名词映射为类的属性)
- 角色actor不一定是实体类。 除非系统需要在各用例中管理和维护该角色的信息(不是指ID和密码),否则只需将其作为actor,无需作为实体类。
Step 2:描述分析类的属性
- 边界类:
- UI类型的边界类:actor输入数据、系统反馈数据、临时数据
- API类型的边界类:内外部系统(软件/硬件)传递、接收数据
- 控制类:从UI接收数据、事件流执行临时数据、调用实体类、发送给UI的数据
- 实体类:基本属性、状态属性、关联属性、派生属性(计算其他属性值得到的新属性)
Step 3:定义分析类的操作
- 边界类的操作
- 提供给用户的(actor自己做的动作都是边界类的操作)、可在UI上进行的各类操作
- actor发出的每个动作,通常都比较大,需要仔细分析对应于实体类的哪些属性做CRUD
- 对从控制类返回的数据进行各类临时处理而进行的操作
- 提供给其他系统的API
- 提供给用户的(actor自己做的动作都是边界类的操作)、可在UI上进行的各类操作
- 控制类的操作
- 对从边界类接收到的数据进行各类临时处理而进行的操作
- 向实体类发出的调用操作
- 对从实体类接收到的数据进行临时处理而进行的操作
- 实体类的操作
- 对实体内部的属性进行CRUD操作(create、read、update、delete)
- 对状态进行更新的操作
- 辅助操作
Step 4:建立类之间的关系
泛化、关联、组合、聚合、依赖
Step 5:绘制类图
分析类图:描述各边界类、实体类、控制类之间的关联关系,无需刻画属性与操作集

领域类图:可以不包含边界类与控制类,侧重描述各实体类之间的五种关系,需要给出详细的属性与操作集合

三. 建立动态行为模型
时序图/顺序图(Sequence Diagram)
协作图(Collaboration Diagram)


一张时序图从左到右应该是:actor(用户)、边界类、控制类、实体类、actor(外部系统)

四. 案例分析
仔细看