软件工程理论与应用
上QQ阅读APP看书,第一时间看更新

2.5 面向对象分析方法

2.5.1 面向对象分析的基本思想

面向对象方法学是模拟人类思维方式,使开发软件过程与方法接近人类认识问题和解决问题的过程,有助于使问题描述空间与实现方法的解空间达到一致。问题空间都是由客观世界的实体和实体之间的联系构成。如学校的组成通常由教师和学生这两个基本实体构成,同时教师与学生存在着必然的联系。在软件开发过程中,面向对象方法学采用“对象”的概念,可以根据客观问题定义或选取空间对象,通过软件系统形成问题的解空间,达到问题空间与解空间的一致。

2.5.2 面向对象的基本概念

面向对象的软件技术以对象(Object)为核心,是对现实世界实体的正确抽象,把对象作为由数据及可以施加在数据上的操作所构成的整体,对象之间通过传递消息互相联系,以模拟现实世界中不同事物彼此之间的联系。下面给出几个常用的概念。

1.对象

对象是人们要进行研究的任何事物,从最简单的整数到复杂的飞机等均可看做对象,它不仅能表示具体的事物,还能表示抽象的规则、计划或事件。因此,在应用领域中有意义的、与所要解决的问题有关系的任何事物都可以作为对象,包括任何的实体、概念、事物等有意义的东西,如学生、教师、课程、学校、办公室、注册课程、政策、法规等均可作为对象。在软件系统中设立对象用来反映系统保存对象及其相关信息。

2.对象的状态和行为

对象具有状态,一个对象用数据值来描述它的状态。

对象还有操作,用于改变对象的状态,对象及其操作就是对象的行为。

对象实现了数据和操作的结合,使数据和操作封装于对象这个统一体中。

3.类

具有相同或相似性质的对象的抽象就是类。因此,对象的抽象是类,类的具体化就是对象,也可以说类的实例是对象。

类具有属性,它是对象的状态的抽象,用数据结构来描述类的属性。

类具有操作,它是对象的行为的抽象,用操作名和实现该操作的方法来描述。

4.类的结构

在客观世界中有若干类,这些类之间有一定的结构关系。通常有两种主要的结构关系,即一般-具体结构关系和整体-部分结构关系。

(1)一般-具体结构称为分类结构,也可以说是“或”关系,或者是“is a”关系。

(2)整体-部分结构称为组装结构,它们之间的关系是一种“与”关系,或者是“has a”关系。

5.消息和方法

对象之间进行通信的结构叫做消息。在对象的操作中,当一个消息发送给某个对象时,消息包含接收对象去执行某种操作的信息。发送一条消息至少要包括说明接收消息的对象名、发送给该对象的消息名(即对象名、方法名)。一般还要对参数加以说明,参数可以是认识该消息的对象所知道的变量名,或者是所有对象都知道的全局变量名。类中操作的实现过程叫做方法,一个方法有方法名、参数、方法体。

具体的对象类和对象实例如图2-24所示。这个雇员的对象类定义了有关公司所需要的雇员的基本信息,包括他们的姓名、性别、年龄等信息,同时列出与该对象类相关的一些操作,如可以对雇员进行基本信息的录入、修改、查找等基本操作。

图2-24 雇员对象类/对象的表示

2.5.3 面向对象分析步骤

面向对象的分析是建立问题域的对象模型,该模型描述了问题域的“类与对象”以及它们之间的关系。典型的工作步骤是:确定类和对象;确定关联;划分主题;确定属性;识别继承关系。

1.确定类和对象

通过分析找出系统应该具有的类与对象。首先,找出候选类与对象。对象是对问题域中有意义的事物的抽象。一般分为:

(1)可感知的客观实体,如书本、手机;

(2)人或组织机构,如学生、教师、学校、公司等;

(3)需要记录下来的事件,如登录、成绩;

(4)不同对象之间的作用关系,如选课、退课;

(5)需要说明的概念,如政策、法规等。

根据这五类的基本要求,找出当前问题域中存在的候选类与对象。

