到底什麼是 “Component(元件)”?

前陣子看到討論區有人提問,元件與類別有何不同?
直覺上,覺得蠻奇怪的,怎麼會拿這兩者來比較?因為這兩者是不同等位的:類別是虛的;元件是實的。

類別,即是種類上的區別。簡單的說,即是「物以類聚」。自然而然,我們會把較同性質的事物擺在一起,以別於其他的事物。
所以,分類是一種本能(不一定單指人類才有這種本能),是一種從抽象的角度來區別事物在行為或特徵上的不同點。
為了作比較,我們會區分為動物類、植物類;再更進一步的觀察,又會再把動物類更細分為哺乳類、爬蟲類...等。在更深入,會再將哺乳類細分為人類、狗、貓、猩猩、猴子等各種類別...。
以此推知,元件也會分門別類,諸如,UI(User Interface)元件、企業元件(Business Component)、功能性元件(Functional Component)等。

在軟體設計上,如何分類,是一門相當深入的功夫。這又是另外一篇重要的主題了。
回到本標題,真要作比較,可能是元件(Component)與物件(Object)來作比較說明會來得恰當。

學習軟體設計多年,我個人覺得有兩個專業的字彙,是最難最難解釋的了:一個是 “架構(Architecture)”;另外一個就是 “元件” 了。因為,這兩個字太容易太容易被濫用及泛用了。
針對上述兩個字彙,我個人也思考多年,或多或少有些自己的見解(至現在為止,除了高煥堂大師有這種能耐可以解釋這兩個字彙,我還沒有看過有人可以說出此兩個字彙真正的意涵)。
因為是我個人的見解來解釋什麼是 “元件”。並無所謂絕對的「對」與「錯」,只能說:僅供參考!

先說明什麼是物件(Object)?一言以蔽之:「Everything is Object」!你所看到的,全都是物件。
咖啡是物件、汽車是物件、主機板是物件;咖啡的元素咖啡豆也是物件、汽車引擎也是物件;CPU也是物件。
物件有大有小,端賴於你何時要將一個物件視為 “整體(Whole)” 時,來觀察該物件的特徵及外顯的行為。

例如,當我買一台DVD錄放影機時,我所觀察到的是這台DVD錄放影機整體的功能及效能為何,至於內部是由哪些組件(物件)所組成,一般消費者並不關心;但,若是玩家級的玩家,可能會關心到該錄放影機的硬碟儲存容量問題,他可能會興起更換硬碟的念頭。此時,該玩家已經不是僅將錄放影機視為一個整體的 “Whole”,而是剖析、深入至內部的 “Part” 組件了。當然,對該玩家而言,他可能最多關心到硬碟的品質與容量等問題,但,若當該硬碟發生故障時,維修工程師又要更深入一層,關注到硬碟內的 “Part” 組件,以瞭解故障的原因為何。

“Whole” 與 “Part” 其實是相對的,你所想關注的焦點,那一點就是 “Whole”。把所觀察的事物視為一個 “Whole” 時,目的就是為了瞭解該整體所表現出來的特徵及行為,並且,是適時地 “封裝(Encapsulation)”了其複雜度:忽略掉了 “Part” 的細節。

那麼,到底,什麼又是元件(Component)呢?我個人是這麼認為...

元件,其本質其實就是物件!但最大的不同點在於:物件強調的是 “個體(Instance)” 的特徵及外在行為;而元件強調的是 “介面(Interface)” 的溝通。

若以類別圖(Class Diagram)來表達元件的話,可以參考如下圖所示:

以類別圖來表達元件

從程式設計的角度來看時,會認為元件化的設計即在於依循業界的標準規格,如 Microsoft 的 COM -> COM+ -> .NET 元件;Sun Java Group 所制訂 JavaBean、EJB(Enterprise Java Bean)元件;OMG 所推的 CORBA 元件。

但從軟體設計的角度來看時,元件的定義並非如此的狹隘。更甚者,從自然生態界來觀察,小至原子、基因;大至地球、太陽系、銀河系,甚至全宇宙都可稱之為元件。

所以,反映至軟體系統,小至 WebPage(ASP Page、Php Page、JSP Page…)、UI widgets(Button、Textfield、Label …)、UI Forms(WebForm、Windows Form)、企業元件(以 .NET、Java Object、JavaBean、EJB等來實做);大至 模組(Module)、子系統(Sub-System)、甚而整個企業應用系統等,都可稱之為元件。

既然,任何事物都可稱之為元件,那麼,又如何來定義及切割(Divide)元件呢?

“元件,提供了觸角(稱之為介面, Interface),以服務其他元件的呼叫使用。至於元件的內部實做,則被封裝隱藏起來。所以,無論元件內部狀態如何的變化,只要所提供的介面是不變的,那麼,外部元件就不會因為該元件的變動而變動。”

元件的單位有大有小。

顆粒度細緻(fine-grained)的元件,會比較接近本質性(Essentiality)、單一性(Atomic)。所提供的介面是屬於高度穩定的。
領域物件(Domain Object),係源自於該領域所經常溝通的術語(terminology),具備著高度的穩定性及本質性,即屬於此類型的元件。(Customer、Employee、Order、Sales…等,這些術語過 100 年都還不會變。)

顆粒度粗糙(coarse-grained)的元件,也可稱之為聚合(Composite)元件,是基於完成某項功能或為提供服務而聚合了欲完成該功能或服務的多個 “Part” 組件來達成任務。其所提供的介面是較不穩定的(功能會基於需求而善變)。
模組(Module)、子系統(SubSystem)等,是屬於 “coarse-grained)” 元件 — 基於服務或功能而形成的聚合元件。

既然元件式的開發所強調的完全是以 “介面(Interface)” 為主要的溝通,所以,”介面”是主角;而實做該介面的”物件”反而變成配角了。
這是一件很有趣的事。介面相對於實做的物件,介面是”虛”的;物件是”實”的。

現今的軟體設計已不再強調古典物件導向式的開發,而越來越走向元件式的開發(再一次強調,非指業界所稱之的元件規格,如 COM+、EJB…等),亦即,更專注在 “介面” 的設計!

*** 原因在於現今的系統已不再只能假設是單一、獨立所開發的;更甚於此,有許多系統是既存、異質,但又必須整合成為整體的系統。所以,如何整合、如何分析出既存系統的介面,正是元件式開發的最大特點。 ***

藉此可以一併思考,從事軟體一職的開發者,到底所真正重視的是物件實做面的技術?還是,真正用心在 “純” 軟體設計的領域上,專注這些基本功夫(如介面設計)的修練呢?