歡迎光臨
每天分享高質量文章

優秀架構師必須掌握的架構思維

介紹

架構的本質是管理複雜性,抽象、分層、分治和演化思維是我們工程師 /架構師應對和管理複雜性的四種最基本武器。

最近團隊來了一些新人,有些有一定工作經驗,是以高階工程師 /架構師身份進來的,但我發現他們大部分人思維偏應用和細節,抽象能力弱。所以作為團隊技術培訓的一部分,我整理了這篇文章,希望對他們樹立正確的架構設計思維有幫助。我認為,對思維習慣和思考能力的培養,其重要性遠遠大於對實際技術工具的掌握。

由於文章內容較長,所以我把它分成兩篇小文章,在第一篇《優秀架構師必須掌握的架構思維》中,我會先介紹抽象、分層、分治和演化這四種應對複雜性的基本思維。在第二篇《四個架構設計案例及其思維方式》中,我會透過四個案例,講解如何綜合運用這些思維,分別對小型系統,中型系統,基礎架構,甚至是組織技術體系進行架構和設計。

在進入正文之前,順便推薦一下我在極客時間開設的《微服務架構實戰 160 講》影片課程,微服務是架構師必須掌握的核心技能,本週五是課程的最後一天優惠期,想訂閱的同學請抓緊最後的優惠機會。

掃碼或點選圖片(Android 使用者)即可訂閱。

抽象思維

如果要問軟體研發 /系統架構中最重要的能力是什麼,我會毫不猶豫回答是抽象能力。抽象 (abstraction)這個詞大家經常聽到,但是真正理解和能講清楚什麼是抽象的人少之又少。抽象其實是這樣定義的:

對某種事物進行簡化表示或描述的過程,抽象讓我們關註要素,隱藏額外細節。

舉一個例子,見下圖:

你看到什麼?你看到的是一扇門,對不對?你看到的不是木頭,也不是碳原子,這個門就是抽象,而木頭或者碳原子是細節。另外你可以看到門上有個門把手,你看到的不是鐵,也不是鐵原子,門把手就是抽象,鐵和鐵原子是細節。

在系統架構和設計中,抽象幫助我們從大處著眼(get our mind about big picture),隱藏細節(temporarily hide details)。抽象能力的強弱,直接決定我們所能解決問題的複雜性和規模大小。

下圖是我們小時候玩的積木,我發現小時候喜歡玩搭積木的,並且搭得快和好的小朋友,一般抽象能力都比較強。

上圖右邊的積木城堡就是抽象,這個城堡如果你細看的話,它其實還是由若干個子模組組成,這些模組是子抽象單元,左邊的各種形狀的積木是細節。搭積木的時候,小朋友腦袋裡頭先有一個城堡的大圖(抽象),然後他 /她大腦裡頭會有一個初步的子模組分解(潛意識中完成),然用利用積木搭建每一個子模組,最終拼裝出最後的城堡。這裡頭有一個自頂向下的分治設計,然後自底向上的組合過程,這個分治思維非常重要,我們後面會講。

我認為軟體系統架構設計和小朋友搭積木無本質差異,只是解決的問題域和規模不同罷了。架構師先要在大腦中形成抽象概念,然後是子模組分解,然後是依次實現子模組,最後將子模組拼裝組合起來,形成最後系統。所以我常說程式設計和架構設計就是搭積木,優秀的架構師受職業習慣影響,眼睛裡看到的世界都是模組化拼裝組合式的。

抽象能力不僅對軟體系統架構設計重要,對建築、商業、管理等人類其它領域活動同樣非常重要。其實可以這樣認為,我們生存的世界都是在抽象的基礎上構建起來的,離開抽象人類將寸步難行。

這裡順便提一下抽象層次跳躍問題,這個在開發中是蠻普遍的。有經驗的程式員寫程式碼會保持抽象層次的一致性,程式碼讀起來像講故事,比較清晰易於理解;而沒有經驗的程式員會有明顯的抽象層次跳躍問題,程式碼讀起來就比較累,這個是抽象能力不足造成。舉個例子:

一個電商網站在處理訂單時,一般會走這樣一個流程:

  1. 更新庫存 (InventoryUpdate)

  2. 打折計算 (Discounting)

  3. 支付卡校驗 (PaycardVerification)

  4. 支付 (Pay)

  5. 送貨 (Shipping)

上述流程中的抽象是在同一個層次上的,比較清晰易於理解,但是沒有經驗的程式員在實現這個流程的時候,程式碼層次會跳,比方說主流程到支付卡校驗一塊,他的程式碼會突然跳出一行某銀行 API遠端呼叫,這個就是抽象跳躍,銀行 API呼叫是細節,應該封裝在 PaycardVerification這個抽象裡頭。

分層思維

除了抽象,分層也是我們應對和管理複雜性的基本思維武器,如下圖,為了構建一套複雜系統,我們把整個系統劃分成若干個層次,每一層專註解決某個領域的問題,並向上提供服務。有些層次是縱向的,它貫穿所有其它層次,稱為共享層。分層也可以認為是抽象的一種方式,將系統抽象分解成若干層次化的模組。

分層架構的案例很多,一個中小型的 Spring Web應用程式,我們一般會設計成三層架構:

作業系統是經典的分層架構,如下圖:

TCP/IP協議棧也是經典的分層架構,如下圖:

如果你關註人類文明演化史,你會發現今天的人類世界也是以分層方式一層層搭建和演化出來的。今天的網際網路系統可以認為是現代文明的一個層次,其上是基於網際網路的現代商業,其下是現代電子工業基礎設施,諸如此類。

分治思維

分而治之 (divide and combine或者 split and merge)也是應對和管理複雜性的一般性方法,下圖展示一個分治的思維流程:

對於一個無法一次解決的大問題,我們會先把大問題分解成若干個子問題,如果子問題還無法直接解決,則繼續分解成子子問題,直到可以直接解決的程度,這個是分解 (divide)的過程;然後將子子問題的解組合拼裝成子問題的解,再將子問題的解組合拼裝成原問題的解,這個是組合 (combine)的過程。

面試時為了考察候選人的分治思維,我經常會面一個分治題:給你一臺 8G記憶體 /500G磁碟空間的普通電腦,如何對一個 100G的大檔案進行排序?假定檔案中都是字串記錄,一行約 100個字元。

這是一個典型的分治問題,100G的大檔案肯定無法一次載入到記憶體直接排序,所以需要先切分成若干小問題來解決。那麼 8G記憶體的計算機一次大概能排多大的資料量,可以在有限的時間內排完呢?也就是 100G的大檔案要怎麼切法,切成多少份比較合適?這個是考察候選人的時間空間複雜度估算能力,需要一定的計算機組織和演演算法功底,也需要一定實戰經驗和 sense。實際上 8G記憶體的話,作業系統要用掉一部分,如果用 Java開發排序程式,大致 JVM可用 2~4G記憶體,基於一般的經驗值,一次排 1G左右的資料應該沒有問題(我實際在計算機上乾過 1G資料的排序,是 OK的)。所以 100G的檔案需要先切分成 100份,每份 1G,這樣每個子檔案可以直接載入到記憶體進行排序。對於 1G資料量的字串排序,採用 Java裡頭提供的快速排序演演算法是比較合適的。

好,經過有限時間的排序(取決於計算機效能,快的一天內能排完),假定 100個 1G的檔案都已經排好了,相當於現在硬碟上有 100個已經排好序的檔案,但是我們最終需要的是一個排好序的檔案,下麵該怎麼做?這個時候我們需要把已經解決的子問題組合起來,合併成我們需要的最終結果檔案。這個時候該採用什麼演演算法呢?這裡考察候選人對外排序和歸併排序演演算法的掌握程度,我們可以將 100個排好序的檔案進行兩兩歸併排序,這樣不斷重覆,我們就會得到 50個排好序的檔案,每個大小是 2G。然後再兩兩歸併,不斷重覆,直到最後兩個檔案歸併成標的檔案,這個檔案就是 100G並且是排好序的。因為是外排序 +歸併排序,每次只需要讀取當前索引指向的檔案記錄到記憶體,進行比較,小的那個輸出到標的檔案,記憶體佔用極少。另外,上面的演演算法是兩路歸併,也可以採用多路歸併,甚至是採用堆排序進行最佳化,但是總體分治思路沒有變化。

