软件工程:第九章 面向对象分析
软件工程:第九章 面向对象分析
导学目标
- 了解面向对象分析的目标、关键要素及过程
- 掌握建立对象模型、动态模型、功能模型的步骤
- 了解服务的相关知识
第一节 面向对象分析概述
1、无论我们采用何种方式开发软件,分析的过程都是提取需求的过程。分析工作主要包括3项内容,理解、表达、验证。
- 理解:系统分析员通过与用户及领域专家交谈,力求完全理解用户需求和该应用领域内关键性的背景知识
- 表达:用某种无二义性的方式把这种理解表达成文档资料
- 验证:由于问题复杂,交流过程中可能出现偏差,理解可能达不到预期的效果,因此我们需要去验证文档资料的正确性,若有问题,需要重新进行修改
2、面向对象分析(OOA)的关键
- 识别问题域内的类与对象,并分析它们之间的关系,建立起针对于问题域的正确模型
3、面向对象分析(OOA)的定义
- 抽取和整理用户需求并建立问题域精确模型的过程
4、面向对象分析(OOA)的过程
- 获取用户需求
- 建立模型(需要向领域专家学习并自信研究类似的问题域)
- 书写需求规格说明书
- 复审
5、面向对象建模中的三个要素
- 对象模型:几乎在解决任何一个问题
- 动态模型:当问题设计到交互和时序时
- 功能模型:解决运算量很大的问题
6、复杂问题的对象模型:(5个层次)
- 主题层
- 类与对象层
- 结构层
- 属性层
- 服务层
7、需求陈述的内容包括问题的范围、功能需求、性能需求、应用环境及假设条件等。需求陈述说明的是做什么,而不是怎样去做
8、书写需求陈述的要点
- 要尽力做到语法准确
- 不要把实际需求和设计决策混为一谈
- 需求陈述可繁可简
- 需求陈述要具体无二义性、完整性和一致性
需求陈述案例
银行ATM取款机
1、需求陈述
- 某银行拟开发一个自动取款机系统,它是一个由自动取款机、中央计算机、分行计算机及柜员终端组成的网络系统。ATM和中央计算机由总行投资购买【ATM系统的组成】
- 总行拥有多台ATM,分别设在全市各主要街道上。分行负责提供分行计算机和柜员终端。柜员终端设在分行营业厅及分行下属的各个储蓄所内。该系统的软件开发成本由各个分行分摊【总行ATM以及分行ATM的功能和应用领域】
- 银行柜员使用柜员终端处理储户提交的储蓄事务。储户可以用现金或支票向自己拥有的某个账户内存款或开新账户。储户也可以从自己的账户中取款。通常,一个储户可能拥有多个账户【储户和ATM系统和账户之间的关系】
- 柜员负责把储户提交的存款或取款事务输进柜员终端,接收储户交来的现金或支票,或付给储户现金。柜员终端与相应的分行计算机通信,分行计算机具体处理针对某个账户的事务并且维护账户【储户、柜员、分行计算机、账户之间的关系】
- 拥有银行账户的储户有权申请领取现金兑换卡。使用现金兑换卡可以通过ATM访问自己的账户。目前仅限于用现金兑换卡在ATM上提取现金(即取款),或查询有关自己账户的信息(例如,某个指定账户上的余额)。将来可能还要求使用ATM办理转账、存款等事务
- 所谓现金兑换卡就是一张特制的磁卡,上面有分行代码和卡号。分行代码唯一标识总行下属的一个分行,卡号确定了这张卡可以访问哪些账户。通常,一张卡可以访问储户的若干个账户,但是不一定能访问这个储户的全部账户
- 每张现金兑换卡仅属于一个储户所有,但是,同一张卡可能有多个副本,因此,必须考虑同时在若干台ATM上使用同样的现金兑换卡的可能性。也就是说,系统应该能够处理并发的访问【系统要求:并发访问】
- 当用户把现金兑换卡插入ATM之后,ATM就与用户交互,以获取有关这次事务的信息,并与中央计算机交换关于事务的信息
- 首先,ATM要求用户输入密码,接下来ATM把从这张卡上读到的信息以及用户输入的密码传给中央计算机,请求中央计算机核对这些信息并处理这次事务
- 中央计算机根据卡上的分行代码确定这次事务与分行的对应关系,并且委托相应的分行计算机验证用户密码
- 如果用户输入的密码是正确的,ATM就要求用户选择事务类型(取款、查询等)。当用户选择取款时,ATM请求用户输入取款额。最后,ATM从现金出口吐出现金,并且打印出账单交给用户
第二节 建立对象模型
面向对象分析的首要工作,就是建立问题域的对象模型
对象模型描述了类与对象以及它们之间的相互关系,表示了目标系统的静态数据结构
静态数据结构对应用细节依赖较少,比较容易确定;当用户需求发生变化时,静态数据结构相对比较稳定。因此,用面向对象方法开发出绝大多数软件时,都首先建立对象模型,然后再建立其他两个子模型
1、建立对象模型的步骤
- 确定分析类
- 确定类的关联
- 划分主题
- 确定属性
- 识别继承
- 反复修改
9.2.1 确定类与对象
1、找出候选的类与对象
-
边界类
-
通常一参与者与一用例之间交互或通信关联对应一边界类
-
示例:ATM的系统用例图
边界类 说明 SetupForm 开新账户的操作界面 DepositForm 存款的操作界面 ATMWithdrawForm ATM用户取款的操作界面 ATMBalanceForm ATM查询余额的操作界面 ATMPasswordForm ATM改变密码的操作界面 TellerWithdrawForm Teller用户取款的操作界面 TellerBalanceForm Teller查询余额的操作界面 TellerPasswordForm Teller改变密码的操作界面
-
-
控制类
-
控制类负责协调边界类和实体类,通常在现实世界没有对应的事物。一般来说,一个用例对应一个控制类
-
示例
控制类 说明 SetupControl 负责执行开新账户 DepositControl 负责执行存款 WithdrawControl 负责执行取款 BalanceControl 负责执行查询余额 PasswordControl 负责执行改变密码
-
-
-
实体类
-
实体类通常是用例中的参与对象,对应着现实世界中“事物”

