C4 模型 - 視覺化架構設計

wu發表於2020-12-22

   前言

  世界上最難的兩件事是:

  1. 把我的思想放進你的腦袋

  2. 把你的錢放進我的口袋  

  第二點我們不探討,因為這是眾所周知的,不信?過來試試:)  

  對於第一點,對我們程式設計師來說,其實也是我個人一直強調的,很多事情的成敗,其實就在於掌舵人的思想層面是否認知是一致的,當我們對於一個事物的認知不在同一層面,就好比我們的划槳是不統一的,這是不能發揮最大的生產力。

  你碰到過嗎?

  當我們進入一家新公司的時候,每個人都需要對公司的業務系統進行了解,當你不得不向別人解釋系統是如何工作的,業務模組是如何串聯的,子系統是如何各司其職的,特別是對於非技術人員來說,你會從程式碼開始解釋嗎?

  如果是這樣的話,這將是最低效且會讓人陷入無窮無盡的技術細節裡面,如何清晰描述系統讓不同人找到自己的關注點,將成為難題。

  通常我們會從巨集觀的架構設計上進行講解,然而當我們在探討架構設計的時候,每個人對架構的抽象層次理解都不一樣,抽象這種東西,說起來好像存在,但是要具體描述乃至落筆下來,還是非常有難度的。

  所以我們需要的是:讓程式設計師和業務人員在討論系統時候,能有統一的維度和統一標準,這就像是領域驅動設計裡面所提倡的統一語言,讓所有人在統一的認識中有效的溝通。

  鑑於這樣的背景,C4 model提出這樣的概念來解決這個問題。

  C4 模型

  C4的理念是,具體把系統分為:System Context(上下文), Container(容器), Component(部件), Code(程式碼)這四層,每層代表著不同的檢視架構,關注點也會不同,所以每層適用於不同的人員,我們會針對當前的人員的角色,找到共同的關注點(合適的層級)來統一認識,然後擴充話題。

  當我們使用C4模型來描述自己的軟體架構時,可以通過不停的放大,把架構從巨集觀到細節具體地描述出來。就好比我們看地圖一樣,總覽(System Context)關注的是國家層面,然後到省(Container)的層面,由多個省來構成國家,再下一層,到市(Container),再到市是如何建設起來的(Code)。這四種不同的抽象層次的定義會讓我們更容易固定住我們討論的層次以及共同認識。

 

 

 

  我們來看一下每一層的具體含義。

  第一層 -  System Context

  在這一層,我們將不會關注細節,這裡提供的是系統級別的總覽關係圖,這層的關注點應該是使用者和系統的互動,而不是協議,技術點等一些具體的體現。所以它的使用人群是非技術人員,這裡面描述的是系統級別的互動,誰使用。

 

  在這裡,我們可以理解這是一個可供終端使用者使用的完整系統(或者多個系統)的描述和專注於該層的使用人員,這裡的一個系統可由一個或者多個服務(程式)組成,能完成我們業務的服務組合。所以看到我們使用者直接面對的是可用的系統,而一些郵件和許可權系統,則屬於子系統。

  在這裡的一些特定技術術語需要澄清一下:一個系統可由多個服務(微服務)組成,也可只有一個服務組成(郵件系統很可能只有一個郵件的收發服務)。

  需要特別注意的是,在跟別人探討這層的時候,儘可能不要引入技術術語,因為這層更多的是使用人員關注的,大家的認知應該是在對系統的正常理解。

  第二層 - Container

  這一層是上一層Context的繼續(我們這裡選擇的是用業務系統這個系統作為例子),是我們將各個System Context放大(Zoom in)的效果,我們將會看到一個技術棧以及各模組的一個職責和依賴。

   

  這層是給具有技術背景的人員看,這裡面描述的是程式級別的應用,這是可直接部署和執行的,通過這層,我們將可以看清軟體整體形態以及職責描述。

  這裡的Container也可以理解為容器,因為我們的應用程式也是按容器為單位部署的。

  第三層 - Component

   這一層是Container層的繼續放大,這裡將看到服務的具體組成,如我們的訂單服務包含哪些職責的類

  我們可以看到,這一層是給開發人員看,這裡描述的是系統組成部件、部件之間的層級關係和依賴。

  這層的Component,可以理解為java裡面的包或者c#裡面的程式集,這裡描述的是內部的包/程式集相互引用(呼叫)關係以及包對外部系統的程式的依賴

  第四層 - Code

  這一層是持續將Component放大的效果(借用一下官網的類圖:))。

 

  這一層的使用物件是開發人員,這裡描述的是基於UML等圖形來描述實現的技術細節,直接反映了程式碼層面。

  找到共同語言

  好了,當我們把整個系統通過通過C4 模型設計把不同層次的抽象軟體架構描述了出來,我們可以找到各自所關心的層次進行快樂的交流了。

  什麼?你想給剛來的產品經理講Component級別的架構?不,你不想,你也不能想,因為他並不關心這個,你能講的,就是基於Context級別,講述我們公司的整個產品體系是如何執行以及關聯依賴的。

  所以,回到我們的前言:讓所有人在統一的認識中有效的溝通。這讓我們在探討之前,先找好各自關心的層次,然後再進行交流。這也是C4 模型給我們帶來的巨大價值。

  我們如何落地?

  說了那麼多概念,可以來點乾貨了,如何動手把腦袋中的架構展示出來?

  PlantUML

  什麼是PlantUML? PlantUml是一個支援快速繪製的開源專案,其定義了一套完整的語言,通過文字、程式碼等工具用於實現UML關係圖的描述。

  通過PlantUML,我們可以輕鬆通過程式碼形式畫出自己想要的圖形。 

  這裡採用一個流程圖作為例子: 

@startuml
使用者 -> 認證中心: 登入操作
認證中心 -> 快取: 存放(key=token+ip,value=token)token

使用者 <- 認證中心 : 認證成功返回token
使用者 -> 認證中心: 下次訪問頭部攜帶token認證
認證中心 <- 快取: key=token+ip獲取token
其他服務 <- 認證中心: 存在且校驗成功則跳轉到使用者請求的其他服務
其他服務 -> 使用者: 資訊
@enduml

  

  PlantUML不僅僅能畫出C4 模型架構,還能輕鬆畫出常用的UML圖,以及通過安裝外掛,實現draw.io ,xmind等外掛的圖形繪畫。

  使用PlantUML刻畫C4

   在VSCode中下載PlantUML外掛,然後在GitHub上搜尋一些好用的PlantUML開源庫,直接程式碼形式畫圖吧。

 

   補充個人上面圖形的PlantUML原始碼:)

   總結

  軟體架構圖是一種非常好的表達方式,可以用它們來表達你將如何構建一個軟體系統或者現有的軟體系統是如何工作的,而C4 模型則能很好的解決這個問題,它是由一系列分層的軟體架構圖組成,這些架構圖用於描述不同層次的不同的抽象,每層的抽象都會有不同的適用人群。

  當我們擁有了C4 模型的方法論之後,面對不同角色人員,我們將清楚的知道,應該宣講哪層以及該把關注點放在哪層,這樣我們將會在統一的意識層面上探討,做到意識上的統一。

相關文章