概述
最近在開發(fā)系統(tǒng)中倾贰,發(fā)現(xiàn)需要一種方式來構(gòu)建對于當前系統(tǒng)的理解和細化易猫,UML是我一下子映入腦海的方式著隆,但是很久不再接觸了狡相,剛好在前段時間看到關(guān)于C4model(官網(wǎng))相關(guān)文章,剛好可以試試
架構(gòu)圖的主要功能是從各個角度和各個層次去描述系統(tǒng)的功能褪迟,主要是從宏觀到微觀的描述冗恨。C4 Model也是提供圖形從不同的層次去描述我們的系統(tǒng)。主要的優(yōu)勢是C4 Model提供很少的抽象圖形要素和圖類型來描述系統(tǒng)味赃,使得各個系統(tǒng)參與者都能很快理解系統(tǒng)的功能掀抹。這些圖從層級上來看都是縮放的,就行谷歌地圖一樣
為了構(gòu)建實際系統(tǒng)的抽象心俗。C4 Model對于系統(tǒng)的描述提供了四個抽象層次:
這個抽象層次里面包含5個要素
- Software System:軟件系統(tǒng)最高的抽象層次傲武,描述了交付給用戶完成用戶所需功能的系統(tǒng)蓉驹。
- Person:使用系統(tǒng)的人或者角色
- Container: 容器是獨立運行一些代碼和數(shù)據(jù),組合起來完成系統(tǒng)功能的要素揪利。一個容器可以是Server-side web application态兴、Client-side web application、Client-side desktop application疟位、Mobile app瞻润、Server-side console application、Microservice甜刻、Database绍撞、Blob or content store、File system得院、Shell script等傻铣。
- Component:組件一組相關(guān)功能的封裝,對外提供良好的接口祥绞。
基于這四個層次的抽象非洲,C4 Model由4張核心圖和3張附加圖組成
四張核心圖
4張核心圖分別為系統(tǒng)上下文圖(Context)、容器圖(Container)就谜、組件圖(Component)、代碼圖(Code)里覆,代碼圖是實際的類實現(xiàn)丧荐,可選。
系統(tǒng)上下文圖
系統(tǒng)上下文圖主要表述的是當前要開發(fā)的系統(tǒng)和周邊環(huán)境的關(guān)系喧枷,包括系統(tǒng)和用戶之間的關(guān)系和系統(tǒng)和周邊系統(tǒng)的關(guān)系虹统,在系統(tǒng)上下文圖里,方塊指代的是軟件系統(tǒng)隧甚,藍色表示我們關(guān)注的系統(tǒng)(位于中心)车荔,灰色表示我們直接依賴的系統(tǒng)或者依賴我們的系統(tǒng),虛線框一般用于用于聚合相關(guān)元素戚扳。
容器圖
當我們理解了當前關(guān)注的系統(tǒng)在整個IT環(huán)境中的地位的時候忧便,需要將當前系統(tǒng)放大,觀察里面的內(nèi)部結(jié)構(gòu)帽借,放大后就會看到容器珠增,如上圖所示,C4模型認為系統(tǒng)是由容器組成的砍艾。容器圖顯示的是軟件架構(gòu)中各個獨立的部分(一般是一個獨立的進程)蒂教,每個容器的職責和他們間是如何交互的,以及容器與其他系統(tǒng)是如何交互的脆荷。它顯示了當前軟件系統(tǒng)的技術(shù)選型和交互方式凝垛。它是一個簡單的懊悯、以高級技術(shù)為重點的圖表,對軟件開發(fā)人員和支持/操作人員都很有用
組件圖
繼續(xù)放大容器梦皮,可以看到每個容器里有哪些組件組成炭分,組件的職責是什么,組件是如何交互的届氢。組件主要是相關(guān)功能的聚合欠窒,提供對外的接口
代碼圖
代碼圖跟UML里面的類圖很類似。除非非常重要的且還沒有寫出代碼的組件才畫代碼圖退子。
核心圖主要固定了我們系統(tǒng)的抽象層次岖妄,方便討論和理解。
三張擴展圖
核心圖讓我理解了系統(tǒng)靜態(tài)架構(gòu)寂祥,三張擴展圖缠借,可以讓我們關(guān)注更多的維度砖织。
系統(tǒng)景觀圖
系統(tǒng)景觀圖是比系統(tǒng)上下文圖更豐富的系統(tǒng)級別的表達。不像上下文圖只關(guān)注聚焦系統(tǒng)和它的直接關(guān)系,連一些間接相關(guān)的系統(tǒng)都會標示出來鞋仍,包括那些外部系統(tǒng)相關(guān)的用戶。系統(tǒng)景觀圖的意義在于從企業(yè)的整個IT架構(gòu)來看待當前要構(gòu)建的系統(tǒng)的功能和價值尘奏。
動態(tài)圖
動態(tài)圖不同于上面所有靜態(tài)圖的表達马昨,它表達的系統(tǒng)的某個運行態(tài),這個運行態(tài)中完成了一個用戶的場景或者功能虽界。所以一般有步驟汽烦,有順序。而且可以在各個層級去描述這個動態(tài)圖莉御。
部署圖
部署圖主要描述系統(tǒng)在容器級別是如何實際部署到物理基礎設施中的撇吞。
圖形符號(Notation)如何描述
C4模型沒有規(guī)定任何特殊的圖形。所以簡單的圖形就可以描述礁叔,如下
我們可以使用顏色和形狀是的圖形描述更加清晰牍颈。所有圖形都需要是自描述的。
下面有一些關(guān)于圖形符號的實踐推薦
圖
- 每張圖都應該有個標題標明圖類型和范圍
- 圖中需要有個圖例來解釋所使用的圖形符號(比例 形狀琅关、顏色煮岁、邊框樣式等)
- 圖形里面的縮寫所有受眾都能理解
元素
- 所有元素的類型需要被明確指定
- 所有元素都需要一個簡單描述,描述其核心職能
- 所有的容器和組件都需要明確的指定技術(shù)
關(guān)系
- 所有關(guān)系線都只表示單向的關(guān)系
- 每一行都應該加上標簽涣易,標簽應該與關(guān)系的方向和意圖保持一致(例如依賴關(guān)系或數(shù)據(jù)流)人乓。盡量把標簽寫得具體些,最好避免使用“Uses”這樣的單字都毒。
- 容器之間的關(guān)系(通常代表進程間通信)應該有明確標記的技術(shù)/協(xié)議色罚。
C4的工具
在挑選了眾多工具之后,發(fā)現(xiàn)C4-PlantUML比較適合账劲,當然功能最強大的還是C4 model官網(wǎng)推薦的第一個工具structurizr戳护,但是是商業(yè)版本的金抡。C4-PlantUML是可以用文本描述圖形和圖形關(guān)系,但是不足之處是支持的圖并不是很全腌且,不支持動態(tài)圖和部署圖梗肝。所有圖形符號使用方框標示的,直觀性要差一些铺董。
安裝
下載java并安裝巫击,Path里面也要有java的路徑
下載graphviz并安裝
下載visual studio code安裝
配置graphviz的環(huán)境
找到本地graphviz的安裝路徑的bin目錄,我的是D:\Program Files (x86)\Graphviz2.38\bin精续,然后配置系統(tǒng)變量GRAPHVIZ_DOT的值為D:\Program Files (x86)\Graphviz2.38\bin\dot.exe 就成功了
安裝vscode插件
打開vscode
運行 VS Code Quick Open (Ctrl+P)
輸入ext install plantuml
圖形示例
系統(tǒng)上下文圖
@startuml
!includeurl https://raw.githubusercontent.com/RicardoNiepel/C4-PlantUML/master/C4_Context.puml
' uncomment the following line and comment the first to use locally
' !include C4_Context.puml
LAYOUT_WITH_LEGEND
title System Context diagram for Internet Banking System
Person(customer, "Personal Banking Customer", "A customer of the bank, with personal bank accounts.")
System(banking_system, "Internet Banking System", "Allows customers to view information about their bank accounts, and make payments.")
System_Ext(mail_system, "E-mail system", "The internal Microsoft Exchange e-mail system.")
System_Ext(mainframe, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")
Rel(customer, banking_system, "Uses")
Rel_Back(customer, mail_system, "Sends e-mails to")
Rel_Neighbor(banking_system, mail_system, "Sends e-mails", "SMTP")
Rel(banking_system, mainframe, "Uses")
@enduml
系統(tǒng)景觀圖
@startuml
!includeurl https://raw.githubusercontent.com/RicardoNiepel/C4-PlantUML/master/C4_Context.puml
' uncomment the following line and comment the first to use locally
' !include C4_Context.puml
'LAYOUT_TOP_DOWN
'LAYOUT_AS_SKETCH
LAYOUT_WITH_LEGEND
title System Landscape diagram for Big Bank plc
Person(customer, "Personal Banking Customer", "A customer of the bank, with personal bank accounts.")
Enterprise_Boundary(c0, "Big Bank plc") {
System(banking_system, "Internet Banking System", "Allows customers to view information about their bank accounts, and make payments.")
System_Ext(atm, "ATM", "Allows customers to withdraw cash.")
System_Ext(mail_system, "E-mail system", "The internal Microsoft Exchange e-mail system.")
System_Ext(mainframe, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")
Person_Ext(customer_service, "Customer Service Staff", "Customer service staff within the bank.")
Person_Ext(back_office, "Back Office Staff", "Administration and support staff within the bank.")
}
Rel_Neighbor(customer, banking_system, "Uses")
Rel_R(customer, atm, "Withdraws cash using")
Rel_Back(customer, mail_system, "Sends e-mails to")
Rel_R(customer, customer_service, "Asks questions to", "Telephone")
Rel_D(banking_system, mail_system, "Sends e-mail using")
Rel_R(atm, mainframe, "Uses")
Rel_R(banking_system, mainframe, "Uses")
Rel_D(customer_service, mainframe, "Uses")
Rel_U(back_office, mainframe, "Uses")
Lay_D(atm, banking_system)
Lay_D(atm, customer)
Lay_U(mail_system, customer)
@enduml
容器圖
@startuml
!includeurl https://raw.githubusercontent.com/RicardoNiepel/C4-PlantUML/master/C4_Container.puml
' uncomment the following line and comment the first to use locally
' !include C4_Container.puml
LAYOUT_TOP_DOWN
'LAYOUT_AS_SKETCH
LAYOUT_WITH_LEGEND
title Container diagram for Internet Banking System
Person(customer, Customer, "A customer of the bank, with personal bank accounts")
System_Boundary(c1, "Internet Banking") {
Container(web_app, "Web Application", "Java, Spring MVC", "Delivers the static content and the Internet banking SPA")
Container(spa, "Single-Page App", "JavaScript, Angular", "Provides all the Internet banking functionality to cutomers via their web browser")
Container(mobile_app, "Mobile App", "C#, Xamarin", "Provides a limited subset of the Internet banking functionality to customers via their mobile device")
ContainerDb(database, "Database", "SQL Database", "Stores user registraion information, hased auth credentials, access logs, etc.")
Container(backend_api, "API Application", "Java, Docker Container", "Provides Internet banking functionality via API")
}
System_Ext(email_system, "E-Mail System", "The internal Microsoft Exchange system")
System_Ext(banking_system, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")
Rel(customer, web_app, "Uses", "HTTPS")
Rel(customer, spa, "Uses", "HTTPS")
Rel(customer, mobile_app, "Uses")
Rel_Neighbor(web_app, spa, "Delivers")
Rel(spa, backend_api, "Uses", "async, JSON/HTTPS")
Rel(mobile_app, backend_api, "Uses", "async, JSON/HTTPS")
Rel_Back_Neighbor(database, backend_api, "Reads from and writes to", "sync, JDBC")
Rel_Back(customer, email_system, "Sends e-mails to")
Rel_Back(email_system, backend_api, "Sends e-mails using", "sync, SMTP")
Rel_Neighbor(backend_api, banking_system, "Uses", "sync/async, XML/HTTPS")
@enduml
組件圖
@startuml
!includeurl https://raw.githubusercontent.com/RicardoNiepel/C4-PlantUML/master/C4_Component.puml
' uncomment the following line and comment the first to use locally
' !include C4_Component.puml
LAYOUT_WITH_LEGEND
title Component diagram for Internet Banking System - API Application
Container(spa, "Single page Application", "javascript and angular", "Provides all the internet banking functionality to customers via their web browser.")
Container(ma, "Mobile App", "Xamarin", "Provides a limited subset ot the internet banking functionality to customers via their mobile mobile device.")
ContainerDb(db, "Database", "Relational Database Schema", "Stores user registration information, hashed authentication credentials, access logs, etc.")
System_Ext(mbs, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")
Container_Boundary(api, "API Application") {
Component(sign, "Sign In Controller", "MVC Rest Controlle", "Allows users to sign in to the internet banking system")
Component(accounts, "Accounts Summary Controller", "MVC Rest Controlle", "Provides customers with a summory of their bank accounts")
Component(security, "Security Component", "Spring Bean", "Provides functionality related to singing in, changing passwords, etc.")
Component(mbsfacade, "Mainframe Banking System Facade", "Spring Bean", "A facade onto the mainframe banking system.")
Rel(sign, security, "Uses")
Rel(accounts, mbsfacade, "Uses")
Rel(security, db, "Read & write to", "JDBC")
Rel(mbsfacade, mbs, "Uses", "XML/HTTPS")
}
Rel(spa, sign, "Uses", "JSON/HTTPS")
Rel(spa, accounts, "Uses", "JSON/HTTPS")
Rel(ma, sign, "Uses", "JSON/HTTPS")
Rel(ma, accounts, "Uses", "JSON/HTTPS")
@enduml