软件工程中文讲义6文档格式.docx
《软件工程中文讲义6文档格式.docx》由会员分享,可在线阅读,更多相关《软件工程中文讲义6文档格式.docx(92页珍藏版)》请在冰点文库上搜索。
在过程性范型中优先考虑的是过程抽象,而在面向对象范型中优先考虑的是实体,即问题论域的对象。
在面向对象范型中,把标识和模型化问题论域中的主要实体做为系统开发的起点,主要考虑对象的行为而不是必须执行的一系列动作。
面向对象系统中的对象是数据抽象与过程抽象的综合。
系统的状态保存在各个数据抽象的核心所定义的数据存储中。
控制流包含在各个数据抽象中的操作内。
不像在过程性范型里那样,把数据从一个过程传送到另一个过程,而是把控制流从一个数据抽象通过消息传送到另一个数据抽象。
完成的系统体系结构更复杂但也更灵活,如图6.2(b)所示。
把控制流分离成块,这样可以把复杂的动作视为各个局部间的相互作用。
图6.1 过程性系统和面向对象系统的基本构造
④面向进程的范型:
面向进程的范型是把一个问题分解成独立执行的模块。
让不只一个程序同时运行。
这些进程互相配合,解决问题。
面向进程范型产生的主要的块是进程。
一个进程中的活动独立于其它进程的活动,但可以要求从其它进程得到信息,或为其它进程提供信息。
甚至可以异步处理,仅需要进程暂停发送或接收信息。
在面向对象范型中,各个对象是相对独立的,但也存在单线索(单线程)控制。
面向进程范型支持与面向对象范型相同的封装,但可提供多线索(多线程)执行。
图6.2一个智能数据分析系统
⑤混合范型:
在大型系统的开发中,很难说哪种范型对整个问题的解决最好。
系统开发现在有一种补充步骤,可把大型问题分解成一组子问题。
对于每个子问题可以采用适当的软件范型。
例如,设计一个智能数据分析系统时,可把它分解为4个子系统,如图6.2所示。
系统的数据库界面,可以使用面向对象的方法进行设计;
智能数据分析用逻辑范型设计;
而分析算法则是过程性的;
系统通过一个用户界面来实用化,这个用户界面是用面向存取范型设计出来的。
这种设计需要有某种实现语言或一组协同语言的支持。
许多流行的功能不断增强的语言支持不只一种设计范型。
对于混合范型,现在已经存在不少技术。
像C++和并发C这样的语言都是多范型语言,支持过程性范型和面向对象范型。
并发C还支持面向进程范型。
系统可以使用单一的语言,利用两种或多种范型写成。
还可以利用可共享数据格式和连接规约的某些语言,把用这些语言分别编写的块链接到某个单一的应用中去。
(2)面向对象的概念
关于“面向对象”,有许多不同的看法。
Coad和Yourdon给出了一个定义:
“面向对象=对象+类+继承+消息通信”。
如果一个软件系统是使用这样4个概念设计和实现的,则认为这个软件系统是面向对象的。
一个面向对象的程序的每一成份应是对象,计算是通过新的对象的建立和对象之间的消息通信来执行的。
(3)对象(object)
图6.3对象的定义
家具
属性
价格
尺寸
重量
位置
颜色
桌子
一般意义来讲,对象是现实世界中存在的一个事物。
可以是物理的,如一个家具或桌子,如图6.3所示,可以是概念上的,如一个开发项目。
对象是构成现实世界的一个独立的单位,具有自己的静态特征(用数据描述)和动态特征(行为或具有的功能)。
例如:
人的特征:
姓名、性别、年龄等,行为:
衣、食、住、行等。
①对象、属性、操作、消息定义
服务
购买
销售
称重
移动
对象可以定义为系统中用来描述客观事物的一个实体,它是构成系统的一个基本单位,由一组属性和一组对属性进行操作的服务组成。
属性一般只能通过执行对象的操作来改变。
操作又称为方法或服务,在C++中称为成员函数,它描述了对象执行的功能,若通过消息传递,还可以为其它对象使用。
而所谓的消息是一个对象与另一个对象的通信单元,是要求某个对象执行类中定义的某个操作的规格说明。
发送给一个对象的消息定义了一个操作名和一个参数表(可能是空的),并指定某一个对象。
由一个对象接收的消息则调用消息中指定的操作,并将传递过来的实际参数与参数表中相应的形式参数结合起来。
接收对象对消息的处理可能会改变对象中的状态,即改变接收对象的属性,并发送一个消息给自己或另一个对象。
可以认为,这种消息的传递大致等价于过程性范型中的函数调用。
②对象的分类
外部实体:
与软件系统交换信息的外部设备、相关子系统、操作员或用户等。
信息结构:
问题信息域中的概念实体,如信号、报表、显示信息等。
需要记忆的事件:
在系统运行过程中可能产生并需要系统记忆的事件,如单击鼠标左键、击打键盘“”键等。
角色:
与软件系统交互的人员所扮演的角色,如经理、部长、技术支持等。
组织机构:
有关机构,如单位、小组等。
位置:
作为系统环境或问题上下文的场所、位置,如客户地址、收件人(机构)地址等。
操作规程:
如操作菜单、某种数据输入过程等。
在标识对象时必需注意遵循“信息隐蔽”的原则:
必需将对象的属性隐藏在对象的内部,使得从对象的外部看不到对象的信息是如何定义的,只能通过该对象界面上的操作来使用这些信息。
对象的状态通过给对象赋予具体的属性值而得到。
它只能通过该对象的操作来改变。
对象有两个视图,分别表现在分析设计和实现方面。
从分析及设计方面来看,对象表示了一种概念,它们把有关的现实世界的实体模型化。
从实现方面来看,一个对象表示了在应用程序中出现的实体的实际数据结构。
之所以有两个视图,是为了把说明与实现分离,对数据结构和相关操作的实现进行封装。
(4)类(class)和实例(instance)
把具有相同特征和行为的对象归在一起就形成了类。
类成为某些对象的模板,抽象地描述了属于该类的全部对象的属性和操作。
属于某个类的对象叫做该类的实例。
对象的状态则包含在它的实例变量,即实例的属性中。
如图6.4所示。
从“李杰”、“王辉”和“杨芳”等对象可得到类“学生”,而这些对象就称为该类的实例。
类定义了各个实例所共有的结构,类的每一个实例都可以使用类中定义的操作。
实例的当前状态是由实例所执行的操作定义的。
李杰
王辉
杨芳
学生
男
广东
软件
1980.4
9#楼129室
湖南
计算机控制
1979.1
9#楼320室
女
北京
系统结构
1979.12
5#楼418室
姓名
性别
籍贯
专业
出生年月
住址
看书
实验
上课
运动
图6.4对象、类与实例
面向对象程序设计语言,如C++和smalltalk都定义了一个new操作,可建立一个类的新实例。
C++还引入了构造函数,用它在声明一个对象时建立实例。
此外,程序设计语言给出了不同的方法,来撤消(称为析构)实例,即当某些对象不再使用时把它们删去,把存储释放以备其它对象使用。
C++给出了一个操作delete,可以释放一个对象所用的空间。
C++还允许每个类定义自己的析构方法,在撤消一个对象时调用它。
smalltalk没有提供一个机制来撤消对象,但可以进行无用单元收集。
类常常可看做是一个抽象数据类型(ADT)的实现。
但更重要的是把类看做是表示某种概念的一个模型。
事实上,类是单个的语义单元,它可以很自然地管理系统中的对象,匹配数据定义与操作。
类加进了操作,给通常的记录赋予了语义,可提供各种级别的可访问性。
(5)继承(inheritance)
如果某几个类之间具有共性的东西(信息结构和行为),抽取出来放在一个一般类中,而将各个类的特有的东西放在特殊类中分别描述,则可建立起特殊类对一般类的继承。
如图6.5所示,。
各个特殊类可以从一般类中继承共性,这样避免了重复。
汽车
运货车
救火车
起重车
大轿车
图6.5特殊类对一般类的继承关系
图6.6多继承
建立继承结构的好处:
教师
易编程、易理解代码短,结构清晰;
退休者
易修改:
共同部分只要在一处修改即可;
易增加新类:
只须描述不同部分。
(6)多继承
退休教师
如果一个类需要用到多个既存类的特征,可以从多个类中继承,称为多继承。
例如退休教师是继承退休者和教师这两个类的某些特征或行为而得到的一个新类。
(7)多态性和动态绑定
对象互相通信,即一个对象发消息给另一个对象,执行某些行为或又发消息给另外的对象,从而执行系统的功能。
发送消息的对象可能不知道另一个对象的类型是什么。
如在C程序中使用命令ClearInt()时要严格区分该命令适合一个整数,还是一个整数数组。
但在C++情形,ClearInt()对两者都适用,它自己判断对象是哪一个。
这就是多态性。
它意味着一个操作在不同类中可以有不同的实现方式。
如清零操作ClearInt()针对消息对象是intarray还是int,其实现是不同的。
在一个面向对象的多态性语言中,可能代替一个特定类型的类型的集合就是它的子类集合。
图6.74个类的继承层次
三角形
多边形
四边形
例如,图6.7给出了4个类的继承层次。
使用这个继承结构,发送给多边形类的所有消息,它的所有子类都能够响应。
又例如,想要在屏幕上画一系列多边形,多态性允许一个表的元素可以属于一组指定的类型而不仅仅是一个类型,可以认为这是一个类族。
通过遍历这个表,发送给各个表元素以draw消息,画出所有的多边形。
矩形
动态绑定把函数调用与目标代码块的连接延迟到运行时进行。
这样,只有发送消息时才与接收消息实例的一个操作绑定。
它与多态性可以使我们建立的系统更灵活,易于扩充。
做为动态绑定的例子,考虑在多边形类中的方法contains?
(aPoint)。
这个操作可以在类层次的各层重新实现,以有效利用各个子类的特殊的特征。
例如,假定一个矩形有某些边与屏幕的边平行,这时,检查一个点是否包含在矩形内,比检查一个点是否在一个一般的四边形内的效率要高一些。
2.面向对象软件的开发过程
面向对象范型不仅是一些具体的软件开发技术与策略,而且是一整套关于如何看待软件系统与现实世界的关系以及如何进行系统构造的软件方法学。
用面向对象开发方法构造的软件具有以下特点:
面向对象的技术建立的模型与客观世界一致,因而便于理解;
适应变化的需要,修改局限在模块中;
可复用性。
(1)应用生存期
图6.8给出应用生存期模型。
在图中各个阶段的顺序是线性的,但实际上开发过程不是线性的。
还没有办法用图来逼真地反映在面向对象开发过程中各个阶段之间的复杂交互。
有一部分分析工作在设计之前实行,但有些分析工作与其它部分的设计与实现并行进行。
图6.8一个基于复用的应用生存期
开发可复用的软件构件是软件开发过程的一部分。
面向对象方法以类作为单元,并分别考虑类的生存期与应用生存期。
类生存期可包含在图6.8中的类开发阶段中,可与应用生存期集成。
(2)类生存期
图6.9类生存期
在面向对象软件开发过程中特别重视复用。
软件构件应独立于当初开发它们的应用而存在。
构件的开发瞄准某些局部的设计和实现,它们可用于当前问题的解决,但为了在以后的项目中使用,它们还应当足够通用。
在以后的应用开发中,可以调整这些独立构件以适应新问题的需要。
因此,应使得类成为一个可复用的单元,图6.9提出了一个类生存期。
类生存期与应用生存期交叉。
在应用生存期的每一个阶段都可做类的标识。
类生存期有自己的步骤,与任一特定应用的开发无关。
按照这些步骤,可以完整地描述一个基本实体。
而不仅仅考虑当前正在开发的系统。
系统开发的各个阶段都可能会标识新的类。
随着各个新类的标识,类生存期引导开发工作逐个阶段循序渐进。
例如,在应用分析中已经标识了对一个图形显示设备的要求。
如果这样一个图形显示设备类不存在,就应着手开发。
但是,用到显示器所有可能操作的应用寥寥无几。
若把这些操作的开发当做一个特定应用系统开发的一部分,那么只可能标识和实现该系统所要求的那些操作。
但如果考虑让构件独立于应用,就必须能够综合出超出当前系统需求的开发要求,生成一种能表示成一个完全的概念的模型并可建立为以后其它系统复用的类。
在纯面向对象的系统开发中,一个应用程序就“是”一个类。
基本的类,像list类,可不涉及应用,但基本类的实例要聚合到其它类的定义中。
这些类依次又聚合到更复杂的类定义中,最终将会遇到一个类,它涉及整个应用。
下面概括了类生存期各个阶段主要做的事情。
①类的规格说明:
对每一个类都要开发它的规格说明,无论是在哪一个阶段标识的类都是如此。
类的规格说明定义了施加于对象的数据存储上的一组操作。
这组操作应工作在封装在对象内部的数据存储上,或返回关于对象状态的信息。
操作的名字应能反映这个操作本身的含义。
类的规格说明必须足够完整,使得它能够与在类资源库中的那些可复用的类的规格说明做比较。
②类的设计与实现:
此时尽可能利用既存类提供为当前应用所需要的功能。
图6.9给出了利用既存类的三个途径:
原封不动地复用既存类。
对既存类进行演化以得到满足要求的类。
演化可以是横向的,也可以是纵向的。
横向的演化生成既存类的一个新的版本,而纵向的演化将从既存类导出新类。
重新开始进行开发。
一个新的继承结构将建立两种类:
一种是抽象类,它概括了将要表达的概念;
另一种是具体类,它要实现这个概念。
③求精和维护:
维护活动是针对应用系统的,但求精过程是针对类和结构的。
因为我们利用抽象进行开发,因此,维护活动每时每刻都可能修改这些抽象。
随着经验的增长,还可以标识抽象的抽象,使得继承结构通过一般化,增加新的层次。
为便于类的调整,应尽量做到定义与实现分离,实现概念封装和信息隐蔽,使得类具有更大的独立性。
在使用一个类或复用一个类时,类与类之间产生一种相互依赖关系。
但对一个类的公有界面所做的多次修改不应影响使用它的那些类,在公有界面上增加新的操作不应改变既存的软件。
需要谨慎处理的是删除操作或改变操作的特征。
(3)面向对象软件的开发过程
面向对象软件的开发过程开始于问题论域,经历从问题提出到解决的一系列过程。
下面具体说明在过程中的这些步骤。
①分析阶段:
分析阶段包括两个步骤:
论域分析和应用分析。
它们都要标识问题论域中的抽象。
在分析中,需要找到特定对象,基于对象的公共特性把它们组合成集合,标识出对这个问题的一个抽象。
同时要标识抽象之间的关系,并建立对象之间的消息连接。
论域分析:
论域分析开发问题论域的模型。
论域分析应当在应用分析之前进行,我们在了解问题之前应当对问题敞开思想考虑,考察问题论域内的一个较宽的范围,分析覆盖的范围应比直接要解决的问题更多。
应用分析:
应用(或系统)分析细化在论域分析阶段所开发出来的信息,并且把注意力集中于当前要解决的问题。
因为通过论域分析,分析人员具有了较宽的论域知识,因而能开发出更好的抽象。
②高层设计:
在一个纯面向对象环境中,软件体系结构设计与类设计常常是同样的过程,但还是应当把体系结构设计与类的设计分开。
在高层设计阶段,设计应用系统的顶层视图。
这相当于开发一个代表系统的类,通过建立该类的一个实例并发送一个消息给它来完成系统的“执行”。
③类的开发:
根据高层设计所标识的对各个类的要求和类的规格说明,进行类的开发。
因为一个应用系统往往是一个类的继承层次。
对这些类的开发是最基本的设计活动。
④实例的建立:
建立各个对象的实例,实现问题的解决方案。
⑤组装测试:
按照类与类之间的关系组装一个完整的应用系统的过程中进行的测试。
各个类的封装和类测试的完备性可减少组装测试所需要的时间。
⑥维护:
维护的要求将影响应用和各个类。
继承关系可支持对现有应用的扩充,或者加入新的行为,或者改变某些行为的工作方式。
应用系统的维护:
包括在系统的操作中定位故障、在既存的系统中加入新的行为。
应用的维护能够简化对类实例的定位、修改其类的实现、通过改变消息或接收消息的次序来改变应用中特殊对象的角色。
新的行为可通过定义新的类和建立实例来实现。
类的维护:
把类的实现与其规格说明分离可局部化修改的影响。
一般情况下,修正问题要求应尽可能不改变类的界面。
然而,为了在系统中增加新的行为,偶尔会有改变界面的需求。
3.面向对象分析(OOA)与模型化
面向对象分析过程分为论域分析和应用分析。
论域分析建立大致的系统实现环境,应用分析则根据特定应用的需求进行论域分析。
(1)OOA分析的基本原则和任务
为建立分析模型,要运用如下的5个基本原则:
①建立信息域模型;
②描述功能;
③表达行为;
④划分功能、数据、行为模型,揭示更多的细节;
⑤用早期的模型描述问题的实质,用后期的模型给出实现的细节。
这些原则形成OOA的基础。
OOA的目的是定义所有与待解决问题相关的类(包括类的操作和属性、类与类之间的关系以及它们表现出的行为)。
为此,OOA需完成的任务是:
①软件工程师和用户必须充分沟通,以了解基本的用户需求;
②必须标识类(即定义其属性和操作);
③必须定义类的层次;
④应当表达对象与对象之间的关系(即对象的连接);
⑤必须模型化对象的行为;
⑥反复地做任务①―⑤,直到模型建成。
(2)OOA概述
目前已经衍生许多种OOA方法。
每种方法都有各自的进行产品或系统分析的过程,有一组可描述过程演进的图形标识,以及能使得软件工程师以一致的方式建立模型的符号体系。
现在广泛使用的OOA方法有以下几种:
①Booch方法:
Booch方法包含“微开发过程”和“宏开发过程”。
微开发过程定义了一组任务,并在宏开发过程的每一步骤中反复使用它们,以维持演进途径。
BoochOOA宏开发过程的任务包括标识类和对象、标识类和对象的语义、定义类与对象间的关系,以及进行一系列求精从而实现分析模型。
②Rumbaugh方法:
Rumbaugh和他的同事提出的对象模型化技术(OMT)用于分析、系统设计和对象级设计。
分析活动建立三个模型:
对象模型(描述对象、类、层次和关系),动态模型(描述对象和系统的行为),功能模型(类似于高层的DFD,描述穿越系统的信息流)。
③Coad和Yourdon方法:
Coad和Yourdong方法常常被认为是最容易学习的OOA方法。
建模符号相当简单,而且开发分析模型的导引直接明了。
其OOA过程概述如下:
使用“要找什么”准则标识对象;
定义对象之间的一般化∕特殊化结构;
定义对象之间的整体∕部分结构;
标识主题(系统构件的表示);
定义属性及对象之间的实例连接;
定义服务及对象之间的消息连接。
④Jacobson方法:
也称为OOSE(面向对象软件工程)。
Jacobson方法与其它方法的不同之处在于他特别强调使用实例(usecase)——用以描述用户与系统之间如何交互的场景。
Jacobson方法概述如下:
标识系统的用户和它们的整体责任;
通过定义参与者及其职责、使用实例、对象和关系的初步视图,建立需求模型;
通过标识界面对象、建立界面对象的结构视图、表示对象行为、分离出每个对象的子系统和模型,建立分析模型。
⑤Wirfs―Brock方法:
Wirfs―Brock方法不明确区分分析和设计任务。
从评估客户规格说明到设计完成,是一个连续的过程。
与Wirfs―Brock分析有关的任务概述如下:
评估客户规格说明;
使用语法分析从规格说明中提取候选类;
将类分组以表示超类;
定义每一个类的职责;
将职责赋予每个类;
标识类之间的关系;
基于职责定义类之间的协作;
建立类的层次表示;
构造系统的协作图。
⑥统一的OOA方法(UML)
统一的建模语言(UML)已经在企业中广泛使用,它把Booch、Rumbaugh和Jacobson等各自独立的OOA和OOD方法中最优秀的特色组合成一个统一的方法。
UML允许软件工程师使用由一组语法的语义的实用的规则支配的符号来表示分析模型。
在UML中用5种不同的视图来表示一个系统,这些视图从不同的侧面描述系统。
每一个视图由一组图形来定义。
这些视图概述如下:
用户模型视图:
这个视图从用户(在UML中叫做参与者)角度来表示系统。
它用使用实例(usecase)来建立模型,并用它来描述来自终端用户方面的可用的场景。
结构模型视图:
从系统内部来看数据和功能性。
即对静态结构(类、对象和关系)模型化。
行为模型视图:
这种视图表示了系统动态和行为。
它还描述了在用户模型视图和结构模型视图中所描述的各种结构元素之间的交互和协作。
实现模型视图:
将系统的结构和行为表达成为易于转换为实现的方式。
环境模型视图:
表示系统实现环境的结构和行为。
通常,UML分析建模的注意力放在系统的用户模型和结构