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