01

中介軟體與分散式物件的核心精神

中介軟體提供更高層次的程式抽象,藏起底層異質性,讓互通與可攜變得可能。

先讀原文段落,旁邊就是白話

這是一本英文書。左邊放原文、右邊放白話導讀——你既讀得懂,也順手碰了原文。

原文 · 中介軟體與分散式物件的核心精神 335 8 DISTRIBUTED OBJECTS AND COMPONENTS 8. 4 From objects to components 8. 5 Case studies: Enterprise JavaBeans and Fractal 8. 6 Summary A complete middleware solution must present a higher-level programming abstraction as well as abstracting over the underlying complexities involved in distributed systems.
白話導讀

中介軟體提供更高層次的程式抽象,藏起底層異質性,讓互通與可攜變得可能。

中介軟體在忙什麼

中介軟體提供更高層次的程式抽象,藏起底層異質性,讓互通與可攜變得可能。

STEP 1

深度探秘

中介軟體到底夾在哪兩層之間

中介軟體是「夾心餅乾的中間層」

一個完整的分散式系統,底層是各種異質的硬體、作業系統與網路;上層是你想寫的應用程式。問題是:底層長得五花八門,你的程式不該被這些細節綁死。

中介軟體 (middleware) 就是夾在中間那層,它有兩個任務:

  • 提供更高層次的程式抽象,讓你寫分散式程式時不必每次都從 socket、封包打包開始。
  • 透過分層 (layering) 把底層異質性藏起來,促進互通 (interoperability)可攜 (portability)

互通=不同實作之間能彼此溝通;可攜=同一份程式能搬到不同平台跑。

本章聚焦兩種最重要的中介軟體風格:分散式物件 (distributed objects)元件 (components)

💡
關鍵

中介軟體提供高層抽象並隱藏底層異質性,讓分散式程式好寫又能跨平台。

STEP 2

生活妙喻

中介軟體就像國際會議的同步口譯

同步口譯員的比喻

想像一場聯合國會議,與會者講英文、法文、中文、阿拉伯文(這就是異質的底層平台)。如果每個人都要學會其他所有語言才能開會,根本辦不成事。

口譯員坐在中間,你只要對著麥克風講母語,對方就能用他的母語聽到——你完全不用管翻譯怎麼運作。

  • 口譯員 = 中介軟體
  • 「對著麥克風講母語」= 高層程式抽象
  • 「不用學其他語言」= 隱藏異質性
  • 「大家都能參與會議」= 互通與可攜
flowchart TD
  A[應用程式] --> B[中介軟體 高層抽象]
  B --> C[作業系統與網路 異質底層]
  B --> D[隱藏異質性 促進互通與可攜]
💡
關鍵

中介軟體像同步口譯,讓你只講母語就能和異質平台溝通。

STEP 3

實用超能力

為什麼物件導向特別適合分散式

物件導向的三個好處,恰好對症下藥

分散式物件之所以受歡迎,是因為物件導向的特質剛好解決分散式的難題:

物件導向特質 帶來的好處
封裝 (encapsulation) 把內部實作包起來,天生適合「跨機器只露出介面」
資料抽象 (data abstraction) 規格與實作乾淨分離,呼叫方只看介面,不管對方用什麼語言或作業系統
動態與可擴充 可以引入新物件,或用相容物件替換舊物件

真實情境:你在寫一個跨公司的訂單系統,對方用 C++、你用 Java。只要雙方同意一份「介面」,你呼叫 placeOrder() 時根本不用知道對方是什麼語言寫的——這就是封裝與資料抽象的威力。

代表性的分散式物件中介軟體包括 Java RMICORBA

💡
關鍵

封裝與資料抽象讓呼叫方只面對介面,這正是分散式程式最需要的乾淨邊界。

🔆
生活妙喻:中介軟體 (middleware) ≈ 聯合國會議的同步口譯員

你只講母語、對著麥克風,口譯員把訊息翻給講其他語言的人;你不用學任何外語,就像程式不用管底層平台差異。

🔆
生活妙喻:資料抽象 (data abstraction) ≈ 餐廳的菜單

你看菜單點菜(介面)就好,廚房用瓦斯爐還是電磁爐、廚師是誰(實作細節)你不必知道也不會影響點餐。

本節字彙

中介軟體 (middleware)
夾在應用程式與底層作業系統/網路之間的軟體層,負責提供高層抽象並隱藏異質性。
🧠 middle=中間,ware=軟體,就是「中間那層軟體」。
互通 (interoperability)
不同實作、不同平台寫的系統之間能夠正確地彼此溝通。
🧠 inter=彼此之間,operate=運作,彼此都能運作就是互通。
封裝 (encapsulation)
把物件的內部實作包覆起來,外界只能透過介面互動,看不到內部細節。
🧠 encapsulate=裝進膠囊,吃膠囊不會看到裡面的粉。
某公司想讓用 Java 寫的訂單服務和用 C++ 寫的庫存服務互相呼叫,且未來可能換到不同作業系統上跑。中介軟體最直接幫上的是哪兩件事?
為什麼說封裝與資料抽象「天生適合」分散式程式設計?
下列哪一句最能說明「互通 (interoperability)」與「可攜 (portability)」的差別?

分散式物件:熟悉又陌生

分散式物件沿用 OO 模型,但在 class、繼承、遠端參照、例外與垃圾回收上都和本地物件不同。

STEP 1

深度探秘

同樣叫物件,分散式版本多了什麼

分散式物件 = 物件 + 距離的代價

分散式物件讓你「像呼叫本地物件一樣」呼叫遠端物件,主要靠遠端方法呼叫 (RMI)。但因為物件跑在別台機器上,許多概念被升級了:

一般物件 分散式物件 多了什麼
物件參照 遠端物件參照 全域唯一、可當參數傳遞
介面 遠端介面 用 IDL 指定可被遠端呼叫的方法
動作 分散式動作 一次呼叫可能引發跨機器的呼叫鏈
例外 分散式例外 多了訊息遺失、行程失敗等狀況
垃圾回收 分散式垃圾回收 要跨機器判斷物件是否還被參照

此外,分散式物件世界裡 class 概念被淡化(異質環境難有共同 class 解讀),而且偏好介面繼承而非實作繼承。

💡
關鍵

分散式物件沿用物件模型,但遠端參照、分散式例外、分散式垃圾回收等都是為了應付『距離』而生的新成員。

STEP 2

生活妙喻

本地同事 vs. 遠距外包

找同事 vs. 找海外外包

呼叫本地物件像是轉頭問坐你旁邊的同事一件事——他一定在、一定聽得到、回答幾乎瞬間到。

呼叫分散式物件像是找一個海外外包團隊:

  • 你得有對方的聯絡方式(遠端物件參照),而且這聯絡方式要能轉交給別人。
  • 你只看得到對方公布的服務清單(遠端介面),看不到他們內部怎麼做。
  • 你的一個請求可能讓對方再去找他們的下游廠商(分散式動作的呼叫鏈)。
  • 訊息可能寄丟、對方公司可能臨時倒閉(分散式例外)。
  • 還得有人定期確認「這外包還有沒有人在用」,沒人用才能解約(分散式垃圾回收)。
