十、面向对象分析
面向对象分析的基本过程
面向对象分析就是抽取和整理用户需求并建立问题域精确模型的过程。
步骤:
- 分析需求陈述(多次与用户协商,快速建立计算机原型系统)
- 深入理解用户需求,抽象出目标系统的本质属性,并用模型准确表示
目的:
全面深入地理解问题域和用户的真实需求,建立问题域的精确模型。
3个结构5个层次
3个结构:静态结构、交互次序和数据变换。
复杂问题的对象模型由下述五层次组成:主题层、类与对象层、结构层、属性层和服务层。
面向对象分析的主要活动:
- 找出类与对象
- 识别结构
- 识别主题
- 定义属性
- 定义服务
上述过程可以大体上按照下列顺序执行:
a. 寻找类与对象;
b. 识别结构;
c. 识别主题;
d. 定义属性;
e. 建立动态模型;
f. 建立功能模型;
g. 定义服务。
建模要点:
a. 面向对象分析不可能严格按照顺序线性进行。
b. 必须在反复分析中对初始模型中不准确、不完整和错误的内容加以扩充和更正。
c. 仔细研究类似问题的分析结果,尽可能重用这些结果。
需求陈述
内容
(1) 阐明“做什么”而不是“怎样做"。
(2) 描述用户的需求而不是提出解决问题的方法。
(3) 指出哪些是系统必要的性质,哪些是任选的性质。
(4) 避免对设计策略施加过多的约束,不描述系统的内部结构。
(5) 描述系统性能及系统与外界环境交互协议。
(6) 描述釆用的软件工程标准、模块构造准则、将来的扩充以及可维护性要求等方面。
书写规范
(1) 做到语法正确,而且应该慎重选用名词、动词、形容词和同义词。
(2) 必须把需求与实现策略区分开,后者不是问题域的本质性质。
(3) 需求陈述可简可繁。
(4) 避免出现具有二义性的、不完整的、不一致的内容。
建立对象模型
面向对象分析的首要工作,是建立问题域的对象模型。对象模型描述了现实世界中的“类与对象”以及它们之间的关系,表示了目标系统的静态数据结构。
步骤:
① 确定对象类和关联(对于大型复杂问题还要进一步划分出若干个主题);
② 给类和关联增添属性,以进一步描述它们;
③ 使用适当的继承关系进一步合并和组织类。
确定类与对象
步骤:
-
找出候选的类与对象
-
筛选出正确的类与对象
在筛选时,按照以下标准,删除不正确或不必要的类和对象
- 冗余(两个类表达重复信息)
- 无关(类与问题不相干)
- 笼统(陈述过于泛泛)
- 属性(有些名词是其他类的属性)
- 操作(有些既可以当动词也可以当名词的词语要考虑其含义)
- 实现(去掉仅和实现相关的对象)
确定关联
步骤:
(1)初步确定关联
在需求陈述中使用的描述性动词或动词词组通常表示关联关系。
步骤:
a. 直接提取动词短语得出的关联。
b. 需求陈述中隐含的关联。
c. 根据问题域知识得出的关联。
(2)筛选
a. 已删去的类之间的关联
如果在分析确定类与对象的过程中已经删掉了某个候选类,则与这个类有关的关联也应该删去,或用其他类
重新表达这个关联。
b. 与问题无关的或应在实现阶段考虑的关联
应该把处在本问题域之外的关联与实现密切相关的关联删去。
c. 瞬时事件
关联应该描述问题域的静态结构,而不应该是一个瞬时事件
d. 三元关联
三个或三个以上对象间的关联,可分解为二元关联或用词组描述成限定的关联。
e. 派生关联
去掉那些可以用其他关联定义的冗余关联。
(3)进一步完善
进一步完善经删选后余下的关联,通常从下述几方面进行改进:
- 正名
- 分解
- 补充
- 标明重数
划分主题
1、定义
在开发大型、复杂系统的过程中,为了降低复杂程度,把系统再进一步划分成几个不同的主题,即在概念上
把系统包含的内容分解成若干个范畴。
2、针对不同类型的方法
① 规模小的系统
可能无须引入主题层。
② 含有较多对象的系统
首先识别出类与对象和关联,然后划分主题,并用它作为指导开发者和用户观察整个模型的一种机制。
③ 规模大的系统
首先由高级分析员粗略地识别对象和关联,然后初步划分主题,经进一步分析,对系统结构有更深入的了解
之后,再进一步修改和精炼主题。
3、原则
① 按问题领域而不是用功能分解方法来确定主题。
② 按照使不同主题内的对象相互间依赖和交互最少的原则来确定主题。
确定属性
属性是对象的性质,藉助于属性人们能对类与对象和结构有更深入更具体的认识。
分析和选择两个步骤:
①分析
a. 在需求陈述中用名词词组表示属性,用形容词表示可枚举的具体属性。
b. 借助于领域知识和常识分析需要的属性。
c. 仅考虑与具体应用直接相关的属性,不要考虑那些超出所要解决的问题范围的属性。
d. 首先找出最重要的属性,以后再逐渐把其余属性增添进去。
e. 不要考虑那些纯粹用于实现的属性。
②选择
从初步分析确定下来的属性中删掉不正确的或不必要的属性。有以下几种常见情况:
a. 误把对象当作属性
如果某个实体的独立存在比它的值更重要,则应把它作为一个对象而不是对象的属性。
b. 误把关联类的属性当作一般对象的属性
如果某个性质依赖于某个关联链的存在,则该性质是关联类的属性,在分析阶段不应把它作为一般对象的属
性。
c. 把限定误当成属性
如果把某个属性值固定下来以后能减少关联的重数,则应该考虑把这个属性重新表达成一个限定词。
d. 误把内部状态当成了属性
如果某个性质是对象的非公开的内部状态,则应该从对象模型中删除这个属性。
e. 过于细化
在分析阶段应该忽略那些对大多数操作都没有影响的属性。
f. 存在不一致的属性
类应该是简单而且一致的。如果得出一些看起来与其他属性毫不相关的属性,则应该考虑把类分解成两个不
同的类。
识别类与继承关系
(1)建立继承关系的方式
确定了类中应该定义的属性之后,就可以利用继承机制共享公共性质,并对系统中众多的类加以组织。可以
使用以下两种方式建立继承关系。
① 自底向上
抽象出现有类的共同性质泛化出父类,这个过程实质上模拟了人类归纳思维的过程。
② 自顶向下
把现有类细化成更具体的子类,这模拟了人类的演绎思维过程。从应用域中常常能明显看出应该做的自顶向
下的具体化工作。
在使用多重继承机制时,通常要制定一个主要父类,从他继承的大部分属性和行为;次要父类只补充一些属性和行为。
动态模型
在开发交互式系统时,动态模型却起着很重要的作用。收集输入信息是系统的主要工作时,则在开发时建立正确的动态模型是至关重要的。
一般步骤如下:
- 编写点型交互行为的脚本
- 从脚本中提取出事件
- 排列事件发生的次序
- 比较各个对象状态图,检查一致性
编写脚本
(1) 定义
脚本是指系统在某一执行期间内出现的一系列事件。脚本描述用户与目标系统之间的一个或多个典型的交互
过程。编写脚本的过程,就是分析用户对系统交互行为的要求的过程。
(2) 目的
编写脚本的目的是保证不遗漏重要的交互步骤,有助于确保交互过程的正确性、清晰性。
(3) 内容
脚本描写的范围主要由编写脚本的具体目的决定,既可以包括系统中发生的全部事件,也可以只包括由某些
特定对象触发的事件。
(4) 方法
① 编写正常情况的脚本;
② 考虑特殊情况;
③ 考虑出错情况。
设想用户界面
大多数交互行为都可以分为应用逻辑和用户界面两部分,通常,系统分析员首先集中精力考虑系统的信息流
和控制流,而不是首先考虑用户界面。
(1) 重要性
用户界面的美观程度、方便程度、易学程度以及效率等,是用户使用系统时最先感受到的。用户界面的好坏
往往对用户是否喜欢、是否接受一个系统起很重要的作用。
(2) 目的
这个阶段用户界面的细节并不太重要,重要的是在这种界面下的信息交换方式。目的是确保能够完成全部必
要的信息交换,而不会丢失重要的信息。
(3) 方法
快速地建立起用户界面的原型,供用户试用与评价。
画事件跟踪图
步骤:
(1)确定事件
(2)画事件跟踪图
(2)画出事件跟踪图
a. 一条竖线代表一个对象;
b. 每个事件用一条水平的箭头线表示;
c. 箭头方向从事件的发送对象指向接受对象;
d. 时间从上向下递增;
e. 用箭头线在垂直方向上的相对位置表示事件发生的先后,不表示事件间的时间差。
下面是一个例子
画状态图
状态图描绘事件与对象状态的关系。当对象接受了一个事件以后,它的下个状态取决于当前状态及所接受的事件。由事件引起的改变称为“转换”。一张状态图描绘了一类对象的行为,它确定了由事件序列引出的状态序列。
方法:
① 仅考虑事件跟踪图中指向某条竖线的那些箭头线。把这些事件作为状态图中的有向边,边上标以事件名。
② 两个事件之间的间隔就是一个状态,每个状态取个有意义的名字。从事件跟踪图中当前考虑的竖线射出的
箭头线,是这条竖线代表的对象达到某个状态时所做的行为。
③ 根据一张事件跟踪图画出状态图后,再把其他脚本的事件跟踪图合并到该图中。
④ 考虑完正常事件后再考虑边界情况和特殊情况,包括在不适当时候发生的事件。
审查动态模型
- 要检查系统的完整性和一致性
- 审查每个事件,跟踪他对系统中各个对象所产生的效果,保证与每个对象相匹配。
功能模型
功能模型表明了系统中数据之间的依赖关系,以及有关的数据处理功能,它由一组数据流图构成。
步骤:
(1)画出系统模型图
(2)画出功能级数据流图
(3)描述系统功能
着重描述每个处理框所代表的功能,而不是实现功能的具体算法。
分类:
①说明性描述
说明性描述规定了输入值和输出值之间的关系,以及输出值应遵循的规律。
②过程性描述
过程性描述则通过算法说明“做什么”。
定义服务
(1) 常规行为
无须在类图中显式表示读、写该类每个属性的常规操作
(2) 从事件导出的操作
状态图中发往对象的事件也就是该对象接收到的消息,因此该对象必须有由消息选择符指定的操作,这个操
作修改对象状态并启动相应的服务。
(3) 与数据流图中处理框对应的操作
数据流图中的每个处理框都与一个对象上的操作相对应。应该仔细对照状态图和数据流图,以便更正确的确
定对象应该提供的服务。
(4) 利用继承减少冗余操作
应该尽量利用继承机制以减少所需的服务数目。
课后题
这章的课后题基本都为分析题,各位可以自己看看。