欢迎来到.net学习网

欢迎联系站长一起更新本网站!QQ:879621940

您当前所在位置:首页 »  .NET本质论第一卷:公共语言运行库教程 » 正文

本教程章节列表

第一章:CLR是一个更好的COM

创建时间:2012年08月14日 16:45  阅读次数:(6560)
分享到:

我的第一部书是《Essential COM》(Addison-Wesley出版,1998年)。它首先描述了困扰前COM世界的问题,继而引出了COM这种新的架构,以解决这些难题。由于CLR与COM有着某种密不可分的继承关系,因此让这本书与《Essential COM》有一个类似的开头比较合适。不同的是,我们这次将考察一个COM已经成型的世界。

COM回顾

组件技术主要强调独立开发和部署的程序之间的约定(contract)。组件对象模型[Component Object Mode(COM)]是Microsoft公司首次尝试将这些约定规范化。这样,它们既能作为设计范例(design paradigm),也能用作支持的平台技术(supporting platform technology)。COM的设计范例就是将组件约定表示为类型定义(type definition)。而在COM出现以前,约定仅仅表现为简单的函数入口点,于是COM从以前的世界跨出了一大步。在这个方面,COM是个重大的进步,它将动态加载代码和类型系统以相当一致的方式有机结合在一起。

1.中文书名为《COM本质论》,由潘爱民先生译,中国电力出版社于2001年8月出版。
2.contract一词的译法在翻译过程中曾多次变更。曾经考虑过“协议”、“契约”、“合同”,最后选择了“约定”。“协议”一般用于网络上,对应的英文词为protocol,于是在开始时就将它排除了。“契约”这个词在一些C++的书上也出现过,但对应的英文词为agreement。而contract一词也是随着.NET的推出而大量地出现在MSDN上,因此应该用一个新的中文词汇与之对应。很长时间译者都将这个词译为“合同”,直到有一天发现MSDN的中文版上用“约定”的译法比“合同”要多一些。为了便于读者在概念上不被混淆,最后还是选择了“约定”。同时还要说明的是,本书绝大多数名词术语的译法都尽量做到与中文版的MSDN或者.NET帮助保持一致。
3.八年来,人们一直在使用各种形式的组件对象模型(COM)。事实证明,它是最为成功的可复用软件模型。COM引进了“组件”的概念——它是可复用的代码块,可以将多个独立函数的功能进行组合,从而扩充成诸如Microsoft Word这样的应用程序。从开发人员的角度看,COM通过引进几个明确定义的接口(诸如IUnknown)便可提供代码复用功能,开发期工具可通过这些接口来查询一个组件的功能,并能把这些功能添加到工具中。实际上,每个控件都代表上百行甚至上千行的代码,可以容易地封装在“黑匣子”中,开发人员只需直接调用其功能即可。

COM编程模型本身极好地经受住了时间的考验。COM将很多现有的思想,例如,封装(encapsulation)、多态(polymorphism),以及接口与实现分离等等,融合进统一的编程规范,这在软件工程领域留下了不可磨灭的印记。这里,我不想重复阐述COM模型,有关内容你可以参考《Essential COM》或者《Design Patterns》(Erich Gamma等著,Addison-Wesley出版,1995年)的第一章。尽管它们在表述上相差甚远,但本质上都是指相同的编程模型。
COM既是编程模型,也是支持的平台技术。对于后者,COM做得就不如我所喜爱的编程模型那样棒。遗憾的是,还需要一个稳固的平台技术,使COM不只是一个理念或者编程准则。正是因为这方面的原因,COM时代面临着终结。
多数COM平台的问题都能追溯到组件(component)间约定的本性上。在理想世界中,组件间的约定纯粹是通过用户与组件之间的语义保证和假设的形式表示的。不过,软件工程领域仍然要定义某种形式来表示语义,并且,它是已经被证明,对于大范围工业界的部署在商业上(或者技术上)是可行的。最接近的专业做法是采用可编程的类型定义,以及描述那些类型定义的人工可读的(human-readable)文档。这是COM以前的做法,也是最后一个COM组件消失后的做法。
COM用类型的形式表示组件约定;不过,COM的组件约定存在两个关键问题,使得基于COM的约定技术对表示语义并不是最优的。其中,一个问题与COM约定的描述有关;另一个则与约定本身有关。
COM的第一个问题来自约定的描述。COM规范特别避免强制用于约定定义的交换格式。这意味着如果只遵循COM规范,就无法以标准化的方式描述约定;准确地说,COM规范假定约定的类型定义之间将通过完全是COM之外的某种技术进行交互。当然,这只有在规范的世界里才行之有效。为了使COM成为有用的技术,就需要具体的解决方案;否则,构建编译器、工具和支撑架构都是不可能的。

中文书名为《设计模式》,由李英军等译,吕建审校,机械工业出版社于2000年9月出版。
作者试图说明:采用类型定义表示组件之间合同的做法,是一直以来就使用的方式。