flowchart TD
  A[客戶端] -->|遠端方法呼叫| B[遠端物件]
  B -->|呼叫鏈| C[下游遠端物件]
  A -.->|可能發生| D[訊息遺失或行程失敗 分散式例外]
💡
關鍵

分散式物件像找海外外包:要聯絡方式、只看服務清單、可能牽連下游、還可能出包。

STEP 3

實用超能力

中介軟體替你扛的額外苦差事

因為有距離,中介軟體要多做這些事

正因為分散式物件比本地物件複雜,中介軟體必須額外提供:

  • 物件間通訊 (inter-object communication):通常用 RMI,也常補上分散式事件等間接通訊。
  • 生命週期管理 (lifecycle management):物件的建立、遷移與刪除。
  • 啟動與停用 (activation/deactivation):物件數量龐大時不可能全部一直開著,要用到才喚醒,閒置就休眠。
  • 持久化 (persistence):物件有狀態,必須跨越啟動/停用循環甚至系統故障保存下來。
  • 額外服務:命名、安全、交易等。

為什麼要啟動/停用? 想像一個有上百萬個物件的伺服器,如果全部常駐記憶體會爆炸;所以平常讓它們「睡覺」,有請求進來才「叫醒」(activation),就像旅館不會把每間房的燈都開著等客人。

💡
關鍵

距離帶來複雜度,於是中介軟體得扛起通訊、生命週期、啟動停用、持久化與各種服務。

🔆
生活妙喻:遠端物件參照 (remote object reference) ≈ 海外外包的聯絡方式

它是全域唯一的『聯絡卡』,可以交給別人去聯絡同一個遠端物件,就像把外包窗口的名片轉交給同事。

🔆
生活妙喻:啟動與停用 (activation/deactivation) ≈ 旅館房間平常不開燈,有客人才點亮

物件數量太多不可能全常駐,平常讓它休眠省資源,收到請求才喚醒、配給執行緒,這就是啟動;反之則是停用。

本節字彙

遠端物件參照 (remote object reference)
用來指向某個分散式物件的全域唯一識別,可以當參數傳遞。
🧠 remote=遠端,reference=參照,就是『遠端物件的名片』。
介面繼承 (interface inheritance)
新介面繼承舊介面的方法簽章並可加入新方法的關係,分散式物件偏好它而非實作繼承。
🧠 只繼承『介面長相』,不繼承內部做法。
持久化 (persistence)
把有狀態物件的狀態保存下來,使其能跨越啟動/停用循環甚至系統故障。
🧠 persist=堅持存在,連關機都『堅持』把狀態留著。
一個伺服器要管理上百萬個分散式物件,但同一時間真正被呼叫的只有少數。中介軟體用哪個機制避免浪費資源?
下列哪一項是『分散式物件』相對於『一般物件』新增的概念,且專門用來應付跨機器的失敗?
為什麼分散式物件中介軟體偏好『介面繼承』而非『實作繼承』?
02

CORBA 的語言中立魔法:IDL

OMG 用 ORB 這個比喻來幫客戶端呼叫遠端物件;CORBA 物件實作 IDL 介面,客戶端不一定是物件。

先讀原文段落,旁邊就是白話

這是一本英文書。左邊放原文、右邊放白話導讀——你既讀得懂,也順手碰了原文。

原文 · CORBA 的語言中立魔法:IDL 4 From objects to components 8. 5 Case studies: Enterprise JavaBeans and Fractal 8. 6 Summary A complete middleware solution must present a higher-level programming abstraction as well as abstracting over the underlying complexities involved in distributed systems. This chapter examines two of the most important programming abstractions, namely distributed objects and components, and also examines associated middleware platforms including CORBA, Enterprise JavaBeans and Fractal.
白話導讀

OMG 用 ORB 這個比喻來幫客戶端呼叫遠端物件;CORBA 物件實作 IDL 介面,客戶端不一定是物件。

ORB 與 CORBA 物件模型

OMG 用 ORB 這個比喻來幫客戶端呼叫遠端物件;CORBA 物件實作 IDL 介面,客戶端不一定是物件。

STEP 1

深度探秘

OMG、ORB 與語言中立的野心

CORBA 想解決什麼

OMG (Object Management Group) 在 1989 年成立,目標是讓不同語言、不同硬體、不同作業系統寫的分散式物件都能互相溝通。為此他們設計了一套與實作語言無關的介面語言

他們提出一個核心比喻:物件請求仲介者 (Object Request Broker, ORB)。ORB 的工作是幫客戶端在遠端物件上呼叫方法,這包含三步:

  1. 定位物件
  2. 必要時啟動物件
  3. 把客戶端的請求轉達給物件,物件執行後回覆

CORBA = Common Object Request Broker Architecture,整個架構就是繞著 ORB 這個仲介者打造的。本書聚焦 CORBA 2 規格。

💡
關鍵

OMG 用語言中立的介面語言與 ORB 仲介者,讓任何語言寫的物件都能互相呼叫方法。

STEP 2

生活妙喻

ORB 像萬能客服總機

客服總機的比喻

想像你打電話給一家大公司的總機(ORB),說:「我要找會計部處理這張發票。」你不需要知道:

  • 會計部在幾樓(定位物件
  • 承辦人現在在不在座位上、要不要先去叫他來(啟動物件
  • 你的需求怎麼被轉接過去(轉達請求

你只管講出需求,總機幫你搞定一切,承辦人處理完再回覆你。

flowchart TD
  A[客戶端] -->|我要呼叫某方法| B[ORB 物件請求仲介者]
  B --> C[定位物件]
  B --> D[必要時啟動物件]
  B --> E[轉達請求給遠端物件]
  E -->|執行並回覆| A

更厲害的是,這台總機聽得懂各國語言——不管承辦人講 C++、Java 還是 Python,總機都能橋接。

💡
關鍵

ORB 像萬能客服總機,幫你定位、喚醒並轉接到正確的承辦人,還跨語言。

STEP 3

實用超能力

CORBA 物件模型的幾個關鍵差異

CORBA 物件模型:和你想的物件不太一樣

CORBA 物件模型和一般 RMI 相似,但有幾個重要差別:

  • 客戶端不一定是物件:客戶端可以是任何送出請求訊息、接收回覆的程式。
  • CORBA 物件指的就是遠端物件:它實作一個 IDL 介面、有遠端物件參照、能回應 IDL 介面中方法的呼叫。
  • 可以用非物件導向語言實作:例如沒有 class 概念的語言也能寫 CORBA 物件。

為什麼 CORBA 沒有 class? 因為不同實作語言對 class 的理解天差地遠,有些語言甚至沒有 class。所以:

結論:CORBA IDL 不能定義 class
  → 因此 class 的實例不能當參數傳遞
  → 但任意複雜的資料結構(如 struct)可以當參數傳遞

實用差別:和單一語言的 Java RMI 比,寫 CORBA 多了三件事要學——CORBA 的物件模型、IDL、以及 IDL 到實作語言的映射。

💡
關鍵

CORBA 物件實作 IDL 介面並有遠端參照,但因為跨語言而捨棄 class,改用 struct 等資料結構傳值。

🔆
生活妙喻:物件請求仲介者 (ORB) ≈ 大公司的萬能客服總機

你只講需求,總機幫你定位部門、必要時把承辦人叫來、再轉接過去,還聽得懂各國語言——就像 ORB 跨語言定位、啟動、轉達請求。

🔆
生活妙喻:CORBA 沒有 class ≈ 國際通用的填空表格 vs. 某國專屬的精裝合約

不同國家(語言)對精裝合約(class)格式各有規定,難以通用;於是改用大家都看得懂的填空表格(struct)來傳遞資料。

本節字彙

ORB (Object Request Broker)
CORBA 中負責定位、必要時啟動並轉達客戶端請求到遠端物件的仲介軟體。
🧠 Broker=仲介,ORB 就是『物件請求的仲介』。
CORBA 物件 (CORBA object)
實作某個 IDL 介面、擁有遠端物件參照、並能回應該介面方法呼叫的遠端物件。
🧠 有介面 + 有參照 + 能被呼叫,三者俱全才算 CORBA 物件。
OMG (Object Management Group)
制定 CORBA(也管 UML 標準化)的組織,目標是推廣可互通的分散式物件系統。
🧠 管理物件的『集團』,CORBA 與 UML 都出自它手。
客戶端想呼叫一個遠端 CORBA 物件,但不知道它在哪台機器、也不知道它現在有沒有被喚醒。ORB 的角色最接近下列哪個描述?
為什麼 CORBA IDL 不能定義 class,也因此不能把 class 的實例當參數傳遞?
下列何者『不是』成為 CORBA 物件的必要條件?

用 IDL 描述介面

IDL 提供 module、interface、型別、屬性與方法簽章;參數用 in/out/inout 標註,並支援例外與介面繼承。

STEP 1

深度探秘

IDL 是一份語言中立的合約

IDL:只說『有哪些方法』,不說『怎麼做』

IDL (Interface Definition Language) 用來指定一個介面的名字與一組客戶端可以呼叫的方法。它的語法是 ANSI C++ 的子集,再加上支援分散式的關鍵字(如 interfaceinoutinoutreadonlyraises)。

IDL 提供的工具有:

  • module:把介面與型別定義分組成邏輯單位,形成命名範圍避免名稱衝突。
  • interface:描述 CORBA 物件提供哪些操作與屬性。
  • 型別:15 種基本型別(如 long、boolean)與建構型別(struct、sequence、array、union、enum 等)。
  • attribute:類似 public 欄位,編譯器會自動產生取值/設值方法(readonly 只產生取值)。

一個方法簽章的通式:

[oneway] <return_type> <method_name>(parameter1, ..., parameterL)
  [raises (except1, ..., exceptN)] [context (...)];
💡
關鍵

IDL 是語言中立的『介面合約』,描述方法、型別與屬性,但完全不談實作。

STEP 2

生活妙喻

in/out/inout 像寄包裹的方向標籤

參數方向:誰寄給誰

IDL 方法的每個參數都要標明方向,這就像在包裹上貼方向標籤:

標籤 意思 比喻
in 值從客戶端傳到伺服器 你寄東西『去』給對方
out 值從伺服器傳回客戶端 對方寄東西『回』給你
inout 兩個方向都可能傳 來回都寄(較少用)

例如:

void getPerson(in string name, out Person p);

你把 name『寄去』,伺服器把找到的 Person『寄回』。

參數傳遞語意也很關鍵:

  • 型別若是某個 IDL 介面的名字 → 傳的是遠端物件參照
  • 基本型別與建構型別 → 以值複製傳遞,到對方那邊產生新的副本。
flowchart LR
  A[客戶端] -->|in 參數| B[伺服器]
  B -->|out 參數與回傳| A
💡
關鍵

in/out/inout 標明參數流向;介面型別傳參照,基本與建構型別以值複製傳遞。

STEP 3

實用超能力

例外、繼承與一段真實 IDL

把它組起來看

一段真實的 IDL(取自白板範例):

struct GraphicalObject {
  string type;
  Rectangle enclosing;
  boolean isFilled;
};

interface Shape {
  long getVersion();
  GraphicalObject getAllState();
};

typedef sequence <Shape, 100> All;

interface ShapeList {
  exception FullException { };
  Shape newShape(in GraphicalObject g) raises (FullException);
  All allShapes();
  long getVersion();
};

重點觀察:

  • 例外newShaperaises (FullException) 宣告它可能丟出使用者自訂例外;CORBA 也會產生系統例外(伺服器太忙、通訊問題等)。客戶端兩種都該處理。
  • 介面繼承:若 interface B: A,B 繼承 A 的方法簽章並可加新項;IDL 允許多重繼承interface Z : B, C),但若 B、C 有同名項則需用 B::Q 這種範圍名稱消歧。
  • 預設呼叫語意是 at-most-once;加 oneway 則變成 maybe 語意(不阻塞、不回傳結果)。
💡
關鍵

IDL 用 raises 宣告例外、用冒號表達介面繼承(可多重),預設 at-most-once,oneway 則不阻塞。

🔆
生活妙喻:in/out/inout 參數 ≈ 包裹上的寄送方向標籤

in 是你寄去給對方、out 是對方寄回給你、inout 是來回都寄;標籤讓中介軟體知道資料該往哪個方向搬。

🔆
生活妙喻:以值傳遞 vs. 以參照傳遞 ≈ 影印一份給對方 vs. 給對方一張置物櫃鑰匙

基本與建構型別像影印副本,對方改了不影響你;介面型別像給鑰匙(遠端參照),雙方指向同一個遠端物件。

本節字彙

IDL (Interface Definition Language)
CORBA 用來定義介面、型別與方法簽章的語言中立語言,語法是 ANSI C++ 的子集加上分散式關鍵字。
🧠 Interface Definition Language=『介面定義語言』,只定義介面不寫實作。
oneway
IDL 關鍵字,使方法呼叫變成不阻塞的 maybe 語意,只能用於不回傳結果的方法。
🧠 one way=單行道,只送出去不等回來。
raises
IDL 方法簽章中宣告該方法可能丟出哪些使用者自訂例外的關鍵字。
🧠 raise=舉起/引發,引發一個例外。
在 IDL 方法 `void getPerson(in string name, out Person p);` 中,`name` 與 `p` 的資料流向分別是什麼?
某 IDL 方法回傳型別是一個 `interface Shape`,另一個參數是 `struct GraphicalObject`。這兩者的傳遞方式分別為何?
開發者想讓某個通知方法『送出後不等待回覆、也不回傳結果』,應在 IDL 中使用什麼?
03

CORBA 的架構與遠端參照

CORBA 架構在 RMI 基礎上多了物件配接器、實作儲存庫與介面儲存庫,並支援靜態與動態呼叫。

先讀原文段落,旁邊就是白話

這是一本英文書。左邊放原文、右邊放白話導讀——你既讀得懂,也順手碰了原文。

原文 · CORBA 的架構與遠端參照 core middleware (see Section 8. Lifecycle management: Lifecycle management is concerned with the creation, migration and deletion of objects, with each step having to deal with the distributed nature of the underlying environment. Activation and deactivation: In non-distributed implementations, it can often be assumed that objects are active all the time while the process that contains them runs. In distributed systems, however, this cannot be assumed as the numbers of objects may be very large, and hence it would be wasteful of resources to have all objects available at any time.
白話導讀

CORBA 架構在 RMI 基礎上多了物件配接器、實作儲存庫與介面儲存庫,並支援靜態與動態呼叫。

ORB core、物件配接器與儲存庫

CORBA 架構在 RMI 基礎上多了物件配接器、實作儲存庫與介面儲存庫,並支援靜態與動態呼叫。

STEP 1

深度探秘

CORBA 架構比基本 RMI 多了三個零件

三個新成員

CORBA 架構建立在 RMI 之上,但多了三個關鍵元件:物件配接器 (object adapter)實作儲存庫 (implementation repository)介面儲存庫 (interface repository)

各零件職責:

  • ORB core:包含通訊模組的全部功能,另外提供啟停 ORB、在遠端參照與字串間轉換、為動態呼叫提供引數清單等操作。
  • 物件配接器:橋接『有 IDL 介面的 CORBA 物件』與『實作它的 servant 類別』。它建立遠端物件參照、把每個 RMI 經由 skeleton 派送給對應的 servant、並負責 servant 的啟動與停用。
  • skeleton / proxy(stub):由 IDL 編譯器產生,skeleton 在伺服器語言、proxy 在客戶端語言,負責封送與解封參數、例外與結果。

CORBA 標準的物件配接器叫 POA (Portable Object Adapter),之所以『可攜』是因為它讓應用與 servant 能跑在不同開發商的 ORB 上。

💡
關鍵

CORBA 在 RMI 基礎上加了物件配接器、實作儲存庫、介面儲存庫;POA 負責把 CORBA 物件接到 servant。

STEP 2

生活妙喻

把伺服器想成一棟智慧辦公大樓

辦公大樓的各個角色

把 CORBA 伺服器想成一棟大樓:

  • ORB core = 大樓的通訊基礎建設(電話線、網路)。
  • 物件配接器 (POA) = 樓層櫃台,知道每個房號(CORBA 物件名)對應到哪位實際員工(servant),並負責把訪客帶到正確的人、員工不在就把他叫來上班(啟動/停用)。
  • 實作儲存庫 = 人資檔案室,記錄『哪個部門的程式檔放在哪、要用時去哪台機器哪個埠把伺服器叫醒』,按需啟動已註冊的伺服器。
  • 介面儲存庫 = 服務型錄查詢台,告訴你某種介面有哪些方法、每個方法要哪些參數型別——這給了 CORBA 反射 (reflection) 的能力。
flowchart TD
  A[客戶端] -->|請求| B[ORB core]
  B --> C[物件配接器 POA]
  C -->|派送| D[Servant 真正執行的物件]
  E[實作儲存庫] -->|按需啟動伺服器| C
  F[介面儲存庫] -->|提供介面資訊 反射| A
💡
關鍵

POA 是樓層櫃台、實作儲存庫是人資檔案室、介面儲存庫是型錄查詢台,三者協作把請求送到正確的 servant。

STEP 3

實用超能力

靜態 vs. 動態呼叫,與 POA 的彈性策略

編譯期就知道 vs. 執行期才知道

CORBA 同時支援兩種呼叫:

  • 靜態呼叫:遠端介面在編譯期就已知,可用客戶端 stub 與伺服器 skeleton。大多數人偏好它,因為程式模型較自然。
  • 動態呼叫 (DII):介面在編譯期未知時使用。例如一個物件瀏覽器要顯示系統裡所有 CORBA 物件,不可能事先包含所有 proxy。此時客戶端可向介面儲存庫查出方法資訊,再臨時組出呼叫送給伺服器。對應地,伺服器側有動態 skeleton 能接受未知介面的呼叫。

POA 的彈性:可設定多種策略,例如

  • 物件參照是持久 (persistent) 還是暫態 (transient)
  • 每次呼叫是否給獨立執行緒;
  • 是否每個 CORBA 物件各有專屬 servant(預設是一個 servant 服務該 POA 的所有物件)。

legacy code(舊有非分散式程式碼)也能變成 CORBA 物件:替它定義一個 IDL 介面、提供合適的物件配接器與 skeleton 即可。

💡
關鍵

介面編譯期已知用靜態呼叫,未知則用動態呼叫;POA 還能設定持久/暫態、執行緒與 servant 對應等策略。

🔆
生活妙喻:物件配接器 (POA) ≈ 樓層櫃台

它握有房號(物件名)對員工(servant)的對照表,把訪客帶到正確的人,員工不在還會把他叫來上班(啟動),訪客離開後讓他休息(停用)。

🔆
生活妙喻:介面儲存庫 (interface repository) ≈ 服務型錄查詢台

你拿到一個沒見過的物件參照,可以到查詢台問『這種介面有哪些方法、要什麼參數』,這就是 CORBA 的反射能力。

本節字彙

物件配接器 (object adapter / POA)
橋接 CORBA 物件與實作它的 servant 的元件,負責建立遠端參照、派送呼叫、啟動與停用 servant。
🧠 adapter=轉接頭,把 IDL 介面『轉接』到實際的 servant。
實作儲存庫 (implementation repository)
負責按需啟動已註冊伺服器、並記錄物件配接器名稱到實作檔路徑與伺服器位址的儲存庫。
🧠 管『實作放在哪、怎麼叫醒』的檔案室。
動態呼叫介面 (DII)
讓客戶端在編譯期不知道介面時,仍能向介面儲存庫查資訊並臨時組出呼叫的機制。
🧠 Dynamic=動態,臨場才決定怎麼呼叫。
一個物件瀏覽器需要顯示系統中所有 CORBA 物件的資訊,但這些物件的介面在它編譯時還不存在,未來也會新增。它最適合採用什麼方式?
物件配接器(POA)在 CORBA 架構中扮演的核心角色是什麼?
介面儲存庫(interface repository)為 CORBA 帶來什麼特別能力?

遠端參照 IOR 與命名服務

IOR 包含型別 ID、傳輸協定位址與物件鍵;暫態與持久 IOR 定位 servant 的方式不同,命名服務則把名字對應到參照。

STEP 1

深度探秘

IOR 是 CORBA 物件的完整門牌

IOR:可互通的物件參照

CORBA 規定了一種遠端物件參照格式,叫可互通物件參照 (Interoperable Object Reference, IOR)。它有三大欄位:

欄位 內容 作用
IDL 介面型別 ID 介面的型別識別 若有介面儲存庫,可用來取回 IDL 定義
協定與位址細節 例如 IIOP 下的主機網域名稱與埠號 找到伺服器在哪
物件鍵 (object key) 物件配接器名稱 + 物件名稱 ORB 用來辨識是哪個 CORBA 物件

IIOP (Internet Inter-ORB Protocol) 使用 TCP,位址就是主機網域名稱加埠號。第二個欄位可重複,以指定多個位址,達成複製與容錯。

💡
關鍵

IOR 是 CORBA 物件的完整門牌,含型別 ID、協定位址與物件鍵三欄。

STEP 2

生活妙喻

暫態 vs. 持久 IOR:臨時攤位 vs. 連鎖總部

兩種門牌,兩種找人方式

IOR 分兩種,定位 servant 的方式不同:

  • 暫態 IOR (transient):只在『裝著該物件的行程』活著時有效,門牌上寫的是伺服器本身的位址

    • 找法:伺服器 ORB core 收到請求 → 用物件配接器名稱找到配接器 → 用物件名稱找到 servant。
    • 比喻:路邊臨時攤位,攤位收了門牌就失效。
  • 持久 IOR (persistent):能跨越物件的多次啟動,門牌上寫的是實作儲存庫的位址

    • 找法:實作儲存庫收到請求 → 取出物件配接器名稱 → 必要時在登記的主機位址啟動 CORBA 物件 → 把實際位址回給客戶端 ORB,之後客戶端直接對該位址送請求。
    • 比喻:連鎖店總部,你先找總部,總部告訴你現在哪家分店在營業。
flowchart TD
  A[客戶端 ORB] -->|暫態 IOR| B[伺服器 ORB core 直接定位 servant]
  A -->|持久 IOR| C[實作儲存庫]
  C -->|必要時啟動並回傳位址| A
💡
關鍵

暫態 IOR 直接指向伺服器、隨行程消失;持久 IOR 指向實作儲存庫、可跨啟動定位。

STEP 3

實用超能力

命名服務:給物件一個好記的名字

別讓人類記 IOR

IOR 對機器很完美,但對人類來說又長又難記。命名服務 (Naming service) 就是來解決這件事:它把人類可讀的名字對應到遠端物件參照,是任何 ORB 幾乎都要加上的基礎服務。

典型用法(Java):伺服器把物件以名字 rebind 到命名服務,客戶端再用同樣的名字 resolve 取回參照。

// 伺服器端:把 ShapeList 物件以名字註冊
NameComponent nc = new NameComponent("ShapeList", "");
NameComponent path[] = { nc };
ncRef.rebind(path, SLRef);

// 客戶端:用名字取回參照
ShapeList shapeListRef =
    ShapeListHelper.narrow(ncRef.resolve(path));

注意 narrowresolve 回傳的是泛用的 Object 型別,要『窄化』成你真正需要的型別(ShapeList)。

對比命名與交易服務:命名服務用名字找物件;交易服務 (Trading service) 則用屬性找物件,像目錄服務——你說『我要一個會做 X、價格低於 Y 的服務』。

💡
關鍵

命名服務把好記的名字對應到遠端參照,用 rebind 註冊、resolve 取回,再用 narrow 窄化型別。

🔆
生活妙喻:暫態 IOR vs. 持久 IOR ≈ 路邊臨時攤位 vs. 連鎖店總部

暫態 IOR 像臨時攤位,攤位收了門牌就失效;持久 IOR 像先找連鎖總部,總部再告訴你目前哪家分店在營業(必要時把物件啟動)。

🔆
生活妙喻:命名服務 (Naming service) ≈ 電話簿

你不必背別人的長串電話號碼(IOR),只要查名字就能找到對應號碼(遠端參照)。

本節字彙

IOR (Interoperable Object Reference)
CORBA 的標準遠端物件參照格式,含 IDL 介面型別 ID、協定位址細節與物件鍵三欄。
🧠 Interoperable=可互通,是跨 ORB 都認得的『物件門牌』。
命名服務 (Naming service)
把人類可讀的名字對應到遠端物件參照的 CORBA 服務,用 rebind 註冊、resolve 取回。
🧠 Naming=命名,幫物件取個好記的名字。
narrow (窄化)
把命名服務 resolve 回傳的泛用 Object 型別轉換成所需的具體型別的操作。
🧠 narrow=變窄,從泛用型別收窄成你要的型別。
一個 CORBA 物件需要在多次啟動之間都能被定位,而非只在某個行程存活期間有效。它應該使用哪種 IOR,且該 IOR 內存的是誰的位址?
IOR 的三大欄位是下列哪一組?
為什麼實務上會用命名服務,而不直接把 IOR 交給人類使用?
04

從物件演進到元件

隱性相依、需懂大量中介軟體細節、關注點纏繞、部署全靠手工,是催生元件式做法的四個需求。

先讀原文段落,旁邊就是白話

這是一本英文書。左邊放原文、右邊放白話導讀——你既讀得懂,也順手碰了原文。

原文 · 從物件演進到元件 ontainer are to provide a managed server-side hosting environment for components and to provide the necessary separation of concerns alluded to above, where components deal with application concerns and the container Figure 8. 12 The structure of a container Lifecycle interface External (provided) interfaces Components Calls to external distributed system services Interception Incoming invocations SECTION 8. 4 FROM OBJECTS TO COMPONENTS 363 deals with distributed systems and middleware issues, ensuring that non-functional properties are achieved. The overall structure of a container is shown in Figure 8.
白話導讀

隱性相依、需懂大量中介軟體細節、關注點纏繞、部署全靠手工,是催生元件式做法的四個需求。

分散式物件的四大痛點

隱性相依、需懂大量中介軟體細節、關注點纏繞、部署全靠手工,是催生元件式做法的四個需求。

STEP 1

深度探秘

分散式物件很好用,但有四個結構性問題

為什麼還要演進到元件

分散式物件(如 CORBA)很成功,但實務上暴露出四個痛點,正是它們催生了元件式做法:

  1. 隱性相依 (implicit dependencies):物件介面只說明它『提供』什麼,沒說明它『依賴』什麼。物件內部可能偷偷呼叫別的物件或命名、安全等服務,但這些從外部介面看不出來。
  2. 與中介軟體的互動太複雜:就算標榜透明,程式設計師仍被迫處理大量低階細節——命名、POA、ORB core 等呼叫,把真正的應用邏輯淹沒。
  3. 缺乏分散式關注點的分離:安全、交易、協調、複製這些非功能性需求,得由開發者親手在物件中插入呼叫,造成關注點纏繞。
  4. 沒有部署支援:物件得手動部署到每台機器、手動啟動、手動建立綁定,大規模部署既累又易錯,且不可攜。
💡
關鍵

分散式物件的四大痛點是:隱性相依、與中介軟體糾纏、無法分離分散式關注點、缺乏部署支援。

STEP 2

生活妙喻

找水電工 vs. 找一個只報價不說工具的師傅

隱性相依:看不見的依賴最可怕

想像你請一位師傅來裝冷氣(他公布的『介面』是:我會裝冷氣)。但他沒告訴你:

  • 他得先借用你家的電鑽(依賴別的工具)
  • 還得打電話叫一個搬運工來幫忙(依賴別的服務)

這些隱性相依讓你很難評估:換另一位師傅行不行?少了搬運工會不會出事?這正是物件介面『只說提供、不說依賴』的問題。

再看關注點纏繞:好比食譜裡,把『怎麼煮這道菜』和『瓦斯怎麼開、抽油煙機怎麼接電、廚房防火怎麼做』全寫在一起——真正的料理步驟反而被淹沒。

flowchart TD
  A[物件對外介面 只說提供什麼] --> B[實際上偷偷依賴]
  B --> C[其他物件]
  B --> D[命名服務]
  B --> E[安全與交易服務]
  A -. 看不見這些依賴 .-> B
💡
關鍵

隱性相依像『只報價、不說會用到哪些工具與幫手』的師傅,讓人難以替換與安全組裝。

STEP 3

實用超能力

每個痛點都對應一個明確需求

痛點 → 需求:元件要補的洞

書中把每個痛點轉成一個明確需求,這正是元件式中介軟體要實現的目標:

痛點 對應需求
隱性相依 不只要描述物件提供的介面,也要描述它對其他物件的依賴
與中介軟體糾纏 乾淨分離『中介軟體框架程式』與『應用程式』,讓開發者只專注後者
關注點未分離 把安全、交易等分散式服務的複雜度盡量對開發者隱藏
無部署支援 中介軟體應內建部署支援,讓分散式軟體像安裝單機軟體一樣容易

回看真實例子:CORBA 的 whiteboard 範例裡,伺服器其實會對客戶端 callback、客戶端與伺服器都會呼叫命名服務——但這些都沒寫在對外介面上(隱性相依);而真正和白板有關的程式碼很少,卻和一堆分散式系統呼叫交織在一起(關注點纏繞)。這就是為什麼需要演進。

💡
關鍵

四個痛點各自對應一個需求:顯式描述依賴、分離中介軟體與應用、隱藏分散式服務複雜度、內建部署支援。

🔆
生活妙喻:隱性相依 (implicit dependencies) ≈ 只報價、不說會借用哪些工具與幫手的師傅

你只看到他公布『我會裝冷氣』,卻不知道他暗中依賴你的電鑽和一個搬運工,導致你很難評估替換或安全組裝。

🔆
生活妙喻:關注點未分離 ≈ 把料理步驟和瓦斯接線、防火工程寫在同一份食譜

安全、交易等分散式關注點和應用邏輯纏在一起,真正的『料理步驟』被技術細節淹沒,程式變得又長又難懂。

本節字彙

隱性相依 (implicit dependencies)
物件介面只描述提供什麼,卻未表明它依賴哪些其他物件或服務,使組裝、替換與第三方開發變困難。
🧠 implicit=隱含的,看不見的依賴最難處理。
非功能性需求 (non-functional concerns)
如安全、交易、協調、複製等與『功能本身』無關但攸關系統品質的需求。
🧠 不是『做什麼功能』,而是『做得安不安全、可不可靠』。
關注點分離 (separation of concerns)
把不同類別的程式邏輯(如應用邏輯與分散式服務呼叫)清楚分開,避免纏繞。
🧠 各管各的,互不打結。
某物件對外介面寫著『提供下單功能』,但實作裡其實還會呼叫命名服務、對客戶端做 callback。第三方開發者因此難以安全替換它。這對應到分散式物件的哪個痛點?
在 CORBA 白板範例中,真正與白板有關的程式碼很少,卻和大量 POA、ORB、命名服務呼叫交織在一起。這暴露了哪個痛點?
下列哪一項『不是』書中列出的分散式物件四大痛點之一?

元件、容器與部署

元件用提供介面與必要介面寫清楚相依;容器扛起非功能性需求;部署描述子讓部署像裝單機軟體一樣簡單。

STEP 1

深度探秘

元件:把依賴也寫進合約

元件的定義

Szyperski 的經典定義:

軟體元件是一個組合單位,具有契約式指定的介面僅有明確的上下文相依

關鍵字是『僅有』——意思是所有上下文相依都必須明確 (explicit),沒有任何隱性相依。元件像分散式物件一樣是封裝的組合單位,但它的契約同時包含:

  • 提供介面 (provided interfaces):它對外提供的服務。
  • 必要介面 (required interfaces):它正常運作所依賴、必須被連接上的其他元件。

在一個元件組態中,每個必要介面都必須綁定到另一個元件的提供介面。這就形成了一份軟體架構:元件 + 介面 + 介面間的連接。

元件擁護者強調組合優於繼承,因為繼承會在類別間製造另一種隱性相依(如脆弱基礎類別問題)。

💡
關鍵

元件同時宣告提供介面與必要介面,把所有依賴寫成明確契約,杜絕隱性相依。

STEP 2

生活妙喻

元件像有公母插頭的電器,容器像保母

提供/必要介面像插頭與插座

把元件想成一台電器:

  • 提供介面 = 它對外能輸出的服務,好比它身上的插座,別人可以插進來用。
  • 必要介面 = 它自己要運作所需的依賴,好比它的插頭,必須插到別人的插座才能通電。

組裝系統就像把一堆電器的插頭和插座一一接好——軟體開發因此從『開發』走向『組裝 (assembly)』,可以用現成元件拼出更複雜的服務。

容器 (container) 則像一個盡責的保母/管家:它把元件包在裡面,不讓外界直接碰元件,而是攔截 (interception) 所有進來的呼叫,先替元件處理好安全、交易、生命週期等雜事,再放行給元件。

flowchart TD
  A[進來的呼叫] --> B[容器 攔截]
  B --> C[呼叫安全與交易服務]
  B --> D[管理 ORB 與生命週期]
  B --> E[元件 只負責應用邏輯]
💡
關鍵

提供/必要介面像插座與插頭,靠組裝拼系統;容器像保母,靠攔截替元件扛下分散式雜事。

STEP 3

實用超能力

容器、應用伺服器與部署描述子

容器補齊了另外三個需求

上一節元件定義解決了『隱性相依』,但簡化開發、隱藏服務複雜度、支援部署這三項,是靠容器補上的。容器支援常見的三層模式:

  • 前端(常為 web)客戶端
  • 容器,內含實作應用/商業邏輯的元件
  • 系統服務,管理持久儲存中的資料

支援容器模式與關注點分離的中介軟體就叫應用伺服器 (application server),例如 WebSphere、EJB、Spring、JBoss、GlassFish。它的好處是把分散式複雜度藏起來,例如 POA 相關呼叫由容器代勞、交易與安全靠攔截自動處理。

部署支援部署描述子 (deployment descriptor),通常用 XML 寫,描述:

<!-- 概念示意:部署描述子說明如何部署元件組態 -->
<deployment>
  <component name="OrderService" required="InventoryService"/>
  <transaction policy="container-managed"/>
  <security level="required"/>
</deployment>

元件被部署進容器,容器解讀部署描述子來設定底層中介軟體與分散式服務的政策;工具則據此在實體架構上正確部署。

💡
關鍵

容器用攔截扛下非功能性需求形成應用伺服器;部署描述子(常為 XML)讓部署像裝單機軟體一樣自動化。

🔆
生活妙喻:提供介面與必要介面 ≈ 電器的插座與插頭

提供介面像插座讓別人插進來用,必要介面像插頭必須接到別人的插座才能通電;組裝系統就是把插頭插座一一接好。

🔆
生活妙喻:容器 (container) ≈ 盡責的保母/管家

外界的呼叫不直接碰元件,而是先被容器攔截,由它替元件打理好安全、交易、生命週期等雜事,元件只管做自己的應用邏輯。

本節字彙

提供介面 / 必要介面 (provided / required interfaces)
元件對外提供的服務介面,以及元件正常運作所依賴、必須被連接的其他元件介面。
🧠 提供=我給你的(插座),必要=我需要的(插頭)。
容器 (container)
在伺服器端託管元件、透過攔截替元件處理安全、交易、生命週期等非功能性需求的環境。
🧠 把元件『裝在裡面』並代為打理雜事的容器。
部署描述子 (deployment descriptor)
通常以 XML 撰寫、描述元件組態如何在分散式環境中部署與配置的檔案。
🧠 descriptor=描述書,描述『怎麼部署』。
依 Szyperski 的定義,元件與一般分散式物件最關鍵的差別是什麼?
把元件比喻成電器時,『必要介面』對應到什麼,又代表什麼意義?
容器主要透過什麼機制,在不更動元件應用邏輯的前提下,替它加上安全、交易等非功能性處理?
05

元件案例:EJB 與 Fractal

EJB 用 POJO 加註解開發 bean,容器負責交易、安全與生命週期,並支援相依注入與攔截。

先讀原文段落,旁邊就是白話

這是一本英文書。左邊放原文、右邊放白話導讀——你既讀得懂,也順手碰了原文。

原文 · 元件案例:EJB 與 Fractal Enterprise JavaBeans specification as an example of an application server. 13 Application servers Technology Developed by Further details WebSphere Application Server IBM [www. com] Enterprise JavaBeans SUN [java. com XII] Spring Framework SpringSource (a division of VMware) [www.
白話導讀

EJB 用 POJO 加註解開發 bean,容器負責交易、安全與生命週期,並支援相依注入與攔截。

Enterprise JavaBeans:受管的三層式元件

EJB 用 POJO 加註解開發 bean,容器負責交易、安全與生命週期,並支援相依注入與攔截。

STEP 1

深度探秘

EJB 是伺服器端、受管的元件架構

EJB 是什麼

Enterprise JavaBeans (EJB) 是 Java EE 的核心,是一種伺服器端、受管 (managed) 的元件架構。元件在 EJB 中叫 bean,負責承載應用(商業)邏輯,並把這層邏輯和後端資料庫的持久儲存分開——直接支援三層式架構

『受管』指的是用上一節的容器模式:容器透過攔截,自動替 bean 注入交易、安全、生命週期等服務的呼叫(container-managed);開發者也可選擇自己掌控(bean-managed)。

EJB 3.0 支援兩種主要 bean:

  • Session bean(會談 bean):實作某項任務,例如在 eShop 下單。可以是
    • stateful:維持與單一客戶端的對話狀態(如購物進度);
    • stateless:不維持狀態,能同時和多個客戶端對話。
  • Message-driven bean(訊息驅動 bean):支援間接通訊,透過 JMS 的訊息佇列或主題以事件驅動方式互動。
💡
關鍵

EJB 是伺服器端受管元件架構,bean 承載商業邏輯,容器代管交易、安全與生命週期,直接支援三層式架構。

STEP 2

生活妙喻

POJO 加註解,像給普通員工別上識別證

POJO + 註解:簡單到不可思議

EJB 3.0 大幅簡化了開發:一個 bean 其實就是一個 POJO (Plain Old Java Object)——純粹用 Java 寫的應用邏輯,裡面沒有任何與『它是 bean』有關的程式碼。然後用註解 (annotations) 來告訴框架該怎麼對待它。

比喻:POJO 像一位普通員工,本身就會做事;註解就像別在他身上的識別證與職務標籤——『@Stateful:我是有狀態會談』『@Remote:我這個窗口對外開放』。識別證不改變他會做的事,只是讓大樓系統(容器)知道該給他什麼待遇。

@Stateful public class eShop implements Orders { ... }
@Stateless public class CalculatorBean implements Calculator { ... }
@MessageDriven public class SharePrice implements MessageListener { ... }

@Remote public interface Orders { ... }   // 對外遠端介面
@Local public interface Calculator { ... } // 僅本地、較高效

business interface 等於上一節的『提供介面』;@Remote 需透過 RMI/JMS 等通訊中介軟體,@Local 則是更直接、更高效的綁定。

💡
關鍵

bean 是純 Java 的 POJO,加上註解就像別上識別證,讓容器知道該給它什麼樣的管理待遇。

STEP 3

實用超能力

交易、相依注入與攔截器,全靠註解

用註解駕馭容器

交易管理:先宣告由 bean 還是容器管理:

  • @TransactionManagement(BEAN):開發者自己用 UserTransaction.begin()commit() 框出交易範圍。
  • @TransactionManagement(CONTAINER)預設):容器決定何時開始/結束,搭配方法上的劃界政策。

常見交易屬性(劃界政策):

屬性 政策
REQUIRED 有現存交易就加入,否則開新交易
REQUIRES_NEW 一律開新交易
MANDATORY 必須由現存客戶端交易呼叫,否則丟例外
NEVER 絕不能在交易中被呼叫,否則丟例外

相依注入 (dependency injection):用 @Resource 等註解標出依賴,容器在執行期(常用反射)把對的物件填進去——這正是元件『必要介面』在 EJB 的實現。

攔截 (interception):用 @AroundInvoke 在不改商業邏輯下插入橫切行為(如記錄、稽核);用 @PostConstruct@PreDestroy(stateful 還有 @PostActivate@PrePassivate)回應生命週期事件。

@Stateful public class eShop implements Orders {
  @Resource javax.transaction.UserTransaction ut; // 相依注入

  @TransactionAttribute(REQUIRED)
  public void MakeOrder(...) { ... }

  @AroundInvoke
  public Object log(InvocationContext ctx) throws Exception {
    System.out.println("called: " + ctx.getMethod().getName());
    return ctx.proceed();
  }
}
💡
關鍵

EJB 用註解統一駕馭交易劃界、相依注入與攔截,讓開發者專注商業邏輯、把分散式管理交給容器。

🔆
生活妙喻:POJO + 註解 ≈ 普通員工別上識別證與職務標籤

POJO 本身就會做事(應用邏輯),註解像識別證,不改變他做的事,只讓大樓系統(容器)知道該給他什麼待遇與管理。

🔆
生活妙喻:相依注入 (dependency injection) ≈ 你列出所需食材清單,廚房幫你備齊送來

元件用註解列出依賴,容器這個第三方負責在執行期把對的物件『送進來』填好,你不必自己去找與建立。

本節字彙

bean
EJB 中的元件,承載應用(商業)邏輯,部署到容器中由容器代管非功能性需求。
🧠 EJB 的元件就叫 bean,一顆顆組成系統。
POJO (Plain Old Java Object)
純粹用 Java 寫、不含框架特定程式碼的普通物件;EJB 3.0 的 bean 就是 POJO 加註解。
🧠 Plain Old=樸素老派,普通到不能再普通的 Java 物件。
相依注入 (dependency injection)
由第三方(容器)負責解析並在執行期把元件所需的依賴填入的模式,常以註解與反射實現。
🧠 依賴由外部『注入』進來,你不用自己找。
在 eShop 中,購物車需要記住單一客戶整個結帳過程的進度;另一個計算服務則只需快速處理大量無關客戶的請求。這兩者分別適合哪種 session bean?
EJB 3.0 中『一個 bean 就是 POJO 加上註解』這句話的意涵是什麼?
某方法標註 `@TransactionAttribute(REQUIRED)`。當呼叫端『已經』有一個進行中的交易時,會發生什麼?

Fractal:輕量可重組的元件模型

Fractal 顯式表示軟體架構,提供 server 與 client 介面,刻意極簡、語言中立,常用來建構其他中介軟體。

STEP 1

深度探秘

刻意極簡的元件模型

Fractal 走的是另一條路

EJB 是重量級、處方式 (prescriptive) 的應用伺服器,強大但龐大,只適合三層式、高階伺服器的場景。Fractal 則是輕量級元件模型,刻意極簡:沒有完整容器模式、不內建部署,也沒有應用伺服器那種豐富程式模型。

Fractal 的特點:

  • 顯式表示軟體架構:避免隱性相依問題(呼應上一章的元件精神)。
  • 語言中立:定義的是程式模型,有 Java(Julia、AOKell)、C(Cecilia、Think)、.NET、Smalltalk、Python 等多種實作。
  • 常被用來建構其他中介軟體,例如可設定的 OS 核心 Think、間接通訊平台 DREAM、Grid 平台 Proactive 等。

元件提供兩種介面:

  • server 介面:接收進來的呼叫(等於『提供介面』)。
  • client 介面:發出向外的呼叫(等於『必要介面』)。
💡
關鍵

Fractal 是輕量、語言中立、顯式描述架構的元件模型,刻意極簡,常用來打造其他中介軟體。

STEP 2

生活妙喻

膜與控制器,像細胞與它的細胞膜

細胞的比喻

Fractal 元件在實作上由兩部分組成,恰好像一個細胞

  • 內容 (content) = 細胞質:構成這個元件的子元件與它們之間的綁定階層式組合,子元件本身還能再是複合元件)。
  • 膜 (控制器構成的控制部分,定義元件的生命週期、反射、攔截等控制能力。">membrane) = 細胞膜:定義這個元件的控制能力,由一組控制器 (controllers) 組成。膜決定外界如何與內容互動,介面可分『膜內可見』與『對外可見』。

換掉膜上的控制器,就改變了元件的能力——這正是 Fractal『可重組』的關鍵。控制器的用途包括:

  • 生命週期管理:如 LifeCycleController 的 startFc/stopFc/getFcState,可在執行期暫停、替換、再恢復。
  • 反射/自省:透過 Component 與 ContentController 介面動態探查元件有哪些介面、複合結構長怎樣。
  • 攔截:和 EJB 一樣可透明地記錄呼叫或實施存取控制。
flowchart TD
  A[膜 控制器集合] --> B[生命週期管理]
  A --> C[反射與自省]
  A --> D[攔截]
  A --> E[內容 子元件與綁定]
💡
關鍵

Fractal 元件像細胞:膜由控制器組成、掌管生命週期反射與攔截,內容是階層式的子元件與綁定。

STEP 3

實用超能力

綁定、ADL 與執行期重組

用綁定與 ADL 組裝,還能熱抽換

綁定 (bindings) 讓元件能組合,有兩種:

  • primitive binding:同一位址空間內,一個 client 介面直接對映一個 server 介面(型別相容時),可用直接物件參照高效實作。
  • composite binding:任意複雜的架構,實作跨機器多介面的通訊。例如要在 Fractal 裡實作一條 CORBA 連線,這個綁定本身會由 proxy、ORB core、物件配接器、skeleton、servant 等元件組成。複合綁定本身也是元件,所以系統完全可設定、也可在執行期重組。

Fractal ADL(架構描述語言,基於 XML)用來描述組合:

<definition name="cs.ClientServer">
  <interface name="r" role="server" signature="java.lang.Runnable" />
  <component name="caller" definition="hw.CallerImpl" />
  <component name="callee" definition="hw.CalleeImpl" />
  <binding client="this.r" server="caller.r" />
  <binding client="caller.s" server="callee.s" />
</definition>

膜 vs. 容器:膜和容器都是元件的部署處、都支援隱式分散式管理(容器靠呼叫服務、膜靠控制器)。但膜更有彈性:反射可從黑箱到完整自省、非功能性支援可從『只做封裝』到『像應用伺服器般的交易與安全』,且全程可設定、可重組。正因如此,Fractal 被稱為開放元件模型 (open component model)

熱抽換的實用情境:把 client-server 配置裡的舊伺服器換成支援多執行緒的新版——可先 suspend、替換 callee、再 resume,避免不一致。

💡
關鍵

Fractal 用 primitive/composite 綁定與 XML 的 ADL 組裝系統,膜比容器更有彈性,可在執行期安全熱抽換元件。

🔆
生活妙喻:膜與內容 (membrane and content) ≈ 細胞膜與細胞質

膜(控制器集合)像細胞膜,掌管元件對外的控制能力;內容像細胞質,是構成元件的子元件與綁定。換掉膜上的控制器就改變了能力。

🔆
生活妙喻:執行期重組(熱抽換元件) ≈ 演唱會中途換掉故障音響卻不中斷表演

先暫停受影響的部分、換上更強的元件、再恢復,就像舞台技術人員在表演進行中安全地替換設備,避免不一致。

本節字彙

膜 (membrane)
Fractal 元件中由一組控制器構成的控制部分,定義元件的生命週期、反射、攔截等控制能力。
🧠 membrane=膜,像細胞膜決定『外界怎麼跟內容互動』。
控制器 (controller)
位於膜中、提供特定控制能力(如生命週期管理、自省、攔截)的元件;換控制器即換能力。
🧠 controller=控制器,掌控元件的某項能力。
綁定 (binding)
Fractal 中連接介面以實現組合的機制,分為同位址空間直接對映的 primitive 與跨機器複雜架構的 composite。
🧠 binding=綁定,把 client 介面綁到 server 介面。
一個團隊需要在資源受限、且常需在執行期調整通訊結構的環境中建構中介軟體,不想要 EJB 那種龐大、處方式的負擔。下列哪個模型較符合需求?
在 Fractal 中,元件的 server 介面與 client 介面分別對應到上一章元件術語的什麼?
用細胞比喻 Fractal 元件時,『膜 (membrane)』掌管的是什麼?