以一个自动化图书馆目录系统为例,这个系统包含图书馆中所有图书信息,要求该系统能够让图书管理员、借阅者和读者都可以使用,同时系统支持目录浏览、查询,允许用户发送消息给图书管理员预订在借图书。根据以上描述,客观实体本身有:图书馆、图书,管理员、借阅者、读者、用户,目录浏览、查询、预订,消息、在借图书、目录等,均可作为系统的对象或类。

进一步对上述所选对象进行筛选,去掉不正确的或不必要的,仅仅保留确实应该记录其信息或需要其提供服务的那些对象。如去掉冗余,用户与借阅者或读者有相同的含义,可以保留其中之一。

2.确定关联

多个对象之间的相互依赖、相互作用的关系形成了关联。在需求陈述中使用的描述性动词或动词词组,通常表示了关联关系。大多数的关联可以直接从需求陈述中的动词词组中获得,同时发现一些在陈述中隐含的关联,在进一步的深入探求中,可以获得领域实体之间的必然联系。如上文描述的图书馆目录系统中,直接的动词有浏览、查询、预订、发送消息等,形成的对象关系有图书管理员、借阅者、读者,他们可以浏览、预订、查询、发送消息给图书目录系统等。隐含的关系有图书管理员、借阅者、读者获得图书目录信息。同时在图书馆信息系统中必然包含图书数量、缺书登记、新书公告等相关说明。如果考虑相关的说明,或隐含的必然的管理内容,要筛选和删除无关的对象之间的关系。

3.划分主题

一般来说软件系统的开发为降低系统的复杂程度,通常把系统再进一步划分成几个不同的主题,也就是按照问题域的特点把系统分解为几个子系统,保证不同主题内的对象相互之间的依赖和交互尽可能得少。根据自动化图书馆目录系统的描述,可以按照对象的类别进行划分,如可以按管理者与使用者划分,也可以按目录类与消息类划分。

4.确定属性

属性是对象的性质,可以在需求描述中寻找与某一对象相关的性质,但往往需求描述中所给出的不够详细,或者对象本身所具有的内在性质,都可以成为对象属性,因此,在分析对象属性时,可以借助领域知识和常识进行分析,获得对象的属性。属性的确定直接与问题域和目标系统的任务有关,应该仅仅考虑与具体任务直接相关的属性。如学生类中某名学生张三为对象,该对象可能根据实际任务的要求,确定学号、姓名、年龄、成绩等为其属性。

5.识别继承关系

确定类中应有的属性,继而利用继承关系共享公共性质,实现知识抽取的过程。可以根据实际的领域知识,归纳客观世界的分类模式。

2.5.4 面向对象分析实例

银行网络系统问题陈述:设计支持银行网络的软件,银行网络包括人工出纳站和分行共享的自动出纳机。每个分理处用分理处计算机来保存各自的账户,处理各自的事务;各分理处的出纳站与分理处计算机通信,出纳站录入账户和事务数据;自动出纳机与分行计算机通信,分行计算机与拨款分理处结账,自动出纳机与用户接口接受现金卡,与分行计算机通信完成事务,发放现金,打印收据;系统需要记录保管和安全措施;系统必须正确处理同一账户的并发访问;每个分理处为自己的计算机准备软件,银行网络费用根据顾客和现金卡的数目分摊给各分理处。

建立对象模型:首先标识和关联,因为它们影响了整体结构和解决问题的方法;其次是增加属性,进一步描述类和关联的基本网络,使用继承合并和组织类;最后将操作增加到类中去作为构造动态模型和功能模型的副产品。

1.确定类

构造对象模型的第一步是标出来自问题域的相关的对象类,对象包括物理实体和概念。所有类在应用中都必须有意义,在问题陈述中,并非所有类都是明显给出的。有些是隐含在问题域或一般知识中的。

查找问题陈述中的所有名词,产生如下的暂定类:软件、银行网络、出纳员、自动出纳机、分行、分理处、分理处计算机、账户、事务、出纳站、事务数据、分行计算机、现金卡、用户、现金、收据、系统、顾客、费用、账户数据、访问、安全措施、记录保管。

根据下列标准,去掉不必要的类和不正确的类。

(1)冗余类:若两个类表述了同一个信息,保留最富有描述能力的类。如“用户”和“顾客”就是重复的描述,因为“顾客”最富有描述性,所以保留它。

(2)不相干的类:除掉与问题没有关系或根本无关的类。例如,摊派费用超出了银行网络的范围。

(3)模糊类:类必须是确定的,有些暂定类边界定义模糊或范围太广,如“记录保管”就是模糊类,它是“事务”中的一部分。

(4)属性:某些名词描述的是其他对象的属性,则从暂定类中删除。如果某一性质的独立性很重要,就应该把它归属到类,而不把它作为属性。

(5)操作:如果问题陈述中的名词有动作含义,则描述的操作就不是类。但是具有自身性质而且需要独立存在的操作应该描述成类。如只构造电话模型,“拨号”就是动态模型的一部分而不是类;但在电话拨号系统中,“拨号”是一个重要的类,有日期、时间、受话地点等属性。

在银行网络系统中,模糊类有“系统”、“安全措施”、“记录保管”、“银行网络”等。属于属性的有:“账户数据”、“收据”、“现金”、“事务数据”;属于实现的有:“访问”、“软件”等,这些均应除去。

2.确定关联

两个或多个类之间的相互依赖就是关联。一种依赖表示一种关联,可用各种方式来实现关联,但在分析模型中不用考虑,以便设计时更为灵活。关联常用描述性动词或动词词组来表示,其中有物理位置的表示、传导的动作、通信、所有者关系、条件的满足等。从问题陈述中抽取所有可能的关联表述,把它们记下来,但不要过早去细化这些表述。

下面是银行网络系统中所有可能的关联,大多数是直接抽取问题中的动词词组而得到的。在陈述中,有些动词词组表述的关联是不明显的。最后,还有一些关联与客观世界或人的假设有关,必须同用户一起核实这种关联,因为这种关联在问题陈述中找不到。

银行网络问题陈述中的关联:

● 银行网络包括出纳站和自动出纳机;

● 分行共享自动出纳机;

● 分理处提供分理处计算机;

● 分理处计算机保存账户;

● 分理处计算机处理账户支付事务;

● 分理处拥有出纳站;

● 出纳站与分理处计算机通信;

● 出纳员为账户录入事务;

● 自动出纳机接受现金卡;

● 自动出纳机与用户接口;

● 自动出纳机发放现金;

● 自动出纳机打印收据;

● 系统处理并发访问;

● 分理处提供软件;

● 费用分摊给分理处。

隐含的动词词组:

● 分行由分理处组成;

● 分理处拥有账户;

● 分行拥有分行计算机;

● 系统提供记录保管;

● 系统提供安全;

● 顾客有现金卡。

基于问题域知识的关联:

● 分理处雇佣出纳员;

● 现金卡访问账户。

使用下列标准去掉不必要和不正确的关联:

(1)相关的关联:若某个类已被删除,那么与它有关的关联也必须删除或者用其他类来重新表述。在此例中,我们删除了“银行网络”,相关的关联也要删除。

(2)不相干的关联或实现阶段的关联:删除所有问题域之外的关联或涉及实现结构中的关联。如“系统处理并发访问”就是一种实现的概念。

(3)动作:关联应该描述应用域的结构性质而不是瞬时事件,因此应删除“自动出纳机接受现金卡”,“自动出纳机与用户接口”等。

(4)派生关联:省略那些可以用其他关联来定义的关联。因为这种关联是冗余的,其中含有关联。

3.划分主题

可以将银行按地理位置划分,也可以按不同的处理级别划分,如总行、分理处、ATM进行划分。

4.确定属性

属性是个体对象的性质,属性通常用修饰性的名词词组来表示,形容词常常表示具体的可枚举的属性值,属性不可能在问题陈述中完全表述出来,必须借助于应用域的知识及对客观世界的知识才可以找到它们。只考虑与具体应用直接相关的属性,不要考虑那些超出问题范围的属性。首先找出重要属性,避免那些只用于实现的属性,要为各个属性取有意义的名字。按下列标准删除不必要的和不正确的属性。

