COM 全称Component Object Mode 组件对象模型。
很庆幸刚入行软件开发的时候没有去写COM组件,也很遗憾没有去做一些底层的事情。
一开始接触.NET的时候就被灌输一个模糊的理念,.NET中有一个叫中间语言的东西,一个模糊的说法,ASP.NET第一次运行的时候会比较慢,不过那时候就埋头去学C#了,没有深入研究.net framework的机制,某种意义上说就是纯粹的代码工人,干体力活的,人家搬砖我搬字母,一个重点用肩扛手拉一个轻点用脑子和指头敲敲打打,其实还真是同行,呵呵。
不过一个人的知识总是有限的,但总是有大师给我们指路解惑,Don Box 的这本书读着真的是感觉大脑做了一次升级,以前乱七八糟的知识在这里一串就全通了。
读一章写一点,结合着另一本Jeffrey Richter写的《Microsoft .NET 框架程序设计》一起来对.NET做一个深入的了解。
.NET 本质论 第一章 CLR是一个更好的COM
首先要知道组件的概念:一个可复用的代码块,可以将多个独立函数的功能进行组合,从而扩充成诸如Office Word 这样的应用程序。就像儿童玩的积木一样,一块块的积木就是一个个的组件,搭出来的东西就是应用程序。组件之间有各种约定,这些约定表现为简单的函数入口点,这样不同组件之间就可以通过这些约定进行相互之间的调用
而COM 的设计规范就是将组件约定表示为类型定义。所以多数COM下的问题都能追溯到组件间约定的本性上。COM 用类型的形式表示组件约定,但是第一COM规范特别避免强制用于约定定义的交换格式,所以组件间的约定无法以标准化的方式描述;第二MS定义和支持的COM交换格式有两个,一个是接口定义语言IDL 和类型库TLB,但是自家兄弟之间不同心,这两种格式不是同构的,即互相之间无法互相支持,而且互相不能成为对方的子集,这样一来子集内部就会有两种交换格式,而且没有一种是权威的或是标准的。
COM没有描述组件之间的依赖性dependency,说白了就是部署时候不知道哪个DLL是必须要调用的哪些可以不调用,所以似乎就是把所有的DLL都包括进去就是最保险的了,但是同一个组件的版本也没法静态的确定,所以版本问题的诊断液很难。
第二个大问题是COM约定描述格式缺乏扩展性,这和MS事务服务器有关系。
上面的两个大问题是COM问题的一方面,最重要的是COM约定本身是面向物理的physical,也称二进制约定。即COM对于组件调用有着严格的规定,
1、每一个方法都有精确的vtable(虚函数表)偏移量;
2、在调用的时候COM约定使用明确的堆栈规则;
3、COM约定强制每一个作为方法参数传递的数据结构的明确偏移量,即传参的时候参数顺序也不能有错误;
4、COM约定强制命令具体使用哪一个为被调用者分配内存的分配器;
5、COM约定强制对象引用的明确格式,成为接口指针。
所以综上实际上COM约定最终就是形成了一个堆栈结构的协议,确定了每一个方法、变量如何在内存中分配,基本上就是告诉机器如何分配组件的每一部分,而没有描述一些语义上的内容,我的理解就是低级语言。这样一来,对程序的可控性确实大大提高,但是过分的控制就会降低开发的效率,用“难以接受的不可靠性为代价”换取“高效的代码”,这个确实不合算。
CLR的历史经过了几次命名,从COM3 ->公共对象运行库COR(Component Object Runtime -> COM+ ->通用运行库URT(Universal Runtime) ->CLR。
和COM 相比,CLR也关注组件间的约定,这些约定也是基于类型的,这是两者相同的地方。
本质不同的在于:
1、CLR有完全规范的格式描述组件之间的约定,即我们熟悉而又陌生的元数据(metadata)。元数据是机器可读的,其格式是遵循规范的。在开发中也会接触到元数据,而且是可读写的,实际上这是CLR提供的一些实用部件,使我们可以对元数据进行操作。此外,元数据包括了组件间的依赖关系和版本关系,这就避免了前面提到的那些恼人的问题。
2、第二个区别是约定本身。先说说COM,在COM中组件约定“暗示了堆栈约定、虚函数表,以及作为方法参数传递的数据结构在内存中的表示形式”,于COM 这种物理约定相比,CLR的约定是一种描述逻辑结构的约定,没有暗示访问字段或者方法的精确的代码顺序,也没有约定任何数据的内存表示形式。CLR使用名字与签名代替偏移量引用字段和方法,所有对于数据结构的内存表示形式都被延期,直到在运行类型被加载以及初始化时才确定。实现这种延期的方法就是采用了公共中间语言CIL(Common Intermediate Language)机制来延期那些偏移量的解析。
所以可以看到COM和CLR的本质区别就在于是否对数据结构进行内存分配。CLR将这个操作延期的优势在于在部署的时候可以根据部署机器上的目标处理架构生成与之匹配的物理耦合,这样开发着不必关系部署机器的架构,只要编写好了程序,通过CIL可以将程序翻译为适合任何部署机器架构的实际运行代码,当然,任何程序最终运行时都要翻译成相应的部署机器的机器语言,使得部署机器可以执行程序。CLR通过这种延期机制,实现了程序的任意迁移。
CLR做的所有这些虚拟化工作可以大大降低与机器交互的难度,可以让我们使用任何我们喜欢的高级语言来进行程序的编写。
以上是根据我自己的理解并摘写原书中的一些描述来写的,读完这一章的东西,个人感觉,总有一天,人人都会写程序的!呵呵
------Study is never too later!