引言
网络计算带领软件产业进入了一个新的时代,商机无限,但同时挑战也无限。以电子商务为代表的技术潮流正将大到企业计算、小到个人数字代理的各种应用,在世界范围内联结起来,软件制造业正面临着一些新的课题,如复杂的分布环境、灵活的应用模式、广泛的包容性等,传统的软件设计思想已远远不够。
在这一背景下,构件技术应运而生,并逐渐炙手可热。不同于OO技术强调对个体的抽象,构件则更推广了对象封装的内涵,侧重于复杂系统中组成部分的协调关系,强调实体在环境中的存在形式,形成一个专门的技术领域。
中间件作为存在于系统软件与应用之间的特殊层次,抽象了典型的应用模式,从而使应用软件制造者可以更多地将思路放在业务逻辑中,并基于标准的形式进行开发,这样就使软件构架化成为可能。一些工业标准的推出,进一步使中间件成为可复用构件的运行框架,加速了软件复用的现实化进程。
本文从构件在现实软件发展中的地位展开,分析了中间件在系统组织层次中所起的作用,阐述了构件化思想对中间件本身的促进作用,提出了一种构件化中间件的发展模式。
构件技术的基本思想
OO技术是在"数据+算法"的基础上提升了对事物的认识方法,对象的概念符合人们认识世界的习惯。而构件的思想则更多地将重点从建模本身发展到对软件生产的考虑,即构件可以在应用领域的软件生产中作为零件纳入新的体系中被重用。因此,构件是OO思想的沿袭和扩展,认识事物的角度从对象个体本身上升到个体在群体中的作用。
构件有几个基本属性:
1、构件是可独立配置的单元,因此构件必须自包容。
2、构件强调与环境和其他构件的分离,因此构件的实现是严格封装的,外界没机会或没必要知道构件内部的实现细节。
3、构件可以在适当的环境中被复合使用,因此构件需要提供清楚的接口规范,可以与环境交互。
4、构件不应当是持续的,即构件没有个体特有的属性,理解为构件不应当与自身副本区别,在任何环境中,最多仅有特定构件的一份副本。
可以看出,构件沿袭了对象的封装特性,但同时并不局限在一个对象,其内部可以封装一个或多个类、原型对象甚至过程,结构是灵活的。构件突出了自包容和被包容的特性,这就是作为软件生产线上作为零件的必要特征。
构件技术的关键点涉及构件做什么、构件交互的规则、构件存在的环境等,相应在现实中有各种支撑性的技术,如:
1、构件模型,研究构件的本质特征及构件间的关系;
2、构件描述语言,以构件模型为基础,解决构件的精确描述、理解和组装问题;
3、构件分类与检索,研究构件的分类策略、组织模式及检索策略,建立构件库系统,支持构件的有效管理;
4、构件复合组装,包括源代码级的组装和基于构件对象互操作性的运行级组装;
5、标准化,包括构件模型的标准化和构件库的标准化;
6、软件构架,研究如何快速、可靠地应用可复用构件系统进行系统构造的方式,着重于软件系统自身的整体结构和构件间的互联。
中间件:构件存在的基础
构件技术在最初时更多是作为一种思想存在,进而才在一些关键的环节上发展出解决问题的技术分支。构件的存在某种程度上极大地依赖了构架技术,或环境、基础设施、计算平台,只有在适当的构架中,软件才有可能被抽象和隔离,最终成为构件。因此,单独讨论构件是抽象而空洞的。构架不是操作系统、数据库或网络协议,也不完全是应用,而是在某种特定意义上的构件运行容器,层次上界于应用和基础设施之间。
中间件,从本质上是对分布式应用的抽象,因而抛开了与应用相关的业务逻辑的细节,保留了典型的分布交互模式的关键特征。经过抽象,将纷繁复杂的分布式系统经过提炼和必要的隔离后,以统一的层面形式呈现给应用。应用在中间件提供的环境中可以更好地集中于业务逻辑上,并以构件化的形式存在,最终自然而然地在异构环境中实现良好的协同工作。
不难看出,中间件与构架实际是从两种不同的角度看待软件的中间层次,可以这样说:中间件就是构架,或构件模型的具体实现,是构件软件存在的基础,中间件促进了构件化软件。从下面列举的一些中间件的特征,可以看出,中间件与构架本质上是一致的。
面向需求的构件应用
基于构架的构件化软件开发应当是面向需求的,即设计者集中精力于业务逻辑本身,而不必为分布式应用中的通信、效率、互操作、可靠性、容错性、完整性等大量与业务无直接关系但又非常重要的问题,而耗费大量的精力,理想的构架在这些方面应当为构件软件提供良好的运行环境。事实上,这些正是中间件所要解决的问题,因此,基于中间件开发的应用真正是面向需求的,从本质上符合构件化设计的思想。
使业务逻辑容易划分
服务器构件要求有很好的业务自包容性,应用开发者可以按照不同的业务进行功能的划分,体现为不同的接口或交互模式。针对每种业务的设计和开发是可以独立进行的。
构架和中间件有同样的目标:提供业务的分隔和包容性。例如:消息中间件规定了消息是有属性的,其中部分属性则与业务的划分有关,某种服务构件只进行相应类型的消息交互。至于如何保证业务的分类运行与管理,则是中间件的事情。
因此可以说,中间件和构架都实现了构件向应用的集成。
构件的封装、设计与实现隔离
构件对外发生作用或构件间的交互,都是通过规范定义的接口进行,构件使用者只需要知道构件的接口,而不关心其内部实现,这是设计与实现分开的关键。构架就应当提供构件交互的规则,并基于这些规则实现类似容器的标准环境。
中间件在分布交互模式上都规定了接口(或类似)机制,如IDL就是描述接口的语言规范,从早期的DCE到现在的CORBA、DCOM、Java RMI等都使用IDL描述接口,所不同的只是语言规范。客户访问服务(或对象方法)均通过接口进行,至于服务采用怎样的内部实现、基于怎样的语言、甚至怎样的操作系统、数据库,开发者都不用关心。类似地,消息队列也可作为分布交互的手段,消息的语法和语义定义保证了使用与实现的分离,使用消息队列的客户或服务是不依赖于对方的。既然中间件能隔离设计与实现,能在分布的环境中封装实现的细节,那么,基于中间件的构件开发也就是可能的。
隔离应用构件与复杂系统资源
构架很重要的一个功能就是将系统资源与应用构件隔离,这是保证构件可重用甚至"即插即用"的基础,与中间件的意图同样是一致的。中间件最大的优势之一就是屏蔽多样的系统资源,保证良好的互操作性。应用构件开发者只需要按照中间件规定的模式进行设计开发,不必考虑下层的系统平台。因此可以说,中间件真正提供了与环境隔离的构件开发模式。
符合标准的交互模型
构架不是什么具体软件,而是抽象的模型,但模型中应当定义一些可操作的成分,如标准的协议。标准的中间件则实现了构架的模型,实现了标准的协议,如基于CORBA的对象中间件使用的是CORBA规范作为构架模型,具体则实现了可互操作的GIOP协议,映射到TCP/IP为IIOP协议,定义了CDR数据表示语法、数据包格式、消息语义等内容。因此,基于中间件的构件是符合标准模型的。
软件重用
软件重用是构件化软件生产的根本目标之一,中间件提供了构件封装、构件交互规则、构件与环境的隔离及构架设施等机制,这些都为软件重用提供了方便的解决方案。
另外,通过类似应用桥的机制,中间件可以建立访问过去应用的通道;或者在新的中间件体系中建立特殊的运行容器,封装以往的应用,从而最终做到对应用遗产的继承性重用。
提供对应用构件的管理
基于中间件的构件软件可以方便地进行管理,因为构件总可以通过方便的标识机制进行划分,还可以使用构件库机制配合一些管理规则。例如,微软的COM就利用Windows系统注册表配合几种唯一标识构件的方式,实现构件的登记、注销、定位。CORBA规范中有接口池、实现池等规范定义,配合应用登记管理的机制,也能对应用构件实施管理。
总之不难得出结论,基于中间件开发的应用是构件化的,中间件提供了构件的体系结构,大大提高了应用构件生产的效率和质量。
构件思想对中间件的作用
中间件本身作为软件产品,正处于方兴未艾之际,因此本身也可以借鉴构件思想,构件化的软件开发对中间件同样适用。
首先,中间件作为分布式计算平台,涉及资源多样,包括各种操作系统、数据库、网络协议甚至语言,其目标是在分布的环境中统一使用这些资源。因此,可以建立针对这些资源的构件库,以动态、灵活的方式进行构件的装配,如针对不同的面向连接的网络协议,可使用统一语义的网络驱动器构件,最灵活的情况是根据配置动态绑定。
其次,中间件的一个重要的设计目标是互操作,而互操作的关键是有清晰而与实现无关的接口。因此在互操作的边界上,必须将构件的思想融入设计中。
再次,中间件的应用范围越来越广,但应用有不同的需要,不同的业务特点,如果仅仅依靠固定的模式去套用,显然不合适。例如,多数MIS应用并不需要交易管理;有些分布应用也没有OLTP的特点;金融应用中安全就显得十分关键;拓展到Web的应用则特别要求精干、安全和适应性强。因此,中间件必须设计成可伸缩的体系,由一些可替换的构件组成,如某些重于可靠,某些强调实时,某些则需要小巧。产品只有这种定位,才能在变化迅速的市场上总是适应需求,立于不败之地。
第四,中间件不是最终的应用,需要服务于应用开发,但可以面向典型业务的模型,以方便应用的开发,这些模型可以以构件的形式作为产品提供。例如,CORBA服务和设施就是一些典型应用的抽象体现,使用这些服务的构件,应用可以大大减少开发规模,并获得良好的效果。以构架化技术术语讲,就是领域建模。
第五,成功的商业软件都是非常便于管理的,同样中间件也有可配置性的需要,管理整个系统是个复杂的行为,但如果转化为若干简单行为的统一,对开发就很简单而明确。事实上,标准的网络管理协议正是蕴涵了这种思想。基于构件化开发的中间件也一样,各个构件自身是独立配置的单元,只需进行集成就可达到系统的管理目标。
因此,构件化的软件设计思想在中间件发展中起到了重要的作用,可以预见,构件化的中间件在今后市场上是有强大生命力的。
结束语
构件是一种前沿的软件设计思想,对整个软件行业的发展有着至关重要的推动作用。而中间件作为应用软件系统集成的关键技术,保证了构件化思想的实施,并为构件提供了真正的运行空间。中间件领域工业化标准的制定、统一及实现,使基于构件的应用开发成为可能。反过来,构件对新一代中间件产品中也起到促进作用。
回顾经典的工业化革命,不难得出一些有益的启示:功能再复杂的产品都是由大量标准的零件(尽管零件可能只在本领域内有用)组成,零件在生产线上装配成一个成品,所有零件在成品*同发挥作用。分工越细致、专业生产的程度越高,总体生产效率就越高。而构件技术所扮演的角色就是把零件、生产线和装配运行的概念运用在在软件工业中,可以预见,软构件技术是软件产业化革命的必然发展趋势。
回顾上一讲中在介绍CORBA体系结构时,曾强调CORBA在提高组件重用性、增强分布计算功能方面具有的突出特点:
● 引入中间件作为事务代理;
● 客户程序与服务器程序完全分离;
● 与面向对象的建模概念相结合;
● 引入接口定义语言描述服务对象功能。
CORBA规范只是描述了CORBA系统中各个构件的基本情况以及构件在系统中承担的任务,并没有从功能实现的细节上规定必须如何建立一个基于CORBA规范的软件系统产品。这样,对于基于CORBA的软件产品开发而言,程序设计人员可以*地选择实现方式,但前提是遵循规范中各个构件的实现原则。在本讲和下一讲中,将详细介绍CORBA中各个构件的主要内容。 对象请求代理(ORB)
1. 对象请求代理(ORB,Object Request Broker)的作用
在传统的基于客户机/服务器模式的应用程序开发过程中,项目开发人员遵循公开的标准或*设计模块间的协议,这样的协议依赖于网络类型、实现语言、应用方式等。引入ORB后,客户只要遵循服务对象的对外接口标准向服务对象提出业务请求,由ORB在分布式对象间建立客户-服务对象关系。总结起来,ORB的作用包括:
● 接受客户发出的服务请求,完成请求在服务对象端的映射;
● 自动设定路由寻找服务对象;
● 提交客户参数;
● 携带服务对象计算结果返回客户端。
由图1可以看出,客户(Client)向服务对象的实现(Object Implementation)发出事务请求,其中客户是欲对服务对象发出方法请求的实体,服务对象应包括该方法的数据资源以及实现代码。对象请求代理的作用就在于定位服务对象,接收客户发出的服务请求并将服务对象的执行结果返回给客户。请求发出后,客户对象采用轮询等方式以获取服务对象计算的结果。
2. ORB的结构及类型
ORB通过一系列接口和接口定义中说明的要实现操作的类型,确定提供的服务和实现客户与服务对象通信的方式。通过IDL接口定义、接口库或适配器(Adapter)的协调,ORB可以向客户机和具备服务功能的对象实现(Object Implementation)提供服务。作为CORBA体系结构的核心,ORB可以实现如下三种类型的接口:
● 对于所有的ORB实现具有相同的操作;
● 针对特定类型对象的操作;
● 与对象实现类型有关的操作。
基于ORB实现的不同类型接口,一个客户端请求可以同时访问多个由不同ORB实现通信管理的对象引用。在实际应用中,只要遵循公共的ORB体系结构,程序设计可以选择ORB的多种实现方式,其中包括:
(1)客户和实现驻留(Client-Implementation Resident)ORB:采用驻留在客户和服务对象实现程序的方式实现ORB。在这种实现方式下,客户端可以通过桩(Stub)程序,以位置透明的方式向具体的实现对象提出服务请求,实现客户与服务对象的通信。
(2)基于服务(Server-based)ORB:客户对象和实现对象均可以与一个或多个服务对象进行通信,服务对象的功能是将请求从客户端发送到对象实现。在这种方式中,ORB的作用是完成客户对象与实现对象的通信,为对象之间的交互提供服务。
(3)基于系统(System-based)ORB:在这种实现方式中,ORB被操作系统认为是系统所提供的一项基本服务。由于操作系统了解调用方与服务对象的位置,因而可以充分地实现ORB功能的优化。
(4)基于库(Library-based)ORB:如果认为对象实现可以共享,则可以将实现功能放入实现库(Implementation Repository)中,从而创建基于库的ORB。
3. ORB中的主要方法
客户端和服务对象端均可以*选择使用ORB对象中定义的方法来实现操作。下面举例说明ORB对象中的重要方法: (1)ORB ORB_init(inout arg_list argv,in ORBid orb_identifier)
作用:ORB初始化方法。
(2)String object_to_string(in Object obj)
作用: 将对对象的引用转换成客户可以用字符串方式存储的对象信息。
(3)Object string_to_object(in String str)
作用:上述方法的逆过程。将以字符串方式存储的对象转换成对对象类型的引用。
(4)Object resolve_initial_references(in ObjectID identifier)
作用:获取初始对象引用。
(5)Policy get_policy(in PolicyType policy_type)
作用:返回指定类型的服务策略对象。
作为公共对象请求代理体系结构中的核心内容,ORB提供了相当丰富的方法。读者可以查阅相关资料详细了解ORB中的方法。
4. 服务请求的实现方式
关于对象请求的实现方式,CORBA规范中定义客户程序可以用动态调用接口(DII,Dynamic Invocation Interface)方式或通过OMG IDL文件经编译后在客户端生成的桩(Stub)方式提出服务请求。这两种实现方式的区别在于通过OMG IDL桩(Stub)文件方式实现的调用请求中,客户能够访问的服务对象方法取决于服务对象所支持的接口;而动态调用接口调用方式则与服务对象的接口无关。尽管实现调用请求的方式有所区别,但客户发出的请求服务调用的语义是相同的,服务对象不去分析服务请求提出的方式。
ORB通过IDL客户桩(Stub)方式或动态调用接口(DII)方式定位服务对象的实现代码、传递服务对象应用参数以及完成对请求传送方式的控制。服务对象的实现(Object Implementation)通过对象适配器(Object Adapter)提供对客户请求的服务。客户对服务器端方法的调用方式见图2。
图2 客户调用服务请求的实现方式
从以上对服务请求调用方式的分析可以看出: 服务对象接口的定义在整个CORBA系统服务功能的实现中起着相当重要的作用。那么如何实现服务对象的功能接口呢?CORBA规范中定义了两种接口实现方式:第一种形式是利用OMG IDL接口定义语言对接口进行描述。IDL语言有详细的语法规则(讲座将在第五讲对该语言的语法规则进行详细讲解)。这样,经过对所实现功能的系统分析,利用IDL,依据服务对象可能实现的服务以及服务中需要的参数,对接口进行定义。另外一种方式是将接口放入接口仓库(Interface Repository)中,在运行期间对接口库中的接口进行访问。