de_DEen_USes_ESfa_IRfr_FRhi_INid_IDjapl_PLpt_PTru_RUvizh_CNzh_TW

C4 模型第 3 級深入探討:掌握組件圖以揭示內部結構與職責

什麼是 C4 組件圖?

組件圖是第 3 級西蒙·布朗的 C4 模型中。它會深入探討一個特定的容器(來自第 2 級容器圖)以顯示:

The Ultimate Guide to C4 Model Visualization with Visual Paradigm's AI  Tools - ArchiMetric

  • 該容器所包含的邏輯構建模塊(組件),這些組件構成了該容器。

  • 這些組件之間如何互動彼此互動。

  • 職責以及實現技術(比類別層級更高——例如 Spring Bean、模組、服務、控制器、外觀等)。

  • 關鍵介面合約組件之間的(通常透過關係隱含)。

重要澄清:C4 中的「組件」並非並非一個類別。它是一個類別的邏輯分組位於明確定義的介面後方——具有明確職責,可以在容器內一定程度上獨立開發、測試與部署,但並非像容器一樣可獨立部署。

組件範例:

  • REST 控制器 / 網頁控制器

  • 服務 / 使用案例 / 應用服務

  • 儲存庫 / 資料存取物件

  • 領域模型 / 實體

  • 安全性 / 驗證模組

  • 通知發送器

  • 外部系統的外觀介面

  • 商業規則引擎

  • 快取層

該圖表仍然邏輯上 / 實作無關的程度足夠—— 不包含類別屬性、方法簽章或完整的 UML 類別細節(那是第 4 級程式碼,可選且罕見)。

何時建立組件圖

建立(並維護)組件圖僅在:

  • 所選的容器是複雜到足夠僅憑其名稱和描述無法明顯看出其內部結構。

  • 新成員(特別是後端開發人員)經常會問:「功能 X 在這個服務/API 內到底是如何實際實作的?」

  • 你正在重構拆分,或提取容器內的邏輯,並需要釐清邊界/責任。

  • 你正在進行詳細的設計討論程式碼審查,或值班交接針對特定容器。

  • 您希望記錄關鍵架構決策在容器內部(例如:六邊形架構、垂直切片、CQRS 分離、安全強制點)。

  • 您已識別出技術債上帝類別,或緊密耦合在容器內部,並希望在清理前視覺化現狀。

  • 您正在引進資深開發人員/架構師,他們需要快速理解模組結構。

切勿建立元件圖,用於:

  • 簡單的容器(具有一個控制器 + 一個服務 + 一個資料庫存取層的 CRUD API — 結構明顯)。

  • 大多數微服務(通常規模夠小,容器層級已足夠)。

  • 前端容器(React/Vue 應用程式 — 通常以元件樹或 Storybook 展示更佳)。

  • 當第 2 層(容器)加上良好的程式碼結構/命名已能傳達所有必要資訊時。

Simon Brown 建議:大多數團隊可停在第 1 層 + 第 2 層。僅在以下情況才需進階至第 3 層:複雜 / 高風險 / 核心 / 高變動容器。

為什麼要使用元件圖?(主要優點)

  • 釐清內部責任— 展示關注點分離(例如:控制器 vs 服務 vs 資料存取 vs 外部整合)。

  • 揭露耦合與相依性 — 顯示出上帝組件、循環依賴,或對基礎設施代碼的過度依賴。

  • 支援更佳的入職訓練與交接 — 開發人員比閱讀所有原始碼檔案更快理解模組邊界。

  • 引導重構與演進 — 在拆分單體架構或引入模式(埠與適配器、垂直切片)前後,提供視覺化的基線。

  • 支援架構審查與威脅建模 — 精確指出驗證、授權、記錄等操作發生的位置。

  • 架構即程式碼 — 當儲存在 PlantUML 中時 → 可與程式碼庫一同版本化,可比對差異,並在 PR 中審查。

  • 擴展溝通效率 — 資深開發者關心組件的責任;資淺開發者則關心新程式碼該放在哪裡。