-
-
非正式分析法:提取需求陈述中的名词
- 示例:用非正式分析法提取ATM系统中的实体类
- 银行,自动取款机(ATM),系统,中央计算机,分行计算机,柜员终端,网络,总行,分行,软件,成本,市,街道,营业厅,储蓄所,柜员,储户,现金,支票,账户,事务,现金兑换卡,余额,磁卡,分行代码,卡号,用户,副本,信息,密码,类型,取款额,账单,访问
- ATM系统分析员根据领域知识或常识提取出隐含的类。如通信链路、事务日志等
- 示例:用非正式分析法提取ATM系统中的实体类
2、筛选出正确的类与对象
显然根据非正式分析方法只能确定候选的类与对象,还需要通过严格的标准去筛选出正确的,去掉不正确的
-
筛选的标准
-
冗余
- 如果两个类表达了同样的信息,应该保留此问题域中最富于描述力的名称。
- 示例:储户与用户,现金兑换卡与磁卡及副本应去掉“用户”、“磁卡”、“副本”,保留“储户”和“现金兑换卡”
-
无关
- 如果类与当前要解决的问题无关,需要删除与本问题密切相关类放进目标系统,去掉“成本”、“市”、“街道”、“营业厅”、“储蓄所”
-
笼统——直接去掉
- 示例:银行(总行和分行)、系统、软件、信息、访问(事务)
-
属性——直接去掉
- 示例:现金、支票、取款额、账单、余额、分行代码、卡号、密码和类型
-
操作
- 需求陈述中既作名词又作动词的词,慎重考虑是作类合适,还是作类中操作合适
-
实现—— 直接去掉
- 事务日志、通信链路
-
-
经过初步筛选还剩下的类
- ATM系统筛选后的类:
- 银行,自动取款机(ATM),系统,中央计算机,分行计算机,柜员,终端,网络,总行,分行,软件,成本,市,街道,营业厅,储蓄所,柜员,储户,现金,支票,账户,事务,现金兑换卡,余额,磁卡,分行代码,卡号,用户,副本,信息,密码,类型,取款额,账单,访问确定类与对象
- ATM系统筛选后的类:
-
ATM系统的实体分析类
9.2.2 确定关联
1、初步确定关联
-
步骤
- 提取需求陈述中的动词词组
- 发现隐含关联
- 与用户及领域专家讨论后补充
-
示例:ATM系统
- 直接提取动词短语得出的关联
- ATM、中央计算机、分行计算机及柜员终端组成网络
- 总行拥有多台ATM
- ATM设在主要街道上
- 分行提供分行计算机和柜员终端
- 柜员终端设在分行营业厅及储蓄所内
- 分行分摊软件开发成本
- 储户拥有账户
- 分行计算机处理针对账户的事务
- 分行计算机维护账户
- 柜员终端与分行计算机通信
- 柜员输入针对账户的事务
- ATM与中央计算机交换关于事务的信息
- 中央计算机确定事务与分行的对应关系
- ATM读现金兑换卡
- ATM与用户交互
- ATM吐出现金
- ATM打印账单
- 系统处理并发的访问
- 需求陈述中隐含的关联
- 总行由各分行组成
- 分行保管账户
- 总行拥有中央计算机
- 系统维护事务日志
- 系统提供必要安全性
- 储户拥有现金兑换卡
- 根据问题域知识得出的关联
- 现金兑换卡访问账户
- 分行雇用柜员
- 直接提取动词短语得出的关联
2、筛选
- 初步分析得出的关联只能作为候选关联,还需要做进一步的筛选
- 筛选的标准
- 已删去的类之间的关联
- 删掉某候选类,与这个类有关的关联也删去,或重新表达
- 已删去“系统”、“网络”、“市”、“街道”、“成本”、“软件”、“事务日志”、“现金”、“营业厅”、“储蓄所”、“账单”候选类,关联也应删去:
- ATM、中央计算机、分行计算机及柜员终端组成网络
- ATM设在主要街道上
- 分行分摊软件开发成本
- 系统提供必要安全性
- 系统维护事务日志
- ATM吐出现金
- ATM打印账单
- 柜员终端设在分行营业厅及储蓄所内
- 删掉某候选类,与这个类有关的关联也删去,或重新表达
- 与问题无关的或应在实现阶段考虑的关联应该删去
- 如ATM系统的例子中,“系统处理并发的访问”需要删去.
- 瞬时事件
- 关联应该描述问题域的静态结构,而不应该是一个瞬时事件
- 以ATM系统为例,“ATM读现金兑换卡”、“ATM与用户交互”、“中央计算机确定事务与分行对应关系”隐含“中央计算机与分行通信”
- 三元或者三元以上的关联
- 三个或三个以上对象关联,可分解为二元关联或限定关联
- 在ATM系统例子中,“柜员输入针对账户的事务”分解成“柜员输入事务”和“事务修改账户”
- “ATM与中央计算机交换关于事务的信息”隐含“ATM与中央计算机通信”和“在ATM上输入事务”这两个二元关联
- 派生关联
- 可以去掉那些可以使用其他关联定义的冗余关联
- 例如在ATM例子中,“总行拥有多台ATM”实质上是“总行拥有中央处理机”和“ATM与中央计算机通信”
- 已删去的类之间的关联
3、进一步完善
- 正名
- 应该选择含义更明确的名字作为关联名
- 例如:"分行提供分行计算机和柜员终端"改为"分行拥有分行计算机"和"分行拥有柜员终端"
- 分解
- 把“事务”分解成“远程事务”和“柜员事务”
- 补充
- 需补充"柜员输入柜员事务"、"柜员事务输进柜员终端"、"在ATM上输入远程事务"和"远程事务由现金兑换卡授权"
- 标明重数
ATM原始系统的原始类图
9.2.3 划分主题
为了降低复杂程度,可以把系统划分成不同主题,确定主题时我们应该按照问题领域而不是功能分解来进行划分。原则是使不同主题内的对象相互间依赖和交互最少
9.2.4 确定属性
1、选择
- 误把对象当属性
- 如果某个实体的独立存在比它的值更重要,则应该把它作为一个对象而不是对象的属性
- 误把关联类的属性当做一般对象的属性
- 把限定误当成属性
- 误把内部状态当成了属性
- 过于细化
- 存在不一致的属性
加上属性的实体类图
9.2.5 识别继承关系
-
一般说来,可以有两种方式建立继承关系
- 自底向上:抽象出现有类的共同性质泛化出父类
- 自顶向下:把现有类细化成子类
-
识别出继承关系的实体类图
9.2.6 反复修改
下面以ATM为例,讨论可能做的修改
- 分解“现金兑换卡类”
- 现金兑换卡有两独立功能:标志储户访问账号的权限;含有分行代码和卡号的数据载体。(卡权限和现金兑换卡)
- “事务”由“更新”组成
- 更新包括取款、存款、查询。有自己属性(类型、金额),应独立存在
- 合并“分行”和“分行计算机”
- 类似的应该合并“总行”与“中央计算机”
修改后的实体类图
第三节 建立动态模型
1、应用场景
- 开发交互式系统时,动态模型十分重要
2、建立动态模型的步骤
- 编写典型交互行为脚本
- 从脚本中提取事件及相关对象,用顺序图表达
- 确定对象状态及状态间转换关系,用状态图描绘
- 比较各个对象的状态图,确保事件之间的匹配性
9.3.1 编写脚本
1、定义
- 系统在某一执行期内出现的一系列事件
2、目的
- 保证不遗漏重要的交互步骤
3、范围
- 并不固定,主要由编写脚本的目的决定
4、顺序
- 首先编写正常情况下的脚本
- 考虑特殊情况
- 考虑出错情况
5、编写脚本示例:以ATM为例
- 正常情况
- ATM请储户插卡;储户插入一张现金兑换卡。
- ATM接受该卡并读它上面的分行代码和卡号。
- ATM要求储户输入密码;储户输入自己密码“1234”等数字。
- ATM请求总行验证卡号和密码;总行要求“39”号分行核对
- 储户密码,通知ATM这张卡有效。
- ATM要求储户选择事务类型(取款、转账、查询等);储户选择“取款”。
- ATM要求储户输入取款额;储户输人“880”
- 异常情况
- ATM请储户插卡;储户插入一张现金兑换卡。
- ATM接受该卡并读它上面的分行代码和卡号。
- ATM要求储户输入密码;储户误输入“8888”。
- ATM请求总行验证;总行向有关银行咨询后拒绝这张卡。
- ATM显示“密码错”,请用户重新输入密码;储户输入1234;
- ATM请总行验证后知道输入的密码正确
- ATM请储户选择事务类型;储户选择“取款”
- ATM询问用户取款额;储户不想取款,敲“取消”键
- ATM退出现金兑换卡,请储户拿走;储户拿走
- ATM请储户插卡
9.3.2 画顺序图
-
从脚本提取所有外部事件,确定每类事件发送和接收对象
-
针对系统中的典型功能,画出顺序图
-
ATM用户取款顺序图示例:

9.3.3 画状态图
-
用一张状态图描绘类的行为,集中考虑具有交互行为类
-
根据一张顺序图画出状态图之后,再把其他脚本的顺序图并进来
-
ATM类的状态图
-
总行类的状态图
-
分行类的状态图
第四节 建立功能模型
功能模型表明了数据之间的依赖关系以及有关的数据处理功能,它由一组数据流图组成
1、建立功能模型的步骤
- 画出基本系统模型图
- 画出功能级数据流图
- 描述处理框功能
2、画出基本系统模型图
-
基本系统模型由若干个数据源点和终点,及一个处理框组成,这个处理框代表了系统加工、变换数据的整体功能。基本模型指明了目标系统的边界
-
示例:ATM系统的基本系统模型
3、画出功能级数据流图
-
把基本模型中的单一处理框分解成若干个处理框,就可以得到功能级数据流图
-
示例:ATM系统的功能级数据流图
3、描述处理框功能
- 把数据流图细化分解到一定程度,就可以描述各个处理框功能了
- 描述可以是说明性的,也可以是过程性的
- 示例:ATM中更新账户这个处理功能的描述
- 更新账户(账号、事务类型、金额) -> 现金额、账单数据、信息
- 如果取款金额超过该账户当前金额,拒绝该事务且不付出现金
- 如果取款额不超过账户当前余额,从余额中减去取款额作为新的余额,付出储户要取的现金
- 如果事务是存款,把存款额追加到余额中得到新余额,不付出现金
- 如果事务是查询,不付出现金
- 在上述任何一种情况下,账单内容都是:ATM号,日期,时间,账号,事务类型,事务金额,新余额
第五节 定义服务
- 常规行为
- 定义类中每个属性都是可以访问的
- 从事件导出操作
- 与数据流图中处理框对应的操作
- 利用继承减少冗余操作
- 应该尽量利用继承机制减少所需定义的服务数目