CORBA 连接:CORBA 3.0 的 IDL


CORBA 连接:CORBA 3.0 的 IDL


内容: 
 
为什么使用软件组件? 
组合接口 
“是”对“具有” 
导航和等价接口 
结束语 
参考资料 
关于作者 
对本文的评价 
 
相关内容: 
 
CORBA Component Model (CCM) 
The OMG's new CORBA Component Model 
CORBA notification services 
 
扩展接口间的关系 
Dave Bartlett ([email protected])
顾问、作家兼讲师
2001 年 7 月

“对象管理组织(OMG)”的“接口定义语言”已经能使开发人员根据继承创建对象关系。然而,当处理复杂设计时,经常需要支持包含多个接口的对 象,并且这些对象是通过组合而不是通过继承来构造的。本周,Dave Bartlett 通过扩展“组件实现定义语言”与标准化定义组件接口的方式,解释 了“CORBA 组件模型”如何实现这种需要。
在开始讨论软件组件之前,有必要定义它们是什么以及为什么我们希望使用它们。然后,讨论“组件实现定义语言(CIDL)”以及 CIDL 如何使组件式软件成为现实。

为什么使用软件组件?
为什么我们要使用软件组件?我们的汽车是由零部件(组件)组成;为什么我们喜欢这样,为什么零部件(组件)是重要的?汽车使用零部件(组件)是因 为当零部件(组件)用坏或发现有缺陷时,很容易替换掉它(比如轮胎)。这有助于管理变更,我认为这是使用组件的首要原因。在我的汽车里,我不能保持全部应 用最新的技术,每一个组件隔离了该项技术的某个方面。这导致了使用组件的第二个原因,管理复杂性。分而治之的策略简化了系统中大量的功能。最后一个原因是 重用。为什么重用是最后一个?因为我从来没有真正尝试拆掉我妻子汽车的交流发电机而将它用到我的汽车上,但我猜想我可能会这样做。这可能需要某种层次的式 样更新。重用是一个宏伟的目标,但要达到这个目标却格外困难。如果系统易于维护并且随着环境变化和技术改进易于升级系统,那么从长远来看,该系统的价值将 会极大地增加。脑子里有了这些目标之后,让我们创建一些定义。

组件是象这样的结构化软件单元,它们:

协同定位函数和数据之间的相关性,所以创建结合 
封装软件单元以减少耦合,并将组件用户与数据存储细节或功能实现隔离开 
提供唯一的标识,不考虑状态 

基于组件的软件的目标是创建高度结合的、合作良好的部件,但各自有明显不同的任务,以及创建系统中组件间低耦合性。这需要系统设计者从对象规范来 扩展面向对象原则到用接口定义明确地表示对象相关性。这种组件能力的规范可以划分成跨几个接口。将组件规范划分成多个接口可以使组件内相关性被限制到个别 接口,而不是整个组件规范。

例如,提供时间与日期函数的简单组件也必须实现几个接口,这些接口使得该组件在组件容器中能合作工作。对组件容器的更改需要对那些接口进行更改,但不需要更改时间与日期函数。反之亦然:可以不改变接口而更新时间与日期函数,这提供了组件的维护功能。

总之,基于组件的系统是不同的,因为它将规范和实现分离开,还因为将组件规范分成了表示组件和容器角色的一些具体接口。

组合接口
建立接口之间的关系和建立实现类之间的关系是组件设计的基本行为。设计这些关系的两种方式是继承和组合。“Gang of Four”这本设计模 式书(请参阅参考资料)的第一章通过对对象、实现和重用的广泛描述展示了对象编程的精髓。这一章明确地提出了使重用成为现实的困难性。继承是面向对象语言 典型的特征之一。它也是大多数学生能快速和有效掌握的事物。然而,继承确实有它的不利之处,而对于这些,学生直到具有更多面向对象的经验或除非受益于具有 理性意识的导师时,才能意识到。

在 OO 开发中,继承出现在两个不同的阶段。一方面,接口继承(也称作为子类型),它描述当一个对象用来替换另一个对象时。在 C++ 中,通 过从纯抽象类(具有纯虚拟成员函数的类)公共地继承来做到这一点。由于 Java 编程语言有 interface 关键字,很容易发现接口继承。另一方 面,类继承,它依照另一个对象的实现定义对象实现。类继承也称为实现继承。所以,虽然一些编程语言不支持接口继承和实现继承之间的差别,但优秀的程序员在 实践中可以区分这两者。例如,C++ 通过由抽象类定义类型来处理这两者的差别。

许多设计模式取决于接口继承和实现继承之间这种微妙的差别。Observer 设计模式经常用抽象类(它们是纯接口)来实现。Composite 模式是用来定义公共实现,而这个组合中的组件定义公共接口。