如何建立出色的組件圖(逐步指南 + 最佳實務)

  1. 選擇 ONE 個容器 — 從最複雜或對業務最關鍵的容器開始(通常是主要的 API / 後端服務)。

  2. 從第 2 層複製上下文 — 包含與此容器互動的外部參與者(其他容器、人員、外部系統)。

  3. 繪製容器邊界 — 使用 Container_Boundary 在 PlantUML 中使用,以明確界定「此容器內部」。

  4. 識別組件 — 問題:

    • 內部的主要模組 / Spring Bean / 套件 / 界限上下文是什麼?

    • 外部請求落在哪裡?(控制器/處理器)

    • 商業邏輯是在哪裡協調的?

    • 資料是在哪裡被存取 / 快取 / 驗證的?

    • 橫切關注點是在哪裡處理的?(安全性、記錄)

    • 是否有對舊系統/外部系統的外觀層或反腐蝕層?

  5. 新增技術與簡要說明 — 名稱、技術(Spring 服務、.NET 處理器、Go 模組等),簡短目的(少於 15 字)。

  6. 定義互動 — 顯示方向與意圖(使用、呼叫、讀取、發佈事件至)。協定在此層級通常省略。

  7. 最佳實務

    • 限制範圍 — 每張圖最多 6–12 個組件。若超過 → 創建專注的次級視圖(例如「驗證切片」)。

    • 有意義地命名 — 優先使用「訂單放置服務」而非「OrderService」。

    • 顯示責任,而非類別 — 避免列出每個類別;應邏輯分組。

    • 謹慎使用圖示 — 僅在能釐清技術時使用(例如 Spring、.NET 圖示)。

    • 啟用圖例 — 幫助新讀者理解。

    • 保持佈局整潔 — LAYOUT_WITH_LEGEND()LAYOUT_TOP_DOWN().

    • 版本存放於程式碼庫中 — .puml 檔案與容器程式碼並列存放。

    • 迭代 — 在重構衝刺期間或每季架構健康檢查時更新。

PlantUML 範例 – 網路銀行系統 API 應用程式(經典大型銀行 plc 風格)

以下是一個使用官方 C4-PlantUML 庫的生產級範例——最常被引用的實際應用範例。

@startuml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml

title 組件圖:網路銀行系統 - API 應用程式

' 行動者 / 容器層級的外部元件
Container(spa, "單頁應用程式", "JavaScript & Angular", "透過瀏覽器提供網路銀行使用者介面")
Container(mobile, "行動應用程式", "iOS/Android", "提供有限的行動銀行功能")
ContainerDb(database, "銀行資料庫", "PostgreSQL", "儲存使用者偏好、快取資料與登入會話")
System_Ext(mainframe, "核心銀行系統", "主機 – 核心帳戶與交易")

' 我們要放大檢視的容器
Container_Boundary(api, "API 應用程式") {
    Component(signInCtrl, "登入控制器", "Spring MVC REST 控制器", "處理驗證與登入會話建立")
    Component(accountsCtrl, "帳戶摘要控制器", "Spring MVC REST 控制器", "提供帳戶餘額與摘要資訊")
    Component(resetPwdCtrl, "重設密碼控制器", "Spring MVC REST 控制器", "管理密碼重設流程")
    
    Component(security, "安全元件", "Spring Bean", "JWT 憑證、密碼雜湊、角色檢查")
    Component(accountService, "帳戶管理元件", "Spring Bean / 服務", "協調帳戶查詢與業務規則")
    Component(mainframeFacade, "主機銀行外觀元件", "Spring Bean", "與舊有主機系統之間的反腐蝕層")
    Component(emailNotifier, "電子郵件通知元件", "Spring Bean", "發送確認與重設密碼郵件")
}

' 边界內的關係
Rel(signInCtrl, security, "使用")
Rel(accountsCtrl, accountService, "使用")
Rel(resetPwdCtrl, security, "使用")
Rel(resetPwdCtrl, emailNotifier, "使用")
Rel(accountService, mainframeFacade, "使用")
Rel(accountService, database, "讀取與寫入", "JDBC")
Rel(mainframeFacade, mainframe, "使用", "XML/HTTPS")
Rel(emailNotifier, database, "讀取使用者偏好", "JDBC")

' 前端傳入的呼叫
Rel(spa, signInCtrl, "使用", "JSON/HTTPS")
Rel(spa, accountsCtrl, "使用", "JSON/HTTPS")
Rel(spa, resetPwdCtrl, "使用", "JSON/HTTPS")
Rel(mobile, signInCtrl, "使用", "JSON/HTTPS")
Rel(mobile, accountsCtrl, "使用", "JSON/HTTPS")
Rel(mobile, resetPwdCtrl, "使用", "JSON/HTTPS")

LAYOUT_WITH_LEGEND()
LAYOUT_LEFT_RIGHT()

@enduml

這會產生以下結果:

  • API 容器周圍有清晰的邊界

  • 控制器、服務與外觀元件的邏輯分組

  • 明確的責任

  • 關鍵互動與依賴

  • 自動圖例以提升可讀性

貼入 PlantUML 渲染器(線上或 IDE)——為您的系統自訂名稱/技術

以此模式作為您的起始範本。目標始終是 有效的團隊溝通 —— 而非圖表美觀。祝您建模愉快!

C4 组件圖資源