Contracts#
在軟體架構中,有一個跨越所有面向的常數因素:contracts(契約)。Contract 廣義定義為架構中不同部分之間的連接方式。
Hard parts contract 的定義:架構中各部分用來傳遞資訊或依賴關係的格式。
這個定義涵蓋了所有用來「連接」系統各部分的技術,包括框架和函式庫的 transitive dependency、內部和外部整合點、cache,以及各部分之間的任何通訊。

Figure 13.1: Three-dimensional intersecting space for messaging forces in distributed architectures
Strict Versus Loose Contracts#
契約不是二元選擇,而是一個從嚴格到鬆散的光譜:

Figure 13.2: The spectrum of contract types, from strict to loose
- Strict 端:XML Schema、JSON Schema、Object、RPC(含 gRPC)
- 中間:GraphQL、REST
- Loose 端:Value-driven contracts、Simple JSON、KVP arrays(maps)
Strict contract 要求嚴格遵守名稱、型別、順序等所有細節。最嚴格的例子是 Java 的 RMI——遠端呼叫模仿內部方法呼叫,匹配名稱、參數、型別等。gRPC 也是預設為 strict contract 的流行框架。
- Strict contract 模仿內部方法呼叫的語意
- 但 strict contract 會在整合架構中產生脆弱性——頻繁變動的契約會連帶影響其他服務
Loose contract(如 name-value pairs)只包含最基本的資訊,沒有額外的 metadata 或型別資訊。
- 鬆散契約允許極度解耦的系統
- 但缺乏契約確定性、驗證能力,需要更多應用程式邏輯
GraphQL 的用途:提供唯讀的聚合資料,不同消費者可取得同一資源的不同 view。例如 Customer Wishlist 只需要 name,而 Customer Profile 需要完整地址資訊。
契約應保持在「need to know」的層級——在語意耦合和必要資訊之間取得平衡,避免無謂的脆弱性。
Trade-Offs Between Strict and Loose Contracts#
Strict contracts 的優缺點:
| 優勢 | 劣勢 |
|---|---|
| Guaranteed contract fidelity:schema 驗證確保精確遵守 | Tight coupling:契約變更時雙方都必須改動 |
| Versioned:支援版本策略管理演進 | Versioned(也是劣勢):版本過多可能成為整合噩夢 |
| Easier to verify at build time:可在建置時進行型別檢查 | |
| Better documentation:明確的參數和型別消除歧義 |
Loose contracts 的優缺點:
| 優勢 | 劣勢 |
|---|---|
| Highly decoupled:最低程度的耦合,最高靈活性 | Contract management:可能出現拼寫錯誤、遺漏等問題 |
| Easier to evolve:實作可更自由地演進 | Requires fitness functions:需要 consumer-driven contract 等機制來確保契約正確性 |
Contracts in Microservices#
架構師必須不斷決定服務如何互動:傳遞什麼資訊(語意)、如何傳遞(實作)、以及耦合的緊密程度。
Coupling Levels#
兩種方式讓需要共享資訊的微服務(如 Customer Address)互動:

Figure 13.3: Two services that must share domain information about the customer
- Strict approach:使用同一技術堆疊的 RPC 協議(如 RMI、gRPC),契約可信度高但耦合緊密
- Loose approach:每個服務有自己的 Customer 內部表示,使用 name-value pairs 傳遞資訊
Loose coupling 的好處:
- 各服務在 bounded context 後高度解耦,可獨立演進內部表示
- 即使團隊換技術平台也不影響另一方
- Name-value pairs 是所有平台都能處理的 lingua franca

Figure 13.4: Microservices with their own internal semantic representation can pass minimal info
Consumer-Driven Contracts#
解決 loose coupling 和 contract fidelity 看似矛盾的需求。
- 傳統模式是 push model:provider 決定發出什麼資訊
- Consumer-driven contract 是 pull model:consumer 定義自己需要什麼,將契約交給 provider
- Provider 將契約測試納入 CI/CD pipeline,確保契約始終滿足
- 多個 consumer 各自定義不同契約,provider 必須全部滿足

Figure 13.5: Consumer-driven contracts allow the provider and consumers to stay in sync
Consumer-driven contracts 的取捨:
| 優勢 | 劣勢 |
|---|---|
| 服務間最低耦合的契約 | 需要工程成熟度和紀律 |
| 允許嚴格度的可變性 | 需要兩種互鎖機制而非一種 |
| 可演進(Evolvable) |
Stamp Coupling#
Stamp coupling 是在服務間傳遞大型資料結構,但每個服務只使用其中一小部分的模式。常見於產業標準文件格式(如旅遊業的 XML itinerary)。
- 可能是有意的模式,也可能是無意的反模式

Figure 13.6: Stamp coupling between four services
Over-Coupling via Stamp Coupling#
以 Wishlist Service 和 Profile Service 為例:
- Wishlist 只需要
name(透過 unique ID 存取),但契約卻包含 Profile 的所有欄位 - 若 Profile 變更了 Wishlist 不關心的欄位(如
state),仍然會破壞契約 - 這是過度耦合的反模式——為了「以防萬一」而過度指定契約中的細節

Figure 13.7: The Wishlist Service is stamp coupled to the Profile Service
Bandwidth#
另一個常見問題與分散式計算的經典謬誤有關:bandwidth is infinite。
- 在單體系統中方法呼叫的大小無關緊要,但在分散式架構中會產生實際問題
- 範例:若每個 payload 500 KB,2,000 requests/sec 就產生 1,000,000 KB/sec 的頻寬需求
- 若只傳遞必要資訊(如
name200 bytes),開銷降至合理的 400 KB/sec
Stamp Coupling for Workflow Management#
Stamp coupling 也有正面用途——用於工作流程管理。
- 架構師在契約中加入工作流程資訊(如狀態、交易狀態等)
- 每個服務更新契約中屬於自己的部分,再傳給下一個服務
- 消費者可查看契約來判斷工作流程狀態,無需查詢每個服務
- 若系統需要交易一致性,服務可將契約重新廣播給先前造訪的服務以恢復一致性

Figure 13.8: Using stamp coupling for workflow management
Stamp coupling 用於工作流程管理的取捨:
| 優勢 | 劣勢 |
|---|---|
| 允許 choreography 中的複雜工作流程 | 在協作者間產生(可能是人為的)高耦合 |
| 高規模時可能產生頻寬問題 |
Sysops Squad Saga: Managing Ticketing Contracts#
團隊討論 ticket 管理工作流程中的契約類型:

Figure 13.9: Types of contracts between collaborators in the ticket management workflow
- Orchestrator ↔ Ticket Management / Ticket Assignment:使用 tight contract,因為資訊高度語意耦合,變更頻率一致
- Orchestrator ↔ Notification Service / Survey Service:使用 loose contract,因為這些服務的資訊變更較慢,不需要緊密耦合
- Orchestrator ↔ Mobile Application(Sysops Expert):使用 loose contract(name-value pairs),因為行動應用需透過 app store 部署,更新審核時間長,鬆散契約提供靈活性
ADR: Loose Contract for Sysops Squad Expert Mobile Application
Context:Sysops Squad 專家使用的行動應用必須透過公共 app store 部署,契約更新受限。
Decision:使用 loose 的 name-value pair 契約在 orchestrator 和行動應用之間傳遞資訊,並建立擴展機制以允許短期彈性。
Consequences:若 app store 政策允許更快(或持續)部署,應重新審視此決策。Orchestrator 和行動應用需包含更多契約驗證邏輯。