OMG IDL 总是允许您创建基于继承的对象关系。然而,很多时候,我们的设计需要支持包含多个接口的对象,而这些接口是通过组合而不是通过继 承来构造的。对象继承允许您依照另一个类来定义这个类的实现,而对象组合允许您通过将对象集合或组合在一起来定义一个类。OMG IDL 需要表达组合和 继承的能力。

OMG 已经认识到这些缺陷,并且一直在尝试解决它们。在 1996 年,OMG 发布了 RFP (Request for Proposal)。RFP 的需求将解决对多个接口的需要。CORBA Component Model 被认为是完成最初 在这个建议下提出的需求。

“是”对“具有”
当通过继承将子类和超类联系起来时,我们可以说子类具有了超类的一些特征。例如,狗子类“是”犬科超类的代表,可以强制转化成犬科类。“具有”关系是有很大区别的,它表示组合。

一个重要目标是使用标准接口,针对基于开放标准的组件,也许已经定义了这些接口。播放盒式磁带和 CD 的 stereo 组件都有相似的接口, 所以我们可以将它抽出来形成它自己的接口。这意味着有一个 CassetteDeck 和 CDPlayer 都使用的 AudioPlayer 接口。 AudioPlayer 类似于清单 1 中所示。

清单 1. AudioPlayer 接口

typedef sequence<octet> SoundBytes;
typedef int Speed;

interface AudioStreamIterator {
    void getStream(out SoundBytes nextSound,
                   out boolean hasMore);
};

interface AudioPlayer {
   attribute string name;
   AudioStreamIterator getSoundStream(in String strSound);
   int play(in AudioStreamIterator as);
   int fastForward(in Speed spd);
   int rewind(in Speed spd);
};

component CassettePlayer supports AudioPlayer{
   //  The facet for Client components.
   provides AudioPlayer audioPort;
};

component CDPlayer supports AudioPlayer{
   //  The facet for Client components.
   provides AudioPlayer audioPort;
};

component Stereo {
   attribute string name;
   // The receptacles for Cassettes or CDPlayers
   uses AudioPlayer Cassette;
   uses AudioPlayer CD;
};

AudioPlayer 接口有四种处理模糊定义类型的基本方法。SoundByte 是八位元的序列。这意味着它是一个不知道长度的字节流,并 且由于它是一个八位元,将不会排列它。getSoundStream() 将返回 AudioStreamIterator 对象,该对象将  SoundByte 装入其中。由于声音文件可以是很庞大的,我们可以将这个序列分割成多个部分,从而使 RMI(远程方法调用)免于陷于困境。 play() 方法将 AudioStreamIterator 作为“in”参数。fastForward() 允许您快速前进至流的某个地方, rewind() 使您倒回至流前面的某个地方。

这就是我们的接口。component 关键字是 CIDL 的添加物之一。component 允许 IDL 设计者在其主体内包含该组件的任 何属性声明,以及连同一起的组件平面(组件暴露给外界的接口)和容器(组件使用的接口)的声明与该组件可能需要的任何事件的源和接收器。然而,请注意,方 法中不允许包含 component 关键字。这是因为我们不是在创建接口 - 我们是在组合接口来形成“组件”。CDPlayer 和  CassettePlayer 组件提供了 AudioPlayer 接口,但 Stereo 组件是作为客户机工作,因为它使用该组件的  CDPlayer 和 CassettePlayer。由于有了这个 CCM 的添加物和新的 IDL 关键字,您在创建关系时比以前有更大的灵活性。

AudioPlayer

导航和等价接口
所有平面、容器、事件源、事件接收器和属性的声明都映射到生成等价接口(CIDL 规范用这个术语来称谓)的操作。我必须承认我感到自己正走在刀 刃上,因为我没有可以使我能检测规范和 IDL 的 CCM 和 CIDL 的实现。我的理解是 CORBA 3.0 CIDL 编译器会为您从组件定义 自动生成等价接口。所以,CDPlayer 组件有类似于清单 2 所示的等价接口。

清单 2. CDPlayer 接口

interface CDPlayer : Components::CCMObject, ManagedObject{
   AudioPlayer provide_audioPort;
};

等价接口中的操作允许组件的客户机检索其平面的引用。除此之外,所有组件从组件基本接口 CCMObject 那继承,该基本接口提供了带一般导航操作(通过 Components::Navigation 接口)的等价接口。这个导航提供类似于清单 3 所示的功能。

清单 3. Components::Navigation 功能

module Components {
   valuetype FacetDescription {
     public CORBA::RepositoryId InterfaceID;
     public FeatureName Name;
   };

   valuetype Facet:FacetDescription {
     public Object ref;
   };

   typedef sequence<Facet> Facets;
   typedef sequence<FacetDescription> FacetDescriptions;

   exception InvalidName{};

