【 某某提到: 】
: 一般說(shuō)COM復(fù)雜,首先是名詞太多,其次是基于ATL的實(shí)現(xiàn)比較難懂
: 這并不是COM本身復(fù)雜,而是C++已經(jīng)落后于時(shí)代了。所以ATL看起來(lái)才會(huì)像天書(shū)一般
雖然對(duì)于全新的工程項(xiàng)目,推薦通過(guò).net實(shí)現(xiàn),但是,只要你工作在Windows平臺(tái)上,必然會(huì)遇到和COM相關(guān)的技術(shù)和機(jī)制,無(wú)論是大量的legacy的工程和代碼,還是作為OS重要功能以及native組件的首選交互形式和接口暴露方式,比如DirectX API,比如一些WMI的API;最有趣的是,即使是.net的核心CLR本身也是一個(gè)COM組件,可以通過(guò)Host相關(guān)接口讓native應(yīng)用來(lái)加載,以在當(dāng)前進(jìn)程中啟動(dòng)整個(gè)CLR的虛擬執(zhí)行環(huán)境或者叫托管執(zhí)行環(huán)境(managed executive environment)。
把握COM有兩點(diǎn)很關(guān)鍵,
1)Interface-based design,從設(shè)計(jì)和編碼思路上就是要完全基于接口;
2)VirtualTable-based binary compatibility, 實(shí)現(xiàn)上無(wú)論何種語(yǔ)言或者機(jī)制,只要符合基于虛表的二進(jìn)制兼容規(guī)范,就都可以實(shí)施;
COM僅僅是個(gè)規(guī)范,基于COM的具體技術(shù)非常之多,OLE,Automation,Structural storage,ActiveX...汗牛充棟,還有COM+,這個(gè)是提供企業(yè)級(jí)開(kāi)發(fā)必備的一些基礎(chǔ)功能和設(shè)施,比如,事務(wù)管理機(jī)制,對(duì)象池,安全管理,消息隊(duì)列...需要指出,目前即便是.net Framework也沒(méi)有實(shí)現(xiàn)COM+所提供這些機(jī)制,只是簡(jiǎn)單的封裝了后者。
COM技術(shù)中可能有一些比較困難的地方,接口的一致性,對(duì)象的聚合和生命周期,套間,跨套間的接口訪問(wèn),名字對(duì)象,等等;這些并不是COM規(guī)范人為制造的困難,而是為了設(shè)計(jì)和提供,可以跨進(jìn)程和機(jī)器邊界,跨異構(gòu)平臺(tái)(當(dāng)然必須實(shí)現(xiàn)了COM所規(guī)定的基礎(chǔ)服務(wù)),透明化具體對(duì)象類型及對(duì)象生命周期,便于統(tǒng)一部署和版本管理的組件技術(shù),所必須付出的代價(jià),這個(gè)代價(jià)從開(kāi)發(fā)人員角度看具體表現(xiàn)為,概念理解的困難以及具體二進(jìn)制實(shí)現(xiàn)的困難;
不過(guò)從另一個(gè)角度看,COM已經(jīng)很容易了,
a) COM規(guī)范已把要達(dá)致這些目標(biāo)的系統(tǒng),所必須提供的接口和特性抽象了出來(lái),只不過(guò)為了表達(dá)這些抽象的概念而新造的術(shù)語(yǔ)名詞有些陌生和突兀;如果讓遇到相似問(wèn)題的每一個(gè)設(shè)計(jì)和開(kāi)發(fā)人員都自己來(lái)做抽象,未必會(huì)生成更好的方案;
b) 為了幫助設(shè)計(jì)和開(kāi)發(fā)人員,人們提供了很多的開(kāi)發(fā)庫(kù),以提高COM開(kāi)發(fā)的正確性和效率;最顯著的就是MFC中關(guān)于COM/OLE的輔助類和函數(shù),以及為了COM而生的ATL;從本質(zhì)上看,這些類庫(kù)都是把COM規(guī)范中必須實(shí)現(xiàn)的,Windows平臺(tái)本身沒(méi)有提供,具體設(shè)計(jì)和開(kāi)發(fā)人員實(shí)際實(shí)施時(shí)會(huì)重復(fù)實(shí)現(xiàn)的,同時(shí)又非常容易出錯(cuò)的那部分功能,集中到了這些類庫(kù)里統(tǒng)一實(shí)現(xiàn),讓具體設(shè)計(jì)和開(kāi)發(fā)人員以代碼重用的形式來(lái)實(shí)現(xiàn)COM規(guī)范;
當(dāng)然人們也意識(shí)到了COM這樣的一些問(wèn)題,特別是具體實(shí)現(xiàn)時(shí)設(shè)計(jì)和開(kāi)發(fā)人員必須要關(guān)注幾乎所有的二進(jìn)制細(xì)節(jié),于是.net就誕生了,把這些規(guī)范的許多復(fù)雜性都封裝在了虛擬機(jī)里面,把這些目標(biāo)功能(跨邊界、透明性等等)通過(guò)一致而又平滑的平臺(tái)接口和自描述的meta data,以一種讓設(shè)計(jì)和開(kāi)發(fā)人員更易接受的風(fēng)格開(kāi)放了出來(lái);
COM的影響是非常廣大的,比如XPCOM ,F(xiàn)irefox上的一種插件技術(shù)標(biāo)準(zhǔn),就是根據(jù)COM的思想和原則制定的;許多評(píng)論說(shuō),F(xiàn)irefox的成功是因?yàn)樗寮侨绱说某晒Γ@也算是COM本身所意料不到的貢獻(xiàn)之一。
在.net的平臺(tái)上,即使是.net CLR/SSCLI的具體實(shí)現(xiàn)也大量運(yùn)用了COM的思想和機(jī)制,可以說(shuō).net就是搭建在COM二進(jìn)制組件平臺(tái)之上的虛擬機(jī)托管平臺(tái)。
最后,.net開(kāi)始時(shí)的內(nèi)部編號(hào)是COM 2.0
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*) 關(guān)于“名詞太多”
這是要實(shí)現(xiàn)可以跨進(jìn)程和機(jī)器邊界,跨異構(gòu)平臺(tái)(當(dāng)然必須實(shí)現(xiàn)了COM所規(guī)定的基礎(chǔ)服務(wù)),透明化具體對(duì)象類型及對(duì)象生命周期,便于統(tǒng)一部署和版本管理的組件技術(shù),所必須付出的代價(jià)。
COM規(guī)范已把要達(dá)致這些目標(biāo)的系統(tǒng),所必須提供的接口和特性抽象了出來(lái),只不過(guò)為了表達(dá)這些抽象的概念而新造的術(shù)語(yǔ)名詞有些陌生和突兀;如果讓遇到相似問(wèn)題的每一個(gè)設(shè)計(jì)和開(kāi)發(fā)人員都自己來(lái)做抽象,未必會(huì)生成更好的方案;
舉個(gè)例子,apartment,套間,就是為了抽象傳統(tǒng)OS中進(jìn)程和線程的實(shí)現(xiàn)而新造的術(shù)語(yǔ)名詞和概念;任何人要抽象這樣的一些概念,不新造術(shù)語(yǔ),是非常困難的,對(duì)比.net,后者用了CLR虛擬機(jī)來(lái)封裝了大多數(shù)的實(shí)現(xiàn)細(xì)節(jié),并用讓人更容易接受的風(fēng)格來(lái)開(kāi)放接口,可事實(shí)上仍然新造了一些名詞和概念,如類似范疇的AppDomain;
*) 關(guān)于“基于ATL的實(shí)現(xiàn)比較難懂”
ATL主要使用了template技術(shù),COM接口智能指針,用靜態(tài)轉(zhuǎn)換來(lái)模擬動(dòng)態(tài)綁定,等等,實(shí)際并不是很復(fù)雜,只能算c++實(shí)現(xiàn)機(jī)制的中等難度,主要涉及Modern C++ design一書(shū)中一些相關(guān)設(shè)計(jì)理念的運(yùn)用。對(duì)比Boost中某些庫(kù)的實(shí)現(xiàn),ATL很人道了。
*) 關(guān)于“這并不是COM本身復(fù)雜,而是C++已經(jīng)落后于時(shí)代了”
首先COM的規(guī)范的確是復(fù)雜的,為啥?第一點(diǎn)已經(jīng)說(shuō)了,就是為了要抽象出跨邊界和對(duì)象透明的組件技術(shù);.net表象上看比較“簡(jiǎn)單容易”,風(fēng)格親近設(shè)計(jì)和開(kāi)發(fā)人員,實(shí)際上復(fù)雜事務(wù)和實(shí)現(xiàn)細(xì)節(jié)都被劃分到CLR那個(gè)層面上去實(shí)現(xiàn)了;去看一下CLR的開(kāi)源實(shí)現(xiàn)SSCLI,你會(huì)發(fā)現(xiàn),整個(gè)虛擬機(jī)平臺(tái)的實(shí)現(xiàn),大量運(yùn)用了COM的思想和機(jī)制,就是一個(gè)巨型系統(tǒng)平臺(tái)級(jí)的COM server;
其次,COM規(guī)范本身是獨(dú)立于實(shí)現(xiàn)語(yǔ)言的,只要構(gòu)建出的組件符合規(guī)范制定的二進(jìn)制兼容,系統(tǒng)就可以運(yùn)作,這和C++是否落后時(shí)代沒(méi)有關(guān)系。如果開(kāi)發(fā)人員認(rèn)為,.net才夠先進(jìn),也完全可以用.net中的托管語(yǔ)言,如C#來(lái)實(shí)現(xiàn)COM組件;
最后,每種語(yǔ)言都有其適用的范圍,現(xiàn)在可以這么說(shuō)“如果有一個(gè)全新的項(xiàng)目需求,要達(dá)致跨邊界和對(duì)象透明組件,并且沒(méi)有太過(guò)嚴(yán)苛的性能需求,那么.net平臺(tái)及其上的托管語(yǔ)言來(lái)實(shí)現(xiàn),比用C++及相關(guān)輔助類庫(kù)來(lái)以COM組件形式來(lái)實(shí)現(xiàn),要更合適,也更快速便捷和節(jié)省預(yù)算。”但是,在這個(gè)判斷上我們加了很多嚴(yán)格的約束,一旦需求變更,特別是項(xiàng)目的非功能性需求,要求高性能運(yùn)算或者更順暢的與legacy的native系統(tǒng)相互,那么“使用native語(yǔ)言來(lái)實(shí)現(xiàn)性能關(guān)鍵以及l(fā)egacy交互功能,通過(guò)COM封裝,再由COMInterop交.net托管應(yīng)用調(diào)用”可能是更現(xiàn)實(shí)的方案。C++是一門活的語(yǔ)言,不斷發(fā)展的語(yǔ)言,即使在最新的托管時(shí)代里,C#成為標(biāo)準(zhǔn)主流,但C++/CLI仍然是托管語(yǔ)言里功能最完整的語(yǔ)言。