總體上這是一個非常好的面試題,除了考察候選人的分治思維之外,還考察對各種排序演演算法(快排,外排序,歸併排序,堆排序)的理解,計算的時間空間複雜度估算,計算機的內外存特性和組織,檔案操作等等。實際上能完全回答清楚這個問題的候選人極少,如果有幸被我面到一個,我會如獲至寶,因為這個人有成長為優秀架構師的潛質。

另外,遞迴也是一種特殊的分治技術,掌握遞迴技術的開發人員,相當於掌握了一種強大的程式設計武器,可以解決一些一般開發人員無法解決的問題。比方說最近我的團隊在研發一款新的服務框架,其中包括契約解析器 (parser),程式碼生產器 (code generator),序列化器 (serializer)等元件,裡頭大量需要用到遞迴的思維和技術,沒有這個思維的開發人員就乾不了這個事情。所以我在面試候選人的時候,一般都會出遞迴相關的程式設計題,考察候選人的遞迴思維。

大自然中遞迴結構比比皆是,如下圖,大家有興趣不妨思考,大自然透過遞迴給我們人類何種啟示?

演化思維

社群裡頭經常有人在討論:架構是設計出來的?還是演化出來的?我個人基於十多年的經驗認為,架構既是設計出來的,同時也是演化出來的,對於網際網路系統,基本上可以說是三分設計,七分演化,而且是在設計中演化,在演化中設計,一個不斷迭代的過程。

在網際網路軟體系統的整個生命週期過程中,前期的設計和開發大致只佔三分,在後面的七分時間裡,架構師需要根據使用者的反饋對架構進行不斷的調整。我認為架構師除了要利用自身的架構設計能力,同時也要學會藉助使用者反饋和進化的力量,推動架構的持續演進,這個就是演化式架構思維。

當然一開始的架構設計非常重要,架構定系統基本就成型了,不容馬虎。同時,優秀的架構師深知,能夠不斷應對環境變化的系統,才是有生命力的系統,架構的好壞,很大部分取決於它應對變化的靈活性。所以具有演化式思維的架構師,能夠在一開始設計時就考慮到後續架構的演化特性,並且將靈活應對變化的能力作為架構設計的主要考量。

當前,社群正在興起一種新的架構方法學~演化式架構,微服務架構就是一種典型的演化式架構,它能夠快速響應市場使用者需求的變化,而單塊架構就缺乏這種靈活性。馬丁·福樂曾經在其部落格上給出過一張微服務架構的演化路線圖 [附錄 8.2],可以用來解釋設計式思維和演化式思維的差異,如下圖所示:

上面的路線是一開始就直奔微服務架構,其實背後體現的是設計式架構的思維,認為架構師可以完全設計整個系統和它的演化方向。馬丁認為這種做法風險非常高,一個是成本高昂,另外一個是剛開始架構師對業務域理解不深,無法清晰劃分領域邊界,開發出來的系統很可能無法滿足使用者需求。

下麵的路線是從單塊架構開始,隨著架構師對業務域理解的不斷深入,也隨著業務和團隊規模的不斷擴大,漸進式地把單塊架構拆分成微服務架構的思路,這就是演化式架構的思維。如果你觀察現實世界中一些網際網路公司(例如 eBay,阿裡,Netflix等等)的系統架構,大部分走得都是演化式架構的路線。

下圖是建築的演化史,在每個階段,你可以看到設計的影子,但如果時間線拉得足夠長,演化的特性就出來了。

如何培養架構設計思維

良好的架構設計思維的培養,離不開工作中大量高質量專案的實戰鍛煉,然後是平時的學習、思考和提煉總結。

