軟體系統架構設計的目標不在於設計本身,而在於架構設計意圖的傳達。圖形化有助於在團隊間進行高效的資訊同步,但不同的圖形化方式需要語意一致性和效率間實現平衡。C4模型通過不同的抽象層級來表達系統的靜態結構,並提供了最小集的抽象建模元素,為設計人員提供了一種低認知負載、易於學習和使用的高效建模方式。
軟體系統架構設計的目標不在於設計本身,而在於架構設計意圖的傳達。如果不能清晰、一致的在干係人間進行設計意圖的同步,即使再好的設計也只是空中樓閣。軟體架構設計本質上也是一種抽象和建模的過程(對模型和抽象的本質參考文章《 領域驅動設計開篇 》),軟體架構設計模型的表達有多種方式:圖形化、語言和文字。絕大部分場景下,圖形化在架構設計的表現力層面效果更佳。因此,對於軟體系統架構進行視覺化表達是有價值,且是必要的。
軟體架構視覺化的方式有多種,不同的團隊有不同的實踐方式,最為常見的由如下幾種:
不同的視覺化方式各有優劣,以下部分將對不同的表現形式進行說明
線框圖是最為通用的視覺化表達方式之一,架構師或設計人員大量的架構圖,比如技術架構、功能架構、資料架構、邏輯架構等等都通過線框圖的形式表達。該種視覺化方式的優勢是:
但,基於線框圖表達軟體系統架構存在的問題也非常明顯:語意的一致性問題
你可能自己畫過很多軟體系統架構圖,也可能參與評審過其他團隊的架構圖,我相信,對你而言並不是的所有的圖都是「清晰且易於理解的」。舉個簡單的場景,如果我們在百度搜尋 「架構圖」 ,你可能得到以下結果:
各式各樣的 「架構圖」:不同形狀和顏色的圖形元素、不同形狀和顏色的連線、不同的意圖。
我們可以看出:線框圖雖然簡單,但其其圖形化的語意一致性是大問題。雖然都是通過線框表達軟體系統架構,但不同的人可能使用不同的元素、不同的顏色、不同的連線和分層等等,線框自由表達的靈活性和圖形化語意的一致性存在潛在衝突,最終都會阻礙架構設計意圖傳達。
UML是統一建模語言,相比於線框圖而言,其優勢是在軟體建模層面提供了一致性的建模元語言。簡單來說,UML提供了大家達成一致的(UML支援擴充套件的場景除外)建模元素。如果團隊成員比較熟悉UML,那麼通過UML表達的系統架構圖天然具有認知一致性。
豐富靈活的建模元語言在提升語意一致性的同時,也必然會導致複雜性的上升。掌握UML具有一定的學習成本,而熟練的應用對研發人員也提出了更高的要求。基於 Simon Brown給出的資料,實際情況只有少數團隊真正使用UML。不論是UML的複雜度和學習成本原因,還是敏捷化下對UML的排斥,很多團隊都放棄了UML。
我們不能否認UML的價值,基於統一建模語言能夠更有效的進行架構設計的資訊傳遞和溝通,也能基於UML提供的詳細的模型圖元素進行充分的設計表達。團隊中是否要基於UML進行溝通需要權衡,雖然UML不能表達你所要傳達的全部的架構資訊,但其在某些維度的表達相對比較適合。
架構視覺化另一個非常常見的方式是:草圖。草圖是一種非正式的、易於快速溝通的圖形化方式。團隊基於特定的場景,可以通過草圖的形式進行快速的溝通,以便高效的在干係人間拉齊關鍵資訊。
但,草圖的劣勢與線框圖一樣:語意一致性低
我們可以在白板上 「隨心所欲」 的畫各式各樣的草圖,草圖上的元素、連線,又或者佈局都可能是湧現式的、臨時性的,這些草圖的價值在於 「對談週期內的高效溝通」。如果幹系人沒有完全參與到草圖的討論,又或是後置檢視,大概也很難精準捕獲這些草圖所要表達的設計意圖。
團隊需要統一語言進行高效溝通 !!!
C4模型在不同的級別提供了統一的抽象以表達軟體系統的靜態結構。如下圖所示:
我們要構建的系統不會孤立存在,都會依賴現有的IT設施。要明確我們構建的系統是什麼,宏觀上需要回答:我們的系統如何融入到現有的IT設施。
系統上下文圖正是從高層視角表述待構建系統與當前IT設施的互動及邊界。通過上下文圖:
更進一步的剖析核心系統,回答:系統由哪些容器組成?容器的職責是什麼?以及相關的高層的技術選型是什麼?
與Docker的容器概念不同,C4模型的容器是在 「系統」 作用域之下,其表達的是組成系統的可獨立可部署的物理單元。以下圖為例:單個容器元素重包含了名稱、職責描述、技術選型,同時,容器間的連線及標註標識了其高層的互動協定及互動形式。
進一步的剖析容器,回答:容器由哪些元件組成?這些元件的職責及元件間的互動形式是什麼?
具體到每個容器內部,通過多個元件及元件間的關係表達容器的組成。「元件」 本身是一個泛化的概念,C4模型的元件是在 「容器」 的作用域之下,其表現形式可能是獨立的Jar包,或者是應用內獨立的包,也可能是類級別,但邏輯上都能夠表達一個元件的概念。對於元件圖關鍵的是要表示清楚元件的實現選型、元件職責以及元件間的互動關係。
程式碼處於C4模型的最低層,且是可選的,其關注的是實現相關。C4模型並沒有對實現層面的視覺化進行統一抽象,開發人員可以選擇UML類圖、E-R圖等進行視覺化。是否需要提現程式碼層面研發人員基於具體情況具體分析,一般情況下,如果系統中需要重點關注的部分可以考慮一些程式碼級別的圖支援,比如,我們非常關注系統設計的可延伸性,則關鍵部分可能需要一些類圖表達;又或者非常關注底層資料模型,則E-R圖可以納入考慮範圍。
連線表達依賴關係還是資料流向 ?
都可以,C4模型中的連線既可以表達依賴方向,也可以表達資料流向。原則上,設計人員需要保證其清晰且無歧義。實踐中一般通過合理的文字說明來明確的表達元素間的關係。
Jar或類庫應該建模為「容器」? 「元件」 ?
Jar包或類庫一般是連結到呼叫方的程序中,作為程序中的一部分存在,這種依賴一般不表示為容器,而是元件。當然,是否要將Jar,比如SDK表示為元件並體現在元件圖上需要設計人員具體情況具體分析。
資料儲存系統應該建模為 「軟體系統」 還是 「容器」 ?
資料儲存系統,比如MySQL、DFS等一般是作為獨立的外部儲存叢集存在,叢集的運維可能歸屬於公司的運維團隊。以OSS為例,但從應用角度而言,即使叢集的運維不歸屬當前開發團隊,團隊也會申請租戶隔離的專屬空間,因此,在C4模型中這種情況應該表述為 「容器」。
訊息系統應該如何建模 ?
訊息系統一般作為兩個容器間的互動媒介,因此在C4模型中訊息系統的建模存在兩種方式:
圖形化的過期問題
C4模型本身也是一種檔案化機制,同樣也存在過期問題。只不過C4模型通過對系統在不同的層級進行抽象,每個抽象層級的過期頻率不同,由上到下逐漸增大,上下文圖的變化頻率最小,而程式碼級則變化最大。
為什麼C4不涉及業務流、狀態機、資料模型等建模
C4模型僅對系統的靜態結構進行建模,並不試圖囊括或替代其它建模方式,C4模型並不適合所有維度的視覺化表達。對於業務流可以基於BPML、UML活動圖進行表達,狀態機可以基於UML狀態機圖進行表達,而資料模型可以通過E-R圖表達,不同建模語言相互補充。
作為架構師或系統設計人員,在進行系統架構設計時一般會關注不同維度,一般情況下,對於業務系統建設而言,會關注以下維度。在架構設計(架構和設計)過程中,基於C4模型、UML及BPML等多種建模方式相互補充,不同表現維度下可以採用不同的建模方式
軟體架構設計的終極目標不在於設計本身,而在於架構設計意圖的傳達。圖形化有助於在團隊間進行高效的資訊同步,但不同的圖形化方式在語意一致性和效率間存在平衡。C4模型通過不同的抽象層級來表達系統的靜態結構,並提供了最小及的抽象建模元素,為設計人員提供了一種低認知負載、易於學習和使用的高效的建模方式。在實際專案落地過程中,結合C4模型以及UML、線框圖等組合方式對架構設計進行視覺化表達,一定程度上能夠提升團隊對架構設計認知的一致性以及建模效率。
作者:倪新明