討論元件的原則前,我們先定義什麼是「元件」。Uncle Bob 給出了一個技術上的定義:

「元件是 部署(Deployment) 的最小單位。」
(Components are the units of deployment.)

  • Java: .jar
  • Ruby: Gem
  • .NET: .dll
  • 編譯語言 (C/C++): 連結後的二進位檔或執行檔

若設計得當,這些元件應具備兩特性:

  • 獨立部署(Independently deployable)
  • 獨立開發(Independently developable)

一、元件簡史:從混亂到外掛#

元件演進史,其實就是一部與硬體限制搏鬥的歷史。

1. 史前時代:絕對位址的惡夢#

早期程式設計中,程式員須在程式碼中指定「絕對記憶體位址」。

  • 問題: 如果你要用一個函式庫(Library),你須將它的原始碼包含進來,
    並確保它佔用的記憶體位址不會跟應用程式衝突
  • 後果: 程式越大,編譯時間越長

2. 重定位與連結器 (Relocatability & Linkers)#

為解決這問題,人們發明了「可重定位二進位檔(Relocatable Binaries)」和「連結器(Linker)」。

  • 解決: 編譯器將原始碼轉為 Object files(.o),
    連結器負責將這些檔案「黏」在一起,並動態分配記憶體位址
  • 瓶頸: 隨著程式變大,連結(Linking)過程變得極度緩慢,可能需要數小時

Figure 12.2: Splitting the application into two address segments

3. 摩爾定律的救贖#

隨著摩爾定律(Moore’s Law)生效,硬體速度指數級成長,磁碟變快、記憶體變大。

  • 轉變: 連結器的速度終於追上了編譯器
  • 連結載入器 (Linking Loader): 我們不再需分開執行「連結」步驟。
    我們直接將多個 .jar.dll載入記憶體,系統會在 載入時(Load time)甚至執行時(Runtime) 瞬間完成連結

二、結論:外掛架構的誕生#

正因「連結載入器」運作如此快速且高效,現代軟體架構才得以實現 外掛架構 (Plugin Architecture)

  • 意義: 我們可將系統拆解為多個 .jar.dll 檔案
  • 彈性: 這些檔案(元件)就像是外掛,可以隨時被抽換、更新,
    而不需重新編譯系統。這就是元件化設計的終極型態