(1)对象:若实体的独立存在比它的值重要,那么这个实体不是属性而是对象。如在邮政目录中,“城市”是一个属性,然而在人口普查中,“城市”则被看做是对象。在具体应用中,具有自身性质的实体一定是对象。

(2)限定词:若属性值取决于某种具体上下文,则可考虑把该属性重新表述为一个限定词。

(3)名称:名称常常作为限定词而不是对象的属性,当名称不依赖于上下文关系时,名称即为一个对象属性,尤其是它不唯一时。

(4)标识符:在考虑对象模糊性时,引入对象标识符表示,在对象模型中不列出这些对象标识符,它是隐含在对象模型中,只列出存在于应用域的属性。

(5)内部值:若属性描述了对外不透明的对象的内部状态,则应从对象模型中删除该属性。

(6)细化:忽略那些不可能对大多数操作有影响的属性。

5.使用继承来细化类

使用继承来共享公共机构,以此来组织类,可以用两种方式来进行。

(1)自底向上通过把现有类的共同性质一般化为父类,寻找具有相似的属性、关系或操作的类来发现继承。例如“远程事务”和“出纳事务”是类似的,可以一般化为“事务”。有些一般化结构常常是基于客观世界边界的现有分类,只要可能,就尽量使用现有概念。对称性常有助于发现某些丢失的类。

(2)自顶向下将现有的类细化为更具体的子类。具体化常常可以从应用域中明显看出来。应用域中各枚举字情况是最常见的具体化的来源。例如:菜单,可以有固定菜单、顶部菜单、弹出菜单、下拉菜单等,这就可以把菜单类细化为各种具体菜单的子类。当同一关联名出现多次且意义也相同时,应尽量具体化为相关联的类,例如,“事务”从“出纳站”和“自动出纳机”进入,则“录入站”就是“出纳站”和“自动出纳站”的一般化。在类层次中,可以为具体的类分配属性和关联。各属性和关联都应分配给最一般的适合的类,有时也加上一些修正。

6.完善对象模型

对象建模不可能一次就能保证模型是完全正确的,软件开发的整个过程就是一个不断完善的过程。模型的不同组成部分多半是在不同的阶段完成的,如果发现模型的缺陷,就必须返回到前期阶段去修改,有些细化工作是在动态模型和功能模型完成之后才开始进行的。

(1)几种可能丢失对象的情况及解决办法。

①同一类中存在毫无关系的属性和操作,则分解这个类,使各部分相互关联。

②一般化体系不清楚,则可能分离扮演两种角色的类。

③存在无目标类的操作,则找出并加上失去目标的类。

④存在名称及目的相同的冗余关联,则通过一般化创建丢失的父类,把关联组织在一起。

(2)查找多余的类。类中缺少属性、操作和关联,则可删除这个类。

(3)查找丢失的关联。丢失了操作的访问路径,则加入新的关联以回答查询。

(4)视网络系统的具体情况做如下的修改。

①现金卡有多个独立的特性。把它分解为两个对象:卡片权限和现金卡。

卡片权限:它是银行用来鉴别用户访问权限的卡片,表示一个或多个用户账户的访问权限;各个卡片权限对象中可能具有好几个现金卡,每张都带有安全码和卡片码,它们附在现金卡上,表现银行的卡片权限。

现金卡:它是自动出纳机得到表示码的数据卡片,它也是银行代码和现金卡代码的数据载体。

②“事务”不能体现对账户之间的传输描述的一般性,因它只涉及一个账户,一般来说,在每个账户中,一个“事务”包括一个或多个“更新”,一个“更新”是对账户的一个动作,它们是取款、存款、查询之一。一个“更新”中所有“更新”应该是一个原子操作。

③“分理处”和“分理处计算机”之间,“分行”和“分行计算机”之间的区别似乎并不影响分析,计算机的通信处理实际上是实现的概念,将“分理处计算机”并入到“分理处”,将“分行计算机”并入到“分行”。