对于约定描述,Microsoft定义和支持的COM交换格式不是一个,而是两个:接口定义语言[interface Definition Language(IDL)]类型库[type library(TLB)]文件。这似乎没有什么问题;但是,两种格式并不是同构的(isomorphic)。也就是说,其中一种格式表示的结构,对另一种格式没有什么意义。更糟的是,某种格式所支持的结构无法成为其他格式支持结构的子集。因此,对约定描述而言,无法确定哪种格式是“权威的”或者“标准的”。
有人主张简单地定义第三种格式,并以它来支持其他两种格式都支持的所有构件。然而,在COM中,描述约定的方式还存在其他至少两个关键问题。其中一个就是COM没有描述组件的依赖性(dependency)。直到撰写本书时,还是没有办法解析COM组件(或者它的约定定义),以及确定它所需要的其他组件,以保证它的正确运行。由于缺乏相关信息,使得在部署基于COM的应用程序时,很难确定采用哪些DLL。此外,静态地确定需要哪个版本的组件也是不可能的,这使诊断版本问题变得极其困难。
第二个主要问题,也是敲响COM约定描述格式最终丧钟的,就是缺乏扩展性。早在九十年代,Microsoft事务服务器[Microsoft Transaction Server(MTS)]开发小组正致力于一种新的编程模型,它是基于现在被称为面向方面 [aspect-orient programming(AOP)]的编程思想。AOP获取非特定域(not domain-specific)代码的方面(aspect),并将它们从开发者的源代码中提炼出来。基于AOP的系统依赖于可选择的机制,用于声明它们的方面(aspect),从而使程序员的意图更加清晰,而不是隐晦的。
MTS小组希望开发者将他们对并发、事务以及安全的需求表示为方面(aspect),而不是API函数的调用。由于COM的广泛运用,MTS开发者采用增加COM约定描述的机制,用于表示这些方面。对于使用MTS的开发者,只要简单地通过特性(Attribute)批注他们的COM类、接口和方法

定义,就能够通知MTS执行器(MTS executive)他们对底层代码的要求和假定。为了使这些特性有效,MTS执行器将取代COM加载器,并基于加载类的方面(aspect)插入侦听器。MTS侦听器(interceptor)[也称为上下文包装器(context wrapper)]将采用任何措施,确保在分发方法调用之前,满足开发者的要求。有趣的是,使用声明式的特性模型和侦听模型,后来演变为Enterprise Java Bean(EJB)的基础,这也说明了Sun Microsystems公司对MTS的认同。
遗憾的是,MTS小组并没有依赖任何一个COM约定格式,并将其作为传递和存储特性的可靠方式。其中的一种约定格式,接口定义语言(IDL)是基于文本格式的,极少随组件部署。并且,IDL通常只有C++开发者才会使用。然而,在MTS下开发企业应用的C++程序员数量相对较少,这使得基于IDL约定定义的用途不大。第二种格式类型库(TLB)文件,在扩展性方面也存在不成熟性(甚至缺陷)。然而,最终导致TLB没落的因素是Visual Basic的主流开发者无法直接影响TLB。准确地说,VB的IDE和编译器将开发者和TLB隔离了开来,这就导致了VB程序员在开发的过程中无法指定MTS特性。尽管VB5.0最后只是增加了对一种MTS特性(Transaction)的支持,但MTS小组还是要感谢VB小组,使得这项技术得以推广。由于VB小组有着自己的工作日程,MTS和COM小组只能从大局出发,最终考虑放弃TLB和IDL,而定义新的约定定义格式,它将以一种比TLB更简洁和更易于理解的方式来提供可扩展性。这个约定格式也将是本书所关注的焦点。
前面的讨论主要围绕组件约定的描述问题。然而,即使有一种很好的统一描述格式,在约定的工作方式上,COM也存在着根本问题。这是约定的描述方式所无法解决的,准确地说,是约定本身的问题。

COM组件约定是基于类型描述的。在这些约定中,所采用的类型系统是C++中被保证在编译器间可移植的一个子集。对于这种可移植性的保证,并不仅仅体现在语言层面,更进一步说,是在大多数现代编译器所采用的数据表示方面。然而,问题就出在这里。
COM的组件约定是物理的[(physical);也被称作二进制(binary)约定]。这也就是说,COM对组件间的调用方式有着严格的要求。COM约定要求每一个方法都具有精确的vtable偏移量。在调用方法时,COM约定要求使用明确的堆栈规则(例如,__stdcall);COM约定强制命令作为方法参数传递的每一个数据结构的明确偏移量;COM约定强制命令具体使用哪一个分配器,用于为被调用者分配的内存;COM约定强制对象引用的明确格式[称为接口指针(interface pointer)],包括被采用的vptr和vtbl的明确格式。就COM的底层技术而言,组件约定最终只是在内存中形成堆栈结构的协议,根本没有描述语义内容。
在COM中,组件约定的物理特性存在着缺陷。其中一个就是过度地关注细节,因为只有这样,才能确保正常工作。因而,COM成了难于使用的技术,甚至对那些很关注COM的开发者也是这样的。工具开发者试图隐藏COM的复杂性,但这反而增加了问题。这些可以从处理VB二进制兼容模式的VB程序员那里得到证实。
尤其在针对COM组件的版本控制上,其物理本性的问题就更大了。当必须要求进行语义修改时,版本控制就将成为十分棘手的难题。哪怕是vtable的次序或者字段的对齐这类很小的细节,都会导致运行时的错误,这些只使问题变得更糟。尽管在COM中,约定定义的精确性将产生高效的代码,但它是以难于接受的不可靠性为代价。

L]WY{|媁-N剉筫2C
来源:.net学习网
说明:所有来源为 .net学习网的文章均为原创,如有转载,请在转载处标注本页地址,谢谢!
【编辑:Wyf】

打赏

取消

感谢您的支持,我会做的更好!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

最新评论

共有评论0条
  • 暂无任何评论,请留下您对本文章的看法,共同参入讨论!
发表评论:
留言人:
内  容:
请输入问题 41+47=? 的结果(结果是:88)
结  果: