可視化架構設計——C4介紹

好多年前,同事徐昊說過的一句話給了我很大啟發,他說“紙上的不是架構,每個人腦子裡的才是”。這句話告訴我們,即便是天天工作在一個團隊裡的人,對架構的認識也可能是不一樣的。每個人嘴上說的是類似的話,但心裡想象的畫面仍然是不一樣的。在多年的工作中,我越來越認可這句話所揭示出的道理。軟件開發是一個團隊協作的工作,混亂的理解會造成架構的無意義腐化、技術債的無意識積累、維護成本的無價值上升。

最近聽到一句話,“那些精妙的方案之所以落不了地,是因為沒有在設計上兼容人類的愚蠢”。話糙理不糙,雖然最終人們選擇的方案的思想都是在十年前甚至幾十年前就已經存在的,然而在技術升級到足以“兼容”人類的愚蠢之前,這些思想只能在學術的故紙堆裡睡大覺。當然話糙確實也會有一個問題,將一個思想性問題轉化成了情緒性問題。人們容易把一些糟心的事情歸因到人類的愚蠢,在宣洩完不滿情緒後就停止思考了。作為知識工作者,我們的思維不能停步,我們需要思考到底人類有哪些愚蠢,分別用什麼方法去避免或者“兼容”。

可以肯定彼此明明對自己開發的軟件有不一樣的認識卻天天在一起討論問題並試圖把軟件做好是一件愚蠢的事情,為了兼容這種愚蠢我們需要採用可視化的方法。

為什麼需要可視化呢,主要還是語言不靠譜。人類語言真的是太隨意了,只要你想,你可以說你見過一個方形的圓,併為此與別人辯論。但是無論如何你也畫不出來一個方形的圓,這就是我們需要可視化的原因。

今天我們介紹一個工具,叫做C4 model,這是我近幾年見到的一個比較難得跟我的認知有大量共鳴的工具。

該工具的作者在多年的諮詢中經常發現,很多個人畫出來的架構圖都是不一樣的,但也不是說誰畫錯了,而是每個人的抽象層次不一樣。抽象層次這種東西,說起來好像存在,但真要說清楚還挺難,於是作者類比地圖,提出了縮放的概念。(兩年前我在教學生的時候提過同樣的概念)如下圖:

可視化架構設計——C4介紹

上面的四張地圖就是想說明,當我們看待真實世界的“架構圖”時候,也是要不停的縮放,在每一個層次刻意忽略一些細節才能表達好當前抽象層次的信息。所以他類比著把架構也提出了四個抽象層次:

可視化架構設計——C4介紹

從上到下依次是系統System、容器Container、組件Component和代碼Code。(咦,那為什麼叫C4呢,因為系統的圖叫System Context,系統上下文圖。為了湊四個C也是夠拼的。)

基於這四個層次的抽象,C4模型由4張核心圖和3張附屬圖組成,分別用於描述不同的場景,下面我們一一介紹一下。

四張核心圖

系統上下文圖

可視化架構設計——C4介紹

如上圖所示,這個圖表達的是你所開發的系統和它的用戶以及它所依賴的系統之間的關係。從這個圖上我們已經看出來C4圖形的幾個關鍵圖形:

可視化架構設計——C4介紹

C4說穿了就是幾個要素:關係——帶箭頭的線、元素——方塊和角色、關係描述——線上的文字、元素的描述——方塊和角色裡的文字、元素的標記——方塊和角色的顏色、虛線框(在C4裡面虛線框的表達力被極大的限制了,我覺得可以給虛線框更大的擴展空間)。

通過在不同的抽象層次上,重新定義方塊和虛線框的含義來將我們的表達限制在一個抽象層次上,從而避免在表達的時候產生抽象層次混亂的問題。

那麼在系統上下文圖裡,方塊指代的是軟件系統,藍色表示我們聚焦的系統,也就是我開發的系統(也可能是我分析的系統,取決於我是誰),灰色表示我們直接依賴的系統,虛線框表示的是企業的邊界。通過這些圖形化的元素表達我們可以看出來各個系統彼此之間的關係。

容器圖

可視化架構設計——C4介紹

當我們放大一個系統,就會看到容器,如上圖所示,C4模型認為系統是由容器組成的。我個人認為,容器是C4模型最大的創舉,尤其是在這個單體架構快速崩塌的時代。所謂容器,既不是Docker的容器,也不是JavaEE裡的容器,而是借用了進程模型,代指有自己獨立進程空間的一種存在。不管是在服務器上的單獨進程空間,還是在瀏覽器裡的單獨進程空間,只要是單獨的進程空間就可以看作一個容器。當然如果你容器化做得好,Docker的Container和這個Container可以一一對應。有了這個概念的存在我們就可以更清晰的去表達我們的架構,而不是總是用一些模糊的東西。

組件圖

可視化架構設計——C4介紹

當我們放大一個容器,我們就會看到組件,如上圖所示。組件在這裡面很好的把接口和它的實現類打包成一個概念來表達關係。我個人覺得有時候一些存在於代碼中,但又不是接口的某些東西,比如Service、Controller、Repository之類也可以用組件圖來表達,如果你學了一些沒有明確抽象層次的架構知識或者一些單體時代的遺留經驗的時候,你可以畫出來一些組件圖,來印證自己的理解,如下圖,是我畫的自己對DDD戰術設計裡面的一些概念的理解:

可視化架構設計——C4介紹

比起模糊的堆砌在一起的文字,這種表達要清晰的很多,哪怕我的理解是不對的,也容易指出和討論。

代碼圖

代碼圖沒什麼可說的,就是UML裡的類圖之類很細節的圖。一般是不畫的,都是代碼生成出來。除非非常重要的且還沒有寫出代碼的組件才畫代碼圖。

以上就是C4的核心圖,我們可以看到四種不同的抽象層次的定義會讓我們更容易固定住我們討論的層次,這點上我覺得C4是非常有價值的。

三張擴展圖

架構設計設計要考慮的維度很多,僅四張核心圖是不夠的,所以作者又提供了三張擴展圖,可以讓我們關注更多的維度。

系統景觀圖

可視化架構設計——C4介紹

看得出來,系統景觀圖是比上下文圖更豐富的系統級別的表達。不像上下文圖只關注聚焦系統和它的直接關係,連一些間接相關的系統都會標示出來,那些系統的用戶以及用戶之間的關係也會標示出來,只是內部的用戶會用灰色標記。

這個圖有什麼用呢?在我們分析一個企業的時候,我們需要一個工具幫助我們把一家公司給挖個底掉,做到完全窮盡,才能看到企業的全景圖,從而理解局部的正確定位以做好局部設計為全局優化服務。之前我試過以四色建模的紅卡、事件風暴的事件兩種工具來教人掌握這種能力,一般來說,程序員學員都無法快速掌握這種順藤摸瓜的分析技巧,畢竟跟程序員的思維還是有些差異的。但是用了系統景觀圖之後,學員就毫不費力的掌握了這種分析能力,所以我後來都是用這個圖來教程序員探索企業的數字化全景圖,效果極好,推薦給大家。

動態圖

可視化架構設計——C4介紹

動態圖不同於其他表達靜態關係的圖,它是用來表達動態關係的,也就是不同的元素之間是如何調用來完成一個業務的。所以動態圖不僅僅適用於一個層面上,它在系統級、容器級和組件級都可以畫,表達的目標是不一樣的。

我之前曾經寫過名為《像機器一樣思考》的一系列文章,在文中也發明了類似的圖,不同於本文中關係線上標註的是調用的方法、函數,我更關注的是數據,使用效果也很好。

什麼時候用動態圖呢?舉個小例子,我之前做一個內部的小系統,團隊中只有一個有經驗的工程師帶著十多個畢業生,我便要求他們在開始工作之前都畫出動態圖來,交由有經驗的工程師去評估他們的思路是否正確,如果有問題,就在開始之前就扼殺掉爛設計。不管是畢業生還是初級工程師,改代碼的能力都比寫代碼的能力要差很多,所以將爛設計扼殺在實現之前還是有幫助的。

部署圖

可視化架構設計——C4介紹

前面的幾張圖都是站在開發的角度思考,但是一個沒有充分思考過部署的架構很容易變成一個運維的災難。所以作者提供了一個部署圖。考慮到DevOps運動如火如荼,這個圖可以變成很好的Dev和Ops之間溝通的橋樑。我們在實操中發現,Dev和Ops關注點的不同、語言的不一致,在這張圖上表現得非常清楚。

圖上最大的的實線框不同於虛線框,它表達的是數據中心,當你開始考慮異地載備的時候它就有了意義。數據的同步、實例的數量都會影響部署圖的內容。部署圖基本都是容器級的,它能很好的表達出來容器到底部署了幾個實例,部署在什麼樣的操作系統上,一個節點部署了幾個容器之類,我們在實際使用中,發現需要考慮的信息太多,自己就抽象出了類似於亞馬遜上實例規格的Small、Large之類的術語來表達機器配置,增進了開發和運維之間的交流準確性。

為什麼C4值得推薦

夠直觀,對於程序員來說容易理解,容易使用。

我們在開頭的時候說過,只有每個人腦子裡的才是架構圖,如果我們使用一個本身就很難達成一致理解的工具,那成員就會陷入理解的死循環。經過嘗試教授不同工具,發現C4模型是最容易理解、最容易使用的工具。可能它的概念是複用了程序員已有的一些認知模型,程序員在學習後都可以迅速的使用起來,並問出一些高質量的問題。

總結

在思維的世界裡,我們都是盲人,很多東西我們以為自己知道,實際上畫出來之後,才發現很多東西沒想到,或者想的是亂的,同時別人也才可以給我們反饋。

有了上面的這個工具,我們就可以開始可視化的架構設計之路了,但路上還有一個心魔需要戰勝。在我們的文化裡,出錯是一件很丟人的事情,所以我們喜歡用一些模糊的描述避免被別人挑戰,而可視化是讓我們精確的描述出自己的理解,來歡迎別人的挑戰。這一個坎不太容易跨過去,但是一旦跨過去、大家形成正向的互動之後,我們的進步速度會變得很快,從而把封閉的人遠遠的甩在後面,獲得組織級的成長推力。我自己就在跟別人的交流之後獲得了更深入的洞見,本文已經分享了一些,還有一些內容後續再跟大家分享。


注:文中圖片均來自:https://c4model.com/

文/ThoughtWorks仝鍵

原文:https://insights.thoughtworks.cn/c4-model/

相關推薦

推薦中...