本文要點預覽:因為軟體系統的分散式特點以及開發團隊的分佈性,瞭解軟體架構的基礎變得越來越重要。而在過度設計和毫無設計之間,我們應該把註意力放在對軟體系統有重大影響的決策和權衡上。好的架構師應該是團隊的活躍分子,不僅能夠進行代碼協作,還能為團隊提供技術指導。軟體架構中的溝通環節極具挑戰性。C4 模型對 ...
本文要點預覽:因為軟體系統的分散式特點以及開發團隊的分佈性,瞭解軟體架構的基礎變得越來越重要。而在過度設計和毫無設計之間,我們應該把註意力放在對軟體系統有重大影響的決策和權衡上。好的架構師應該是團隊的活躍分子,不僅能夠進行代碼協作,還能為團隊提供技術指導。軟體架構中的溝通環節極具挑戰性。C4 模型對軟體架構中的溝通環節進行了結構化,從一個上下文圖表開始,再逐步深入到系統的各個技術層面。實際上,可以多花一些時間實現好的架構,好的架構能夠帶來敏捷。
隨著軟體行業的發展,開發團隊仍然面臨著與軟體架構有關的問題。這些問題比以往任何時候都要來得突出,因為我們現在構建的系統越來越趨於分散式化,開發團隊也越來越分散式化。為瞭解開這些迷思,開發者需要瞭解以下五個與軟體架構有關的事實。
1. 軟體架構不只是前期的“大設計”
傳統的觀點認為,軟件架構就是在前期進行“大設計”,然後通過瀑布模型進行交付,架構團隊要確保軟體的每一個元素在進行編碼之前都要考慮妥當。
2001 年,“敏捷開發宣言”建議我們“擁抱變化而不是遵循計劃”,但這個觀點後來卻被誤讀成不應該制定任何計劃。結果就是,有些開發團隊直接從原先的“大設計”變成了零設計。
這兩種極端的行為都愚蠢至極,實際上,在某個時候,你會發現前期的設計並非開發出完美軟體的必要因素。前期的設計應該只是一個起點,或是作為團隊前進方向的指引。
在進行軟體設計時需要做出一些設計決策。在談及軟體架構和軟體設計之間的區別這個問題時,Grady Booch 說,“架構代表了重要的決策,決策的重要程度通過變更成本來衡量”。
換言之,就是看在後續進行變更時那個決策需要付出更大的成本。所以,好的前期設計就是要充分理解什麼是“重要的決策”。這些決策通常與技術選型和結構(也就是分解策略、模塊化、功能邊界等)有關。
如果開發的是一個單體系統,那麼選擇何種編程語言可能就變得尤為重要。如果採用的是微服務架構,那麼使用何種編程語言就變得不那麼重要,但需要考慮其他方面的因素。類似的,如果採用了六邊形架構,雖然可以將業務邏輯與技術選型解耦開來,但仍然需要做出其他方面的權衡。
所以說,前期設計就是要瞭解影響軟體成型的重要決策,而不是具體的技術細節,比如資料庫的某個列要設置多大的長度。在現實當中,我會讓團隊真正去瞭解他們將要做什麼、如何去做以及他們已經設計好的東西是否可行。可以讓他們識別出最高優先順序的任務,如果有必要可以寫出代碼。總而言之,前期設計就是一個疊加成功幾率的過程。
2. 每個開發團隊都需要進行軟體架構
上述的內容適用於每一個開發團隊,從一個單人團隊到數百人的分散式團隊。設置起點和方向其實就是要建立技術領導力。如果做不到這一點,就可能出現混亂:結構混亂的代碼庫(典型的“大泥球”),難以理解,難以維護,質量不達標,如性能、伸縮性或安全性。簡而言之,任何一個開發團隊都需要技術領導力。
3. 軟體架構師要會寫代碼、指導他人以及參與協作
在大部分人看來,軟體架構師就是給開發團隊下達指令的人,就像接力賽中跑第一棒的人。但事實不是這樣的,現代的架構師喜歡編碼、指導他人並參與協作。我所遇見的好架構師也都是好的開發者,他們仍然喜歡編碼,最起碼他們並不想放棄編碼工作。
因為變化太快,人們很容易就與技術失之交臂。但我認為軟體架構師應該是“建築大師”,在必要的時候他們仍然可以寫代碼。作為團隊的一份子,編碼會讓架構師的工作變得更容易一些,因為編碼有助於架構師理解系統,而且團隊的其他成員會真正把架構師當成是同事。
需要註意的是,軟體架構師不一定要指定某個人來擔任。剛開始可以這樣做,但其實也可以由多個人共同承當這個角色。 但要註意,建立協作式的技術領導力並不是件輕而易舉的事。軟技能本來就不是很輕鬆就能獲得的。
我曾經組建 2 到 5 個人的架構師小組,讓他們來設計軟體系統,但他們在與技術和設計決策方面無法達成共識。在極端情況下,個性衝突會導致小組解散。關鍵是要瞭解你的團隊,並確保應用了恰到好處的技術領導力。
4. 不一定非要用 UML
傳統的軟體架構通常包含大量的 UML 模型圖,試圖充分展現軟體系統的每一個細節。可惜的是,建模和 UML 在很大程度上與前期“大設計”相耦合,而這些技術在近幾年已經過時了。現在完全不懂 UML 的軟體開發團隊比率在逐步上升。
現如今,大部分人只是“在白板上畫幾個方塊和線條”,並將其作為溝通想法的手段。在過去幾年,我參與過的軟體架構小組畫過大量這樣的圖表,我把它們拍成照片,有好幾個 G。我敢說,從行業角度來講,我們已經散失了軟體架構的溝通能力。我見過不計其數的圖表,它們有些是隨機著色方塊和線條的組合,模糊不清,難以辨認。如果一個團隊無法就軟體架構進行溝通,那麼就無法設置起點和建立技術領導力。
我建議使用“C4 模型”來進行軟體架構方面的溝通——上下文(Context)、容器(Containers)、組件(Components)和代碼(Code)。其本質是創建一系列結構化、可伸縮的圖表來描述軟體系統。為每一個軟體系統創建一個上下文圖表,用於描述軟體系統與真實世界之間的關係。然後放大系統邊界,讓內部的容器突顯出來——容器就是可部署、可運行的實體,比如運行在瀏覽器上的單頁應用、伺服器端的 Web 應用、微服務、資料庫實例,等等。如果有必要,可以再將每個容器放大,讓容器內部的組件突顯出來。最後,你也可以放大組件,讓代碼級別的元素(類、介面、函數、對象等)也突顯出來。C4 模型獨立於具體的表示方法,雖然我傾向於使用簡單的“方塊和線條”,但使用 UML 來表示也是可以的。
www.4model.com 提供了更多的信息、視頻、示例圖表和工具鏈接。如果你的團隊正糾結於軟體架構溝通方面的問題,那麼可以看看這些資料。
5. 好的軟體架構是敏捷的
現在仍然存在一種誤解,認為“架構”和“敏捷”之間是一種競爭和衝突的關係。但其實不是的。相反,好的軟體架構也是敏捷的,它有助於應對業務變更,不管是需求變更、業務流程變更還是混合變更。當然,什麼才是“好的架構”仍然有待商榷,但我認為,好的架構與好的模塊化息息相關。如果你曾經有過在“大泥球”上進行變更的痛苦經歷,那麼你就會知道,好的代碼庫結構(好的模塊化)是多麼的重要。
現如今,很多團隊都存在一個很大的問題,他們採用了一種叫作“架構中立的設計”,George Fairbanks 在他的“Just Enough Software Architecture”一書中對此進行了描述。換句話說,他們採用了一種不需要考慮權衡因素的架構風格。在現實中,開發團隊使用微服務架構代替單體代碼庫。但實際上,他們有可能是創建出了一種“分散式的大泥球”,可見軟體設計和分解過程是多麼的重要,不管是要構建一個單體還是一個微服務架構的系統。敏捷和好的軟體架構不是那麼容易就能實現的,它需要一些精巧的設計,也需要作出一些權衡。這也再次說明為什麼設置起點和建立技術領導力是如此的重要。
關於 C4 模型的一些解釋
C4 模型是來自 software architecture for developers 一書的定義,指的是 Context 上下文場景、Container 容器、Component 組件和 Classes 類(或者 Code 代碼),意思指一個軟體架構是由這些模型呈樹形結構組成。
關註代碼仍然是大多數軟體開發生命周期中關註的焦點,這是有一定道理,因為代碼是最終交付。但如果你不得不向別人解釋關於系統是如何工作的,你會從代碼開始解釋嗎?
確實代碼並不能講述系統的整個故事,在缺乏文檔的情況下,人們通常會開始在白板上或紙上用圖框和線條解釋系統的主要構建塊是什麼,它們是如何連接的。而使用 Microsoft Visio, Rational Software Architect 或 Sparx Enterprise Architect 等專業工具又比較複雜。
更好的辦法是在不同的抽象層次創建不同的圖 diagram,一個簡單的圖 diagram 比複雜的圖能夠更有效表達描述。下圖是 C4 模型的示意圖:
類 Class: 這是面向對象世界常用, 類是我們系統最小的構建模塊。
組件 Component: 一個組件可以認為是由一個或多個類組成的邏輯組,比如一個審計 audit 組件或授權服務能夠用於決定資源的訪問是否被允許,組件典型地由許多協同類組成。微服務架構可以認為是一種組件。
容器 Container: 一個容器代表組件執行或駐留的地方,這可能是一個Web容器或應用伺服器,也可以是富客戶端應用或資料庫,容器是做為系統一部分啟動的,容器之間通訊是通過遠程介面如 SOAP web service, RESTful interface, Java RMI, Microsoft WCF, messaging等進行, Docker 可以認為是一個這樣的容器。
Context/系統System: 一個系統是一個高層次抽象和代表,一個系統由多個單獨的容器組成,比如財務系統,銀行系統或網站系統等。
以上解釋來自 jdon.com。
相關文章鏈接:
https://www.infoq.com/articles/brown-are-you-a-software-architect
https://www.infoq.com/articles/architecture-five-things
http://www.jdon.com/artichect/c4-model.html