   interface Navigation {

     Object provide_facet(in FeatureName name)
                         raises (InvalidName);

     FacetDescriptions describe_facets();

     Facets provide_all_facets();

     Facets provide_named_facets (in NameList names)
                                  raises (InvalidName);

     boolean same_component(in Object ref);
   };
};
生成等价接口是用来提供组件接口导航。所有组件接口都会继承它。如果您熟悉 COM 世界,这会使您想起来自 IUnknown 的  QueryInterface() 和在 CoCreateInstanceEx() 中使用的 Multi_QI 结构。通过该导航提供类似以下的行 为:

provide_facet() 方法返回由 name 参数表示的平面的引用,或者如果没有发现由那个 name 参数表示的平面,则返回 InvalidName 异常。 
describe_facets() 操作返回由组件提供的所有平面的序列。返回的值类型 FacetDescription 将包含 RepositoryId 和该平面的名称。 
provide_all_facets() 类似于 describe_facets,但返回的值类型现在将包含支持每个平面的对象的引用。 
provide_named_facets() 将取一列名称,并返回包含 names 参数中平面的描述和引用的序列(在结构上与 provide_all_facets() 中返回的结构是一致的)。 
same_component() 将允许客户机决定是否两个引用属于同一个组件实例。该方法是组件实现相关。 

结束语
下个月,我将继续研究 CCM 中的 CIDL 构造。对于基于 CORBA 的系统,IDL 是基本的构建技术,将这一点牢记在心中是很重要 的。对 IDL 的更改引起了规范和 CORBA 社团的共鸣。添加来创建 CIDL 的关键字是相当广泛和直接明了。很明显,OMG 的梦想是使  CIDL 足够直接明了,以详述软件组件之间的各种关系,以及自动生成许多重现函数和服务用法模式。通过扩展 CIDL,OMG 维护了其语言和平台的 中立,但推动了结合坚实工程原则的软件标准。

参考资料 

关于下一代 CORBA 的介绍,请参阅 CORBA Component Model (CCM)(developerWorks,2001 年 4 月)上最近的 CORBA 连接。 
在 OMG 主页上,会发现许多关于 CORBA 更改方面的文档和讨论。 
如果对 CORBA 3.0 的起源感兴趣,那么 CORBA Component Model RFP 是一份很好资料。 
如果想了解 CORBA 和 CCM 有什么新事物,那么请关注 CORBA 和 CORBA Component Model (CCM) 页面。 
Gopalan Suresh Raj 在其个人主页上提供了一篇有关 CCM 不错的简介。 
来自 java.sun.com 的新闻发布介绍了作为工业标准的 CCM。 
Dr. Dobb's 全面观察了 CCM,并研究了 CCM 如何将与 EJB 和 COM+ 相对抗(DR. Dobbs Journal,2001 年)。 
学习更多有关用 CORBA 来编程的基础知识,请阅读 Michi Henning 和 Steve Vinoski 的 Advanced CORBA Programming with C++ (Addison-Wesley,2000 年)这本极好的书。 
也可以阅读 Jon Siegel 的 CORBA 3 Fundamentals and Programming (John Wiley and Sons,2000 年)。 
Java 开发人员应该看一下由 Gerald Brose、Andreas Vogel 和 Keith Duddy 著作的 Java Programming with CORBA(John Wiley and Sons,2001 年)。 
查找关于 RMI 和 CORBA 简介的 Java 开发人员也许想阅读 IBM Learning Services 教程 RMI, CORBA, and Distributed Objects。 
从 Object Oriented Concepts Inc 下载 Orbacus 4.1.0 以及附带的 Notification Service 实现。 
如果想学习 Java 编程,那么请从 Bruce Eckel 的 Mindview.net 以及他的免费电子版书籍 Java 编程思想,第二版(Prentice Hall,2000 年)开始。 
Gang of Four 一书, Design Patterns: Elements of Reusable Object-Oriented Software 完整地介绍了设计模式(Addison-Wesley,1995 年)。 
WebSphere 开发人员希望了解关于  Integrating CORBA ORB with IBM WebSphere Application Server (WebSphere Developer Technical Journal,2001 年 6 月)。 
关于组件,有新的东西?WebSphere 组已经编辑了关于基于组件开发(CBD)的理论和实践的资源列表。 

关于作者
 Dave Bartlett 居住在美国宾夕法尼亚州的 Berwyn,他是顾问、作家兼讲师。他是 Hands- On CORBA with Java 的作者,这是一本适用于公共课程或企业内部培训的 5 日教程。目前,Dave 正将课程资料编成书,书名是  Thinking in CORBA with Java。Dave 拥有宾州大学的工程和商业硕士学位。如果您对某个主题还有疑问或感兴趣,可通过  [email protected] 与 Dave 联系。 
  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章