另外,基本的架構設計思維,其實在我們大學計算機課程(比如資料結構和演演算法)中可以找到影子,只不過當時以學習為主,問題域比較小和理想化。所以大學教育其實非常重要,基本的架構設計思維在那個時候就已經埋下種子,後面工程實踐中進一步消化和應用,隨著經驗的積累,我們能夠解決的問題域複雜性和規模逐漸變大,但基本的武器還是抽象、分層和分治等思維。

我認為一個架構師的成長高度和他大學期間的思維習慣的養成關係密切。我所知道世界一流的網際網路公司,例如谷歌等,招聘工程師新人時,對資料結構和演演算法的要求可以用苛刻來形容,這個可以理解,谷歌級別公司要解決的問題都是超級複雜的,基本思維功底薄弱根本無法應對。

對於工作經驗<5年的工程師新手,如果你大學時代是屬於荒廢型的,建議工作之餘把相關課程再好好自學一把。個人推薦參考美國 Berkeley大學的資料結構課程 CS61B[附錄 8.1]進行學習,對建立抽象程式設計思維非常有幫助,我本人在研究生階段自學過這門課程,現在回想起來確實受益匪淺,註意該課程中的所有 Lab/Homework/Project都要實際動手做一遍,才有好的效果。

我當年自學的是 CS61B 2006秋季版的課程,上圖是課程 Logo

對於演化設計思維,當前的大學教育其實培養很少,相反,當前大學教育大都採用脫離現實場景的簡化理想模型,有些還是固定答案的應試教學,這種方式會造成學生思維確定化,不利於培養演化式設計思維。我個人的體會,演化式設計思維更多在實際工作中透過實戰鍛煉和培養。

結論

  1. 架構的本質是管理複雜性,抽象、分層、分治和演化思維是架構師征服複雜性的四種根本性武器

  2. 掌握了抽象、分層、分治和演化這四種基本的武器,你可以設計小到一個類,一個模組,一個子系統,或者一個中型的系統,也可以大到一個公司的基礎平臺架構,微服務架構,技術體系架構,甚至是組織架構,業務架構等等。

  3. 架構設計不是靜態的,而是動態演化的。只有能夠不斷應對環境變化的系統,才是有生命力的系統。所以即使你掌握了抽象、分層和分治這三種基本思維,仍然需要演化式思維,在設計的同時,藉助反饋和進化的力量推動架構的持續演進。

  4. 架構師在關註技術,開發應用的同時,需要定期梳理自己的架構設計思維,積累時間長了,你看待世界事物的方式會發生根本性變化,你會發現我們生活其中的世界,其實也是在抽象、分層、分治和演化的基礎上構建起來的。另外架構設計思維的形成,會對你的系統架構設計能力產生重大影響。可以說對抽象、分層、分治和演化掌握的深度和靈活應用的水平,直接決定架構師所能解決問題域的複雜性和規模大小,是區分普通應用型架構師和平臺型 /系統型架構師的一個分水嶺。

課程推薦

我在極客時間開設的《微服務架構實戰 160 講》影片課程已進入最後四天優惠期,現在訂閱即享雙重福利:

福利一:限時優惠價¥199,原價 ¥299(5 月 19 日恢複原價),新使用者還可享受 30元立減優惠。

福利二:每邀請一位好友購買,你可獲得 36 元現金返現,同時好友可獲得 15 元現金返現。多邀多得,上不封頂,立即提現(提現流程:極客時間公眾號 – 我的 – 現金獎勵提現)

如何訂閱

iOS 使用者訂閱方式

掃描下方二維碼或者點選閱讀原文,支付後即可成功訂閱。

Android 使用者訂閱方式

直接點選下方小程式卡片,微信支付後即可成功訂閱。

「閱讀原文」,試看或訂閱本課程。

參考

  1. Berkeley CS61Bhttp://datastructur.es/sp17/

  2. 單塊優先https://www.martinfowler.com/bliki/MonolithFirst.html

贊(0)

分享創造快樂