**鬆散耦合(loose coupling)**是企業架構與整合領域最紅的流行語之一——紅到 Doug Kaye 直接以它為名寫了一整本書 [Kaye]。它的好處早就為人所知,只是隨著 Web services 架構竄紅,才又被推上舞台中央。

鬆散耦合的核心原則是:降低雙方(元件、應用程式、服務、程式、使用者)在交換資訊時對彼此所做的假設。

雙方對彼此與共同協定的假設愈多,溝通就愈有效率——但方案對中斷與變動的容忍度也愈低,因為雙方被緊緊綁在一起。

緊密耦合的極致:本地方法呼叫#

應用程式內部的本地方法呼叫,建立在大量假設之上:

  • 兩個方法必須跑在同一個行程(例如同一個虛擬機)
  • 必須用同一種語言(至少要有共通的中介語言或位元碼)
  • 呼叫端必須傳入數量完全正確、型別完全正確的參數
  • 呼叫是立即的——被呼叫的方法在呼叫發生後馬上開始處理
  • 呼叫是同步的——呼叫端要等被呼叫方法完成才繼續,且自動從呼叫的下一行接續
  • 溝通即時且瞬間完成,因此雙方都不必擔心第三方竊聽的安全問題

正因為有這麼多假設,我們才能輕鬆地把功能拆成一個個小方法互相呼叫——大量的小方法帶來彈性與重用。

把遠端偽裝成本地:RPC 的誘惑#

許多整合途徑試圖把遠端資料交換包裝成本地方法呼叫的語意,於是有了 RPC(Remote Procedure Call)與 RMI(Remote Method Invocation)——CORBA(見 [Zahavi])、Microsoft DCOM、.NET Remoting、Java RMI,以及較晚近的 RPC 風格 Web services,都支援這種作法。

這個策略原本有兩個好處:

  1. 同步方法呼叫的語意,應用開發者早已熟悉——何不建立在已知的東西上?
  2. 本地與遠端用同一套語法語意,就能把「哪些元件跑在本地、哪些跑在遠端」的決策延後到部署時,開發者少操一份心。

為什麼行不通#

麻煩在於:遠端通訊讓本地方法呼叫所依賴的假設幾乎全部失效。 把遠端通訊抽象成單純的方法呼叫語意,因此既令人困惑又具誤導性。

Waldo 等人早在 1994 年就提醒過我們:「分散式系統中互動的物件,必須以本質上不同於同一位址空間中互動的物件的方式來處理。」[Waldo]

一連串本地呼叫從來不必面對的問題會冒出來:

  • 呼叫遠端服務,難道要把自己限制在「用同一種程式語言寫成」的服務上嗎?
  • 跨網路呼叫往往比本地呼叫慢好幾個數量級——呼叫端真的該一路等到被呼叫端完成嗎?
  • 若網路中斷、被呼叫的方法暫時聯繫不上,該等多久?
  • 怎麼確定我們是在跟預期的對象溝通,而不是第三方冒名者?怎麼防竊聽?
  • 若被呼叫方法的簽章(參數清單)改了怎麼辦?如果那個遠端方法由第三方或商業夥伴維護,我們根本無法控制這種變更。此時該讓呼叫失敗,還是試著在參數之間找出最佳對應、硬著頭皮呼叫下去?

把遠端通訊描繪成本地方法呼叫的變體,是在自找麻煩。這類架構通常產出脆弱、難維護、擴展性差的方案——許多 Web services 的先行者最近才又親身重新發現了這件事。