架構師必看:軟體架構圖的藝術
要點
- 設計軟體架構圖並非一件輕而易舉的事情,即使是很簡單的一個架構圖也可能會出錯。有意義且具備一致性的架構圖有助於為不同的利益相關者澄清事實,並達成共識。
- 在大多數情況下,問題的根源並不在於是否使用了一門有效的架構描述語言(比如UML),而在於低估了架構圖的重要性,轉而依賴不恰當或不具備一致性的指導性原則,或者缺乏架構思維。
- 在建立架構圖的過程中,試著混合使用自動生成的圖元和手動建立的圖元,這樣可以減少工作量,並且可以表達出各方面的關注點,覆蓋到系統的各個層面。
- 系統不斷地發生演化,要維護更新架構圖需要花費額外的精力。我們需要知道如何有效地應對這種情況,同時能夠保持架構圖的一致性和健壯性。
現代的軟體架構帶來了更多的複雜性,這些都反映在了架構圖上。
曾幾何時,我們的每一個軟體專案都需要一個架構圖。不管我們是否遵循正式的架構模型(比如Kruchten 4+1、Rozanski & Woods等),都有必要通過圖表來對應用程式的某些部分進行文件化。在軟體架構裡,這些圖表一般都是按照某些檢視進行設計的,這些檢視本身就是模型的一部分,不過在這篇文章裡,我傾向於使用架構圖這個術語,因為它看起來不是那麼正式,至於其他方面的內容並不會在這篇文章裡涉及到。
作為一個軟體架構師和技術培訓師,從我的經驗來看,不同專案之間以及同一個團隊的不同開發人員之間建立架構圖的方式也是很不一樣的。我看到過很多問題,比如一致性問題、碎片化問題、資訊粒度大小的問題,以及圖表的外觀問題。相比架構模型的正式和標準化,架構圖倒是不必要那麼正式或者遵循什麼標準。
相關廠商內容
解讀百度PB級資料倉庫Palo開源架構 Snapchat大規模個性化推薦引擎解密 微信社交廣告核心架構與圖計算儲存 摩拜單車:如何通過機器學習等技術提高單車運營效率 獲取面向人工智慧、機器學習和深度學習的最新工具、框架
相關贊助商
不過,架構圖必須是自描述的,並且要具備一致性和足夠的準確性,能夠與程式碼相呼應。這也就是為什麼架構師或軟體工程師在建立架構圖時需要依賴各種指導性原則,因為它們是理解應用架構(比如結構、元素、關係、屬性、原則)的基石,同時也是具有不同技術背景和關注點的利益相關者的溝通基礎。
當前架構圖的不足之處
在深入展開說明之前,我想引用一句英語諺語:“一張圖片勝過千言萬語”。Wiki上解釋說,“這句諺語的意思是,一個複雜的想法可以通過一張靜態的圖片表達出來,或者圖片可以表達一個主題的意思,又或者圖片比文字描述來得更加直接有效”。對於架構圖來說也是一樣的:如果它所導致的疑問比它能解釋的問題還要多,那麼它就不是一張好的架構圖。一張好的架構圖不需要多餘的文字解釋!
圖片:一張不是很好的架構圖一般會存在如下幾個問題。
現在讓我們來過一下不好的架構圖都有哪些問題,這些問題會阻礙我們建立好的架構圖。
方框或其他形狀表示什麼意思?
隨意使用方框或其他形狀可能會引起誤解。這些形狀有可能表示資料、程式碼或者流程。一個簡單的方框可能會引起多種猜想,所以很有必要顯式地給這些形狀新增有意義的說明。
形狀的邊線表示什麼意思?
在一個糟糕的架構圖裡,形狀的邊線(虛線、點線,等等)可能會引起誤解。邊線是否表示某種元件型別(比如虛線表示容器、微服務、層,等等),或者只是因為設計者想讓架構圖的觀感看起來更加豐富一些?所以,在使用多種邊線或非標準邊線時,要在圖例裡提供準確的說明。
線條或箭頭表示什麼意思?
線條或箭頭可以被理解為資料流(比如從系統A到系統B的資料流)或元素間的關係(比如元件A依賴元件B)。在大多數情況下,箭頭所表示的關係或資料流並不會總是匯聚到同一個方向上,所以很有必要在圖例裡說明清楚。
線條或箭頭表示哪一種型別的互動或關聯?
儘管線條可以表示資料流或元件間的關係,但用於表示互動型別(對於資料流而言)或關聯型別(對於關係而言)的線條或箭頭仍然需要詳細說明。例如,如果使用線條表示資料流,那麼互動型別可以是同步或非同步的,但如果線條表示的是關係,那麼關聯型別有可能是指依賴、繼承、實現,等等。這些細節必須在圖例裡說明。
顏色代表什麼意思?
一個使用了多種顏色的架構圖卻沒有適當的文件說明很容易引起誤解(比如為什麼有些方框是綠色的,而其他是紅色的?為什麼有些線條是黑色的,而有些是藍色的?)。顏色在架構圖裡的作用不是非常大,新增太多的顏色並不會給架構圖帶來更多有價值的資訊。一個僅僅使用了黑白兩色的架構圖也應該是不言自明的,除非非常有必要使用特定的顏色來強調圖中的某些部分。在任何情況下都要保持顏色的簡單性,如果一定要用多種顏色,不要忘了新增說明。
單獨的元素或實體
如果架構圖中出現了單獨的元素或實體,說明架構圖有可能是不完整的。不管是從結構還是從行為角度來看,每一個元素或實體都應該依賴系統的其他部分,或者與它們之間存在某些聯絡。
費解的縮略語或含糊不清的名詞
在為架構圖中的元素新增標籤時,切忌使用費解的縮略語,這樣容易引起困惑。如果沒有恰當的說明,字母的堆疊(比如TFH、RBPM,等等)就毫無意義,最好在圖例裡進行說明(比如TFH表示ticket feed handler,RBPM表示rates business process manager)。
在給元素命名時,另一個常見的問題是使用了含糊不清的名詞(比如業務邏輯、整合邏輯),這些名詞並不能做到自解釋。程式碼裡可能也會存在這樣的問題,我們建議遵循清晰的程式碼原則,使用自解釋的名字。
在架構圖中詳述技術、框架、程式語言、IDE或開發方法論
架構圖並非以技術、框架、程式語言、IDE或開發方法論為基礎,它們只是用來實現架構的工具,而不是中心關注點。它們不應該被包含在架構圖裡,不過可以在架構描述裡簡述使用它們的理由。
在同一個架構圖裡混雜執行時元素和靜態元素
執行時元素(比如執行緒、程序、虛擬機器、容器、服務、防火牆、資料倉庫,等等)不會出現在編譯階段,而且不應該與靜態元素(比如元件、包、類)同時出現在同一個架構圖裡。針對執行時元素有專門的型別圖(比如併發圖、部署圖),一定要注意區別這兩種元素,儘可能避免把它們混雜在一起。
“稍後詳述”或“稍後解釋”
不包含在架構圖裡的任何資訊都有可能丟失,而架構圖裡並沒有額外的地方可以容納口頭說明。所有的口頭說明都會丟失,當其他利益相關者(比如開發人員、架構師)檢視架構圖時,他們並不知道原來還有所謂的口頭說明。試著把所有必要的資訊都包含在架構圖裡,而不是事後加以說明。
層級衝突或混合抽象
在同一個架構圖裡新增不同層級的抽象可能會導致衝突的出現,因為它們是從不同的角度描述問題的。例如,把元件新增到上下文架構圖裡,或者把類加到部署圖裡,這些都會偏離架構圖原先的目的。在建立架構圖時,試著保持相同的抽象層級。
使用混亂或含糊不清的架構圖表達過量的資訊或無效的細節
愛因斯坦曾經說過,“凡事應該儘可能簡單,簡單到極致”。對於架構圖來說也是一樣的,我們需要謹慎地選擇資訊的層級和粒度,這並不是一件容易的事情,它取決於所使用的架構模型、架構師的經驗和系統的複雜度。
在建立架構圖時可參考的指南
除了上面列出的問題清單,還可以參考如下的一些指南來建立更好的架構圖。
選擇最優的架構圖數量
Philippe Kruchten說過,“架構是一項複雜的工作,只使用單個圖表來表示架構很容易造成莫名其妙的語義混亂”。要對系統進行良好的文件化,我們不能只使用一種圖表。不過在建立架構圖的時候,我們也難以確定該使用哪些型別的架構圖以及應該建立多少個。在做出決定之前,我們需要考慮多方面的因素。例如,架構的屬性和複雜度、架構師的技能和經驗、可用的時間、維護成本,以及利益相關者的關注點。網路工程師可能想看到包含了主機、通訊埠和協議的網路模型,資料庫管理員更關心如何系統是如何操作、管理和分佈資料的。所以,我們要選擇最優的架構圖數量,不管這個數字是多少。
糟糕的架構圖(比如缺乏文件)可能會缺失一些資訊,反過來說,如果架構圖太多(比如過度文件化),那麼用於保持架構圖一致性和更新架構圖的工作量也會相應增加。
保持架構圖的結構一致性和語義一致性
架構圖之間應該在方框、形狀、邊框、線條、顏色等方面保持一致。架構圖的結構外觀應該是一樣的,團隊不同成員建立的架構圖不應該給任何一個利益相關者造成理解上的障礙。理想情況下,可以在所有專案裡使用相同的建模工具。
從語義角度來看,所有的架構圖與最新的程式碼變更之間以及架構圖與架構圖之間都應該定期保持同步,因為一個架構圖的變更可能會影響到其他架構圖。同步可以通過手動進行,也可以通過建模工具自動觸發。通過建模工具自動觸發會更好一些,不過這也取決於具體的專案。最終的目的是要保持架構圖和程式碼之間的一致性,至於使用什麼樣的方法或工具可以自行決定。Simon Brown說,“如果架構圖與程式碼失去了聯絡,那麼就無法用來改進架構”。他的話其實是在強調保持語義一致性的重要性。
避免架構圖碎片化
架構圖越多就越難以理解,而且維護起來也很費勁。最直接的後果就是有可能出現碎片化(比如,通過兩到三個架構圖來描述同樣的質量屬性——效能、伸縮性,等等——但每一個架構圖都無法完整地描述它們)。在這種情況下,建議移除不能反映相關質量屬性的架構圖,或者把它們合併起來。
保持架構圖的可追蹤性
保留架構圖的變更記錄、比較不同版本架構圖之間的不同點,以及可以很容易地進行回退,這些都是很重要的。如果建模工具不支援這幾點,那麼對我們來說可能會是個問題。最近業界傾向於使用簡單而直接的文字語言來生成架構圖,這樣似乎可以解決可追蹤性問題。這樣做的另一個好處是可以保持架構圖之間的結構一致性。
在架構圖旁邊加上圖例
如果你沒有使用標準的架構描述語言(比如UML、ArchiMate),那麼就要在圖例裡註明每個架構圖元素的用意(比如方框、形狀、邊框、線條、顏色、縮略語,等等)。
如果使用了標準的架構描述語言,只要在圖例裡新增關鍵性的架構描述,不需要太多額外的資訊,因為看圖的人都知道如何按照標準的描述語言規範來理解你的架構圖。
使用架構描述語言(比如UML、ArchiMate等)會有不一樣的效果嗎?
關於如何在專案裡使用正確的架構描述語言有很多不同的看法。有些人認為UML太過死板,用來做架構設計缺乏靈活性,在某種程度上我認同這個看法。有時候,在不依賴UML的profile和stereotype特性的情況下也能很好地完成架構圖設計。至於說到其他的架構描述語言,我認為ArchiMate更加強大,相比UML,它更適合用來為企業系統建模。還有BPMN,它更專注業務流程的建模。對這些工具進行深入比較已經超出這篇文章的範圍,所以不再累述。
在選擇架構描述語言時,綜合性和靈活性是首要考慮的因素。但據我所知,完全不使用架構文件的情況也很常見。有些人覺得建立架構文件是一件很無聊的事情,而且覺得它們沒有什麼意義。這樣的專案應該不在少數。人們因為沒有使用合適的架構描述語言,所以建立不出很好的架構圖,相反,如果他們使用了更好的工具,結果可能會大不一樣。但事實並非如此,實際上他們跟本不想去建立什麼架構文件(包括架構圖),更糟糕的是,他們可能不知道該如何建立架構圖。這是我們首要解決的問題——瞭解文件的重要性以及如何建立它們(給軟體工程師做培訓),然後選擇合適的工具。
在系統和架構發生變化時如何更新架構圖?
更新架構圖有幾種方式,我將會介紹其中的三種。第一種,也是最簡單的一種,就是直接從程式碼生成架構圖。這樣可以保證架構圖與程式碼是一致的。不過目前的工具還不能完全支援這種方式,在沒有人工介入的情況下,工具還無法基於程式碼生成精確且有意義的架構圖。Len Bass說,“在最理想的開發環境裡,只需要一個按鈕就能得到我們想要的文件”。他指的就是自動生成架構圖,但我們還遠遠沒有達到那種程度。
第二種,先用建模工具建立架構圖,然後生成程式碼骨架(比如元件或包、API),隨後開發人員可以在骨架上新增程式碼。每次架構圖發生變更,需要從架構圖端重新生成程式碼骨架。
第三種,在每次加入新特性時手動更新架構圖。為了保證程式碼與架構圖的一致性,建議把更新架構圖作為開發流程的一部分。不過我們不推薦這種方式,因為這樣很容易造成架構圖過時或出現不一致(比如開發人員總是忘記或者不想更新架構圖)。
我的建議是混合使用現有的工具,結合手動和自動的方式來建立架構圖。例如,嘗試自動生成架構圖,使用工具基於程式碼渲染出符合基本要求的架構圖,不包含混亂無用的資訊。架構圖可以高度可變(比如可以適應頻繁的開發變更,這類架構圖一般具有較低層次的抽象),也可以是靜態的。這類圖表可以是上下文架構圖、參考架構圖、包圖、類圖、實體圖,等等。不過有時候僅僅基於程式碼無法生成滿足需求的架構圖,所以在這種情況下,自動建立架構圖不是理想的方式。這個時候需要手動建模作為補充,這類架構圖包括時序圖、狀態圖、併發圖、部署圖、運營圖,等等。
現代架構(如微服務)對架構圖有什麼影響?
微服務或其他任何一個現代架構風格(如無伺服器、事件驅動)只會影響到系統的結構、元件間的互動方式(比如元件間的關係)和原則。在我看來,我不認為架構風格會改變架構圖原先的含義。不過,相比傳統的系統(比如單體),我們所說的現代系統架構具有更高層次的複雜性,它們對架構描述和架構圖確實會有一些影響,這些是我們需要注意的。我們需要考慮分散式元件(比如分散式微服務)、每種元件的型別、元件間的互動方式(比如邊界、API、訊息)、他們的生命週期以及從屬關係。
綜上所述,我們需要在架構圖中體現系統的分解、開發、部署和運維。假設有一個包含了大量微服務的系統,它就會有很多的架構圖,因為每個微服務都可能有自己的架構圖。一致性(例如,改變一個服務的API會影響到其他服務,所有相關的架構圖都需要做出修改)、碎片化(例如,一個架構圖無法反映分散式服務的高可用性和效能)和橫斷面(例如,是誰在負責處理系統的監控或安全問題)問題會讓人手忙腳亂。我們首要面對的挑戰是如何進行良好的團隊協作,不僅僅是開發,也包括後續的維護。
總而言之,現代系統的複雜性會帶來額外的問題,它們會在架構圖層面造成一定程度的影響。
作者 : Ionut Balosin是Luxoft的軟體架構師,擁有十年以上的應用程式開發經驗,專注效能調優和軟體架構。他是開發大會的演講常客,也是一名技術培訓師。
出處: http://www.infoq.com/cn/articles/crafting-architectural-diagrams
版權申明:內容來源網路,版權歸原創者所有。除非無法確認,我們都會標明作者及出處,如有侵權煩請告知,我們會立即刪除並表示歉意。謝謝。