【關於 Essential COM】
侯捷 jjhou@ccca.nctu.edu.tw
1999.01.12 第一次發表於
清大.楓橋驛站(140.114.87.5).電腦書訊版(Computer/CompBook)
-----------------------------------------------------------
●98 未完紀事
讀者們殷殷垂詢的兩本書:<System Programming for Windows 95> 譯本
和 <Essential COM> 譯本,讓我在此做個報告。
<System Programming for Windows 95> 譯本早於 12 月中旬交稿。
松崗已於 12 月下旬付印。雖然我還沒有收到書,算算日子不是今天
也該是明天了吧。
<Essential COM> 譯稿已於今日完成。我將再完整看過一遍。預計於
1999/01/22 交稿給碁峰。那麼,農曆年前出版上市應該是可以期待的。
●關於 <COM Essential>
這本書中譯名為 <COM 本質論>。如今製作已近尾聲。我將此書之
四篇序文播於網路,以饗讀者。
【譯序】- 侯俊傑
關於本書定位,我沒有辦法一言以敝之。
量子力學大師波耳(Niels Bohr,1922 諾貝爾物理獎得主)曾說:
『思考量子理論而不頭昏眼花的人,根本不懂量子理論』。
我稍帶誇張地借用這句話:
『學習 COM 而不頭昏眼花的人,根本未曾進入 COM』。
然而,量子理論之所以令人頭昏眼花,是因為它與牛頓力學不符,
與我們認知的常識不符。COM 之所以令人頭昏眼花,卻是因為
想要認識它的人,根基通常都不夠。
基本上,學習 COM,你需要具備不少基礎知識:
★要知道 Component Object Model 的最初發展原由,你需得瞭解
C++ Object Model 的缺點。唯因清楚世界上最通行的物件導向語言
C++ 之所不能,你才能夠清楚瞭解 COM 之所能(註1)。
★要認識 component 的體質,你必須知道什麼是 DLLs。
★要瞭解 COM 的 apartment model,你必須知道什麼是 threads。
★要瞭解 COM 的分散性質和 security,你必須多少知道一點 IPC、一點 RPC。
★要瞭解 COM 的組態性質,你必須知道什麼是 Windows Registry。
是的,如果我們有了必要的 C++ Object Model 知識(我指的是虛擬
函式的內部機制、自然多型與非自然多型、static_cast、dynamic_cast
的意義),並且在學習 COM 之前先明白 COM 究竟要解決軟體界的
什麼問題,我們就可以逐步擺脫頭昏眼花的狀態,進入萬物靜觀
皆自得的層次,然後就可以逐步將視野擴展到分散式電算環境中的
各個主題。
換言之,雖然或許人人都耳聞 COM 大名,但它並不是一個程式新手
應該追尋的目標。你必須對物件導向程式開發工具(C++ 語言尤佳)、
作業系統概念、分散式處理原則都有一些基礎,才具備進入這個領域
(並深刻瞭解它)的本錢。所以,以下我所謂的新手,非指程式開發
的全然新手,而是指具備了上述基礎的 COM 新手。
做為本書譯者,我在這裡介紹其他 COM 書籍,有點奇怪。但以資訊
教育者的身份,以及書評人身份,為讀者鋪陳理想的 COM 學習之路,
實乃份所當為。我認為,COM 相關書籍大約可分四類:
1. 入門 例如 Inside COM (Dale Rogerson/Microsoft Press)
2. 進階 例如 Essential COM (Don Box/A.W.) 和
DCOM programming(Richard Grimers/WROX Press)
3. 實作經驗 例如 Effective COM (Don Box etc/A.W.)
4. 觀念整理 例如 Understanding ActiveX and OLE
(David Chappell/Microsoft Press)
以目前國內軟體工程界對 COM 的認識程度,我們最需要的恐怕是
第一類。Inside COM 是一本很容易上手的書,我很推薦。但如果
想要知道「COM 來龍去脈」,還得參酌 Essential COM 第一章。
適才我說過,沒有辦法簡單一句話就說明 Essential COM 的適合對象,
原因便是雖然本書前兩章極適合牽引你進入 COM 領域,但其他章節卻又把
COM 挖得很深,深到即令具備 COM 經驗的老手讀來亦覺吃力。
自從網路上公佈我將翻譯此「COM 本質論」之後,中譯本受到眾多
讀者的期待,我也收到為數極多的 email 詢問信函。但是我想,
不是每一位期待它的人都有馬上享用它的能力,這一點必須提醒你。
當然,以「好書千萬不要錯過」的心情立刻讓它進駐你的書架,
是我的大安慰。
如果你閱讀本書第一章仍覺吃力,那麼你需要先補強 C++ Object Model
的知識。以下是我推薦的兩本書:
1. Inside the C++ Object Model, chap3,4(Lippman/Addison Wesley/1996)
中譯本:深度探索 C++ 物件模型(侯俊傑譯/碁峰/1998)第三章,第四章
(建議看中譯本,因為原文本筆誤極多)
2. 多型與虛擬(Polymorphism in C++)(侯俊傑著/松崗/1998)第二章
有趣的是,COM/OLE 領域中重要的兩本著作的作者,都提到了一種
奇異的頓悟經驗。Inside OLE(註2)作者 Kraig Brockschmidt 說:
---------↓
我隱約感覺 OLE 遠比我原先認知的不同,卻又很難打斷 OLE 與
複合文件之間的等號,因為每一份技術報告都把兩者視為同義。
我逐漸瞭解,OLE 事實上已經建立了一個非常巨大的系統,
一個在 Windows 之下的物件導向程式設計系統。1993 年一月的
某個週日下午,我突然獲得了所謂的 OLE 涅槃狀態。所有關於 OLE
的支支節節突然全都歸定位。歷經六個月的模糊心智之後,我突然
看清楚了 OLE。
---------↑
Essential COM(本書)作者 Don Box 說:
---------↓
我一直未能對「COM 程式模型為什麼設計成這個樣子」有結構上的
瞭解。幸運的是有一天(1994 年 8 月 8 日),突然像神蹟一般,
COM 對我變得再明白不過,我終於瞭解了 COM 的設計動機。如何
把這個程式模型應用在每天遇到的問題中,也因此顯得再明白不過。
---------↑
兩位先生的話,令人覺得學習 COM/OLE 之前要先有宗教信仰,以求
進入涅槃或獲得神蹟。其實沒有漸悟是不可能成就頓悟的,大師開悟
之後的種種心法都已詳實記錄在他們的「嘉言錄」當中,就看我們
自己的用心了。
祝各位早日進入涅槃(註3),獲得神蹟。
註1:雖然 COM 與任何電腦語言都沒有依附性,但 C++ 的純虛擬函式
是最貼近 COM interface 的機制。
註2:Inside OLE, 2nd edition,Microsoft Press,1995
註3:喔歐,當然我是指 OLE 涅槃 :)
【Charlie Kindel 序】
當我坐下來開始寫這篇序時,我的心中盤旋著三個念頭:
o. Don 的像片會出現在封底嗎?如果是,他的頭髮有多長?
o. 這本書的讀者知道 Don 有一張上面寫著 "IUNKNWN" 的車牌嗎?
o. 一個人到底能夠在一本書的序言裡寫些什麼?
關於到底要寫些什麼,我有兩個點子。一個就是寫下我長久以來想寫
的有關於 COM 設計理念之類的東西,另一個就是像 Don Box 為了取
悅我而邀請我寫序一樣地寫些諂媚文字取悅他。我決定兩者都做。
什麼是 COM?為什麼發明 COM?Don 在第一章簡潔地回答了這個問題。
在導入的那一節中他寫道:「本章表現了一個可重複運用的 component
架構,此架構允許各獨立開發的 binary components 得以動態並有效
地組合為一個系統」。這一章的其它部份帶領你走過 COM 設計者的足跡
與思想,這些想法歷經了 1988~1993 年代(當時 COM 初問世)。
我認為 COM 長遠的成功要歸因於數個設計因素,第一是實用,然後是
簡化,然後是彈性。
●實用
COM 以極務實的方法追求軟體設計的理想。COM 捨棄學院派的物件導向
程式設計教條,考慮了人性和資本主義。最好而最具商業價值的古典物件
導向概念已經被設計小組挑選出來,並與 Microsoft 之內或以外的專案
計劃結合在一起。
大部份 OO 教科書都說,如果一個語言支援封裝(encapsulation,資訊
隱藏)、繼承(inheritance)和多型(polymorphism),它就是個物件
導向語言。繼承常常是「可重複運用」的重點。但是 COM 設計者
並不同意這種觀點,他們認為這是一種過度簡化的看法,他們認為
inheritance 實際上有兩種:「implementation 繼承」表示真正的行為
被繼承,「interface 繼承」則表示只有行為的規格被繼承下來。後者才
能做到真正的 polymorphism。COM 完全支援這種型式的繼承。換句話說
「implementation 繼承」只不過是個允許我們重複運用既存實作碼的
機制;如果「重複運用」是終極目標,「implementation 繼承」就只是
邁向目標的途徑之一,而非目標本身。
不論在研究領域或商業應用,「implementation 繼承」都已被視為一種
強而有力的工具,不過卻可能導至 base class 和 derived class 之間
過度的牽扯(所謂的耦合,coupling)。由於「implementation 繼承」
常會造成 base class 實作細節外洩,違反封裝性質,COM 設計者認為
「implementation 繼承」的使用會對 components 的開發帶來限制。
雖然 COM 並不在 components 之間支援 implementation 繼承,但卻
能夠在 components 之內支援之。COM 也完全支援 interface 繼承
(事實上 COM 完全仰賴這一點)。
COM 設計者並不特別強調繼承。繼承通常被視為達到重複運用(reuse)
的一條路徑。COM 用以模塑重複運用性的基本觀念,是封裝而非繼承。
繼承之於 COM 的用途,是用來模塑「共享類似機能之各 objects」間的
型別關係。以封裝來建立 COM 的重複運用模型,設計者於是便可以鼓勵
一種黑盒子般的重複運用性,符合預期中的 component 市場。他們的想
法是:clients 應該視 objects 為不透明的 components,不管其內部
有什麼,也不管它們如何實作出來。COM 設計者相信,應該設計出一個
架構以實現這個想法。但又為什麼要設計一個系統有著不同的重複運用
模型呢?好問題!事實上,這個世界充滿了一些並非黑盒子般封裝(甚至
連要完成它都頗困難)的物件導向系統。C++ 就是個典型的例子。本書
第一章中,Don 對於我在這裡所說的意思描述得非常清楚。
以下方程式說明了物件(object)導向程式設計和組件(component)
導向程式設計之間的不同:
★物件導向程式設計 = 多型 +(一些)後期繫結 +
(一些)封裝 + 繼承
Object-Oriented Programming = Polymorphism + (Some) Late Binding +
(Some) Encapsulation + Inheritance
★組件導向程式設計 = 多型 +(真正的)後期繫結 +
(真正而厲行的)封裝 + interface 繼承 + 二進位碼重複運用
Component-Oriented Programming = Polymorphism + (Really) Late Binding +
(Real, Enforced) Encapsulation + Interface Inheritance + Binary Reuse
出沒於 comp.object 和 comp.object.corba 論壇的那些 OO 純粹
主義者可能會心煩地指著 COM 說「但它並不是真正的物件導向」。
你可以下列兩個觀點反駁:
1. 它也是 OO!只不過你誤解了 OO 的定義!
2. 那又怎樣?COM 在商業上異常成功,成千上萬的獨立軟體開發者
經由安插、修改、整合就狂風落葉般地完成了他們的偉大軟體,而且
也賺到了錢(註1)。他們所寫的軟體組件被採購、被使用、被重複
運用。這不正是任何一種技術的真正重點嗎?此外,我也可以反駁說
唯有 COM 才是真正的物件導向(註2)。
註1:根據 Giga 接受 Microsoft 委託所做的一份調查顯示,商業性
COM-based 組件在 1997 有 US$410M 的市場潛力。估計這個市場將於
2001 成長至 US$2.8B。這些數字並未包含 Micorosft 的產品。
註2:一個小小測驗:請你說出除了 COM 之外的一個商業性物件系統,
提供 binary resue 模型,支援穩健的版本更替解決方案(versioning)
和位置透通性、並獨立於任何電腦語言之外。如果你回答 CORBA,你
已受騙而不自知。
●簡化導至可鍛性(Simplicity Leads to Malleability)
mal.le.a.ble 是個形容詞:
1. 有被形塑的能力(或因鎚打,或因壓力)。
例句:a malleable metal
2. 容易受控制或受影響;馴良而易處理的。
3. 有能力調整以改變境遇;可適應的,可改編的,可通融的。
例句:the malleable mind of the pragmatist(註3)
註3:引自 The American Heritage Dictionary of the English Language, 3/e,
1996 by Houghton Mifflin Company.
COM 的第一個真正應用是 Microsoft 以之做為複合文件架構 Object
Linking & Embedding(OLE)2.0 的基礎。如果你思及今天 COM 被
施行的眾多方式,你一定能夠立刻認知我所謂的可鍛性。程式員利用
COM 為其應用程式提供外加(plug-in)架構、建立大規模商務性交易
用的 multitier client/server 應用程式、在網頁上提供 eye candy???、
控制並監視製造程序、甚至經由遠端控制望遠鏡群以追蹤間諜衛星。
這樣的可鍛性來自一個事實:COM 的設計重點在於讓模型核心儘可能
簡單。C 或 C++ 程式員必須處理所有「汙穢黏滑的東西」,包括 GUIDs
和參用計數(reference counting)。然而所有的繁複都已被 COM 涵蓋
於內,達到簡化的目的。COM 建築師並不強求讓此模型運作,他們知道
如果他們成功,支援工具很快就會進入市場。這樣的假設已因為
最近問世的便利工具而獲得證實,這些工具包括 Visual Basic、
Visual C++ 5.0 對 COM 的支援、和 Active Template Library(ATL)。
當你閱讀此文之時,Microsoft 已經宣佈未來計劃利用一個共同的
執行時期程式庫 COM+(適用於所有工具)來根本簡化 COM 開發工作。
●鄉野傳聞
任何技術如果像 COM 那樣廣被傳佈,就會開始衍生出一些鄉野傳聞。
純粹好玩,我列出以下一些傳聞。你可能沒聽過它們,其中一些甚至
是真的。
★ Microsoft 有許多人對於 COM 的設計貢獻卓著,其中最主要的
建築師是 Bob Atkinson、Tony Williams 和 Craig Whittenburg。
這三人都還在 Microsoft 工作。
★ Bob、Tony 和 Craig 三個人屬於一個跨部會小組,特別允許發表
某些核心技術,此技術可使 Bill Gates 的 IAYF(Information at
Your Fingertips,資訊盡在指尖)願景成真(註4)。雖然三個人對
於 COM 未來的威力非常清楚,但他們三人被綁在「COM 的實用性產品:
OLE 2.0」的出貨重任上,這足以解釋為什麼 COM 說明文件需要如此
久的時間。關於我的吐槽,抱歉啦!
註4:你可以回顧 Bill 於 1990 有關 IAYF 的演說。
★ COM 的第一份實作品包裝於 1993 五月問世的 OLE 2.0。
★ root interface(當時並不被稱為 IUnknown)有一個 GetClassID method。
它被移往 IPersist,這一事實說明了「保持 COM 儘可能簡單」的原則。
★有一段時間,IUnknown 並無 AddRef method。但慢慢地 COM 設計
者瞭解到,不讓人們複製 interface 指標,會造成重重的束縛。
★ "IUnknown" 之所以命為 "Unknown",是源自於一份 Microsoft
1988/12 的內部文件。該文由 Tony Williams 發出,標題為
"Object Architecture : Dealing with the Unknown -- or --
Type Safety in a Dynamically Extensible Class Library"。
★ 以 RPC 做為 process 間的遠端機制,是 1991 前兩個月決定的。
Bob Atkinson 寫了一份備忘錄名為 "IAYF Requirements for RPC",
說明必要條件,交給 RPC 小組(後來改名為 IAYF 小組,負責建造
「讓 Bill Gate 的願景 "Information at Your Fingertips" 得以實現」
的基礎。這份基礎便是 COM(雖然當時不是這個名字)。
★ Monikers 比你所想像的還有威力。
★ 有些人以為 COM 是 "Common Object Model",這都是 Mark Ryland
惹的禍。他深深感到後悔並願意致上最大歉意。
★ MEOW 並不是 Microsoft Extensible Object Wire 的縮寫。
★ Windows NT 3.5 含有第一份 32 位元 COM 和 OLE。有人意外地
在表頭檔中留下了一個 "#pragma optimization off",喔歐,真是的!
如果有一本英文書談論 COM、DCOM、OLE 或 ActiveX,而我也讀過它,
你幾乎一定會發現我的名字被列在技術檢閱那一欄,做為信譽保證。
我自己也寫了許多這方面的文章,我同時也是 COM 規格的主要編寫者。
我給過無數的 COM 簡報,不管對象是技術人員或非技術人員。顯然,
我花了許多時間和精力,嘗試找出 COM 的最佳解釋方法。
當我讀過這本書的最後草稿,我明白我所有的努力都白費了。關於 COM,
沒有任何人闡釋得比 Don Box 更棒!
Charlie Kindel
COM guy, Microsoft Corporation
September 1997
【Grady Booch 序】
一本書的好東西如果太多,就值得說兩次。這是為什麼 Don 這本書
有兩篇序的原因。
如果你正在 Windows 95 或 NT 上建立系統,你不可能遠離 COM 的
範疇。Visual Studio -- 特別是 Visual Basic -- 隱藏了 COM 的
某些複雜度,但如果你想要 (1) 瞭解檯面下發生什麼事 (2) 利用
COM 的強大威力,Don 這本書很適合你。
我特別喜歡這本書的一點是,Don 在說明 COM 時的組織方式。你首先
會曝露在分散式(distributed)系統和並行(concurrent)系統的建構
主題上,然後你會獲得謹慎而完整的說明,顯示 COM 如何解決那些問題。
如果閱讀本書時你對 COM 一無所知,你會被一個清晰簡單的 COM 概念
模式導引,使你瞭解問題之所在,以及「讓 COM 獲得其結構和行為」的
力量所在。如果你是一位有經驗的 COM 開發人員,那麼你一定會特別
欣賞 Don 以 COM 解決一些常見問題時所提出的各種角度的討論。
開發分散式系統和並行系統時,COM 是最被廣泛使用的一種物件模型。
本書可以幫助你利用 COM 成功部署這樣的系統。
Grady Booch
【自序】- Don Box
我的工作終於完成了。在我終於將「口述 COM 歷史」寫成一本書之後,
我終於可以休息了。這本書反映出我個人對於 Microsoft 於 1993 揭示
的這個惡夢般的術語(COM)的瞭解演繹。雖然我並未出席最初的 OLE
專業開發人員研討會,卻感覺自己對 COM 似曾相識。幾乎四年與 COM
的朝夕相處,使我對於那個 COM 尚未出現的年代只剩下勉勉強強的回憶。
然而 1994 年初我移居到 COM 這塊土地上的痛苦,至今記憶猷新。
在我感覺終於瞭解 COM 之前,我花費了幾乎六個月的時間。與 COM
共舞的最初六個月裡,我可以成功地寫出 COM 程式,也幾乎可以解釋
它們為什麼能夠運作。然而我一直未能對「COM 程式模型(programming
model)為什麼設計成這個樣子」有結構上的瞭解。幸運的是,有一天
(1994/8/8,差不多在我購買了 Inside OLE2 六個月之後),突然
像神蹟一般,COM 對我變得再明白不過,我瞭解了 COM 背後的主要動機。
如何把這個程式模型應用在每天遇到的程式問題當中,也變得再明白不過。
許多程式開發人員也有相同的經驗。三個年頭後的今天,當我寫下這篇
序文,程式人員仍然必須走過六個月的等待期,才能成為 COM 社群中具
生產力的一員。我想這本書或許可以縮短這個週期(但我不能保證)。
一如本書所強調,COM 比較像是一門程式設計素養,而不是一項技術。
我並不打算以每一個 interface 的每一個 method 的每一個參數的細節
描述來驚嚇讀者。相反地,我嘗試蒸餾出 COM 的本質是什麼,而將每一
章所遺留的縫隙留給 SDK 文件去填充。任何地點,只要可能,我便嘗試
指出某一特別之 COM 觀念的底層張力,而不是提供詳細的範例,告訴
你如何在一個巧妙的例子中應用每一個 interface 和每一個 API 函式。
我自己的經驗顯示,一旦瞭解了 why,how 的問題也就迎刃而解。相反地,
如果只是知道 how,就少了對文件背後足夠的洞悉能力。這份洞悉能力
非常重要 -- 如果你希望跟上持續演化的程式模型。
對於建立一個分散式物件導向系統而言,COM 是個十分具有彈性的基礎。
為了獲得 COM 彈性所帶來的優點,你必須常常思考 SDK 文件、期刊文章、
書籍以外的各種限制。我個人建議,假想你閱讀的所有東西(包括本書)
可能是不正確的,或是過期失效了,然後想辦法將你個人對程式模型的
瞭解組織起來。瞭解程式模型的最確實方法就是精通基本語彙,這恐怕
只能從撰寫 COM 程式並分析這些程式為什麼可以運作的過程中獲得。
閱讀書籍、論文、技術文件可能也有幫助,但究竟有限。將時間放在
對 COM 四大核心觀念(interfaces, classes, apartments, security)
的思考上,可使你比較快成為一個 COM 開發人員。
為了協助讀者專注於這些核心觀念,我嘗試含入儘可能多的碼,但僅
止於原始碼的呈現,不為讀者提供詳細的推敲。為確保 COM 程式技術
也能呈現於文字之中,附錄B有一個完整的 COM 應用程式,那是本書
所討論的眾多觀念的總集。此外,本書提供了一些可從網路下載的範例,
包括一個由 COM 公用程式碼所組成的函式庫,這個函式庫在我自己的
軟體開發過程中確實有用。這個函式庫的某些部份在本書有詳細的討論,
不過整個函式庫是被含括於一個展示品中,示範如何架構標準的 C++
實作碼。請注意,書中許多程式碼都使用 C 函式庫巨集 assert 來
強調某些必須吻合的前後狀態。在真正上市的產品中,這些 assert 有
許多都應該以更寬大的錯誤處理方式取代之。
出版一本書,有一個缺點就是,當它們到達各地書店之後,常常很快就
過時了。這本書亦不例外。特別是目前尚未定案的 COM+ 和
Windows NT 5.0,勢必造成本書在各方面的不正確或不完整。我已經
在書中嘗試預判 Windows NT 5.0 所呈現的模型演化;然而在下筆此刻,
Windows NT 5.0 尚未進入 beta 測試,所有資訊都有可能變化。COM+
承諾將此程式模型做更大的進化;然而我實在不可能一方面將 COM+ 含入
一方面仍然能夠於今年交出本書手稿。我高度鼓勵你在 Windows NT 5.0
和 COM+ 差不多定形的時候,好好研究它們。
我必須做一個非常痛苦的決定,在各式各樣的商業函式庫當中,選出
一個以 C++ 來實作 COM components 的工具。觀察了各個網際網路
討論群上的常見問題之後,我決定放棄 ATL 和 MFC,而把焦點放在
COM 的基本主題上,那是每一位開發人員不管使用什麼函式庫都必須
精通的東西。愈來愈多開發人員以 ATL 製造出一堆複雜的碼,卻奇怪
它們為什麼不能運作。我全然相信一個人不可能以 ATL 或 MFC 來學習
COM。這並不是說面對 COM components 的開發時 ATL 和 MFC 不是
有用的工具,我意思是說它們並不適合展示或學習 COM 程式設計的
觀念與技術。在一本焦點放在 COM 程式設計模型的書籍中出現 ATL,
將因此顯得格格不入。此外,許多程式設計者的共同經驗是,一旦
瞭解了 COM,極短時間內便可以精通 ATL。
每一章開頭的引言,使我有機會寫出我對本書的一小段感覺。為了
努力讓我的寫作儘可能保持直接的風格,我限制這種狂野而偏離主題
的故事每一章不得超過 15 行 C++ 碼。通常這份引用碼都是用來表示
該章所呈現的觀念或問題的 COM 之前的解法。或許讀者可以藉此解構出
當我根據這些提示寫出一章文稿時的心靈狀態。
●致謝(Acknowledgments)
略
Don Box
Redondo Beach, CA
August 1997
http://www.develop.com/dbox
--- the end
--
※ Origin: 楓橋驛站<bbs.cs.nthu.edu.tw> ◆ Mail: jjhou@ccca.nctu.edu.tw