云原生集成開發(fā)環(huán)境——TitanIDE
通過網(wǎng)頁在任何地方更安全、更高效地編碼2022-10-31
906
原文出自:公眾號“分布式實驗室”
首先,本文不是想介紹架構設計一步一步如何做,細節(jié)的技術手段,完整的理論框架這些問題。這些問題在一篇文章中也不可能覆蓋。本文更多時候是想給很多從細節(jié)設計中走過來,對什么是架構設計只有過一些模糊的,不成形想法的工程師,建立一些基本的認識,理解架構設計的必要性,以及如何看待很多具體的技術對這種必要性的幫助。
從信息論的角度,本文不是要提供新的信息,而是要幫助讀者梳理已經(jīng)擁有的信息。這恰恰也是架構設計的作用:架構設計不是要取代設計,而是在整理設計的組織,讓設計的力量最終指向目標。
以我個人的經(jīng)驗,剛剛開始進入架構設計的工程師,常常對架構設計的整個認識都是錯誤的,這些錯誤的認識會讓他們越走越遠,甚至最終破壞架構。這是本文希望提供的幫助。我希望通過這些思路上的幫助,讓我們身邊的工程師更多從架構的角度考慮問題,因為沒有這樣的文化氛圍,我們很難真正合作起來,也無法讓我們多個技術可以持續(xù)發(fā)展和積累下去,更無法面對未來的挑戰(zhàn)。
我在架構上的很多經(jīng)驗,源自對自己設計過程的反思,以及對后進的工程師的指導,所以在介紹的過程中不免流露一些“好為人師”的感覺,我并非覺得自己就比聽眾們高明,只是如果我不用這樣的描述方法,我的講述就會變成一些經(jīng)典教材那樣——它里面說的東西都是對的,但聽眾沒有從中獲益。這更非我的本意。
什么是架構設計
架構設計是一個非常抽象的概念,從不同的角度有不同的理解。我們先從一個比較高的角度來抽象一下這個問題。我們用畫畫來做個類比,這樣比較直觀。在畫畫的時候,如果我們要畫一個人,我們不會一開始就把眼睛的全部細節(jié)畫出來:
因為這樣不一定能和我們要畫的整個人對得上:
如果我們要畫的整個人的姿態(tài)是下面這幅圖的樣子的,上面那個眼睛整個都是錯的,因為角度就不對。
軟件和硬件的設計同樣存在這樣的問題,一個軟件,一個硬件,或者一個包含軟件硬件的產(chǎn)品,包含非常多的細節(jié),如果我們一開始就開始“畫眼睛”,那么很可能我們經(jīng)過一個很長的開發(fā)周期,最后發(fā)現(xiàn)我們做錯了。
比如你花了無數(shù)的功夫對每個模塊進行存儲優(yōu)化,把運行內(nèi)存的需求壓縮到只有1M,結果最后發(fā)現(xiàn)內(nèi)存在這個設備中的成本只占0.1%,你這些工作就白干了。這還只是浪費工作量,可能你設計一個復雜的加密手段,但加密后你的設備就不能運行用戶自己的軟件了,你這個產(chǎn)品也就廢了。
畫家可以從一個細節(jié)看到一個整體,比如,專業(yè)的畫家可能從上面那個眼睛,就能意識到這個人是正面對著觀察者的視角的,但不一定是坐著還是站著,說不定他還能從眼睛的放松程度,能知道這個人不是躺著。
一個系統(tǒng)架構師也能從一個產(chǎn)品的特定細節(jié)看到這個產(chǎn)品的全體。比如一個芯片構架師可以從系統(tǒng)總線協(xié)議猜到芯片的加工可能用到的制程,進而猜到這個芯片可以實現(xiàn)的最大內(nèi)存帶寬。一個軟件架構師可以從某個API產(chǎn)生了對“設備”這個概念的關聯(lián),從而知道使用這個API的帶寬會被限制在一個設備之內(nèi),無法被Scaling。
所以,構架設計工作是一種“形而上”的工作。架構師用細節(jié)控制整體。好比畫家用線條控制整個人。架構的描述語言并非它表面表述的嚴格意思,它是用這個細節(jié)去反映某個整體的打算。當架構師說某個API應該是什么樣的,和具體實現(xiàn)的工程師眼中的這個API本身是什么樣的,兩人的著眼點是不同的,具體實現(xiàn)的工程師僅僅是為了解決這一層面把參數(shù)傳遞過去的問題。而架構師設計一個API,他的目的是在這個位置上設計一個“約束”,導致其他細節(jié)設計在這個位置上被限制住,最終不會偏離整個設計目標。
架構上說某個API是get(int),我們可能不在乎實施的時候變成get(int, int)或者增加一個get2(int, void *),因為實施這些修改的成本不高(后面我們講關聯(lián)的時候再來討論這個問題),我們說get(int)只是保證這個地方會有一個“接口層”,具體一兩個變化,并不重要。
但如果這個設計上下文是在關注一組已經(jīng)交付的二進制軟件,這個就是大的變化,因為這時任何一點變化,都會導致整個接口和原來不一樣。這就是形而上設計的特征,它不再具有形而下那種“器”的特點,在器這個角度覺得重要的東西,在它這里不一定重要,反過來,在器這個層面覺得不重要的東西,在它這里可以很重要。因為兩者指向的設計目標是不同的。
深入一點說,這就是《道德經(jīng)》中說的名和道的區(qū)別?!暗馈笔前考毠?jié)的一個整體,而“名”是我們抽象出來的一個特征?!懊庇肋h都不會包含“道”的全部細節(jié)。我們設定一個約束,我們說XXX(...)都可以,這表示了無數(shù)的變數(shù),最后我們就沒法交流了。所以我們用了一個“名”,一個形而下的器,一個“具體情形”,來描述這個東西“大致”是這樣的,你把它理解為“器”,非要認為它“就是這樣”的,這樣就把自由度都做沒了,你就失去做架構的作用的。
很多管理者希望把架構工作做成工具,或者把架構過程做成“條條框框”,“最佳實踐”。但架構工作恰恰就是不能這樣干的,因為架構本來就是發(fā)明條條框框的方法,是發(fā)現(xiàn)某個具體情形下,能否設定,如何設定條條框框的一個過程。
在架構設計的過程中,新的約束不斷被發(fā)現(xiàn)和發(fā)明,主要矛盾會變成次要矛盾,架構提取的“名”也會隨之不同,進而策略也要跟隨變化,跟隨變化就是架構這個工作存在的原因。如果你希望在架構設計之前就設定固定的方法,那么架構就無法發(fā)揮我們引入架構設計這個工作原本想起到的作用了。
也就是說,架構師和具體實現(xiàn)工程師設計的東西看起來很可能是完全一樣的,但他們的設計目標可以是完全不同的。就如同上面的兩幅素描,可能架構師和實現(xiàn)工程師都會畫“眼睛”,但架構師關心的是“整個人是什么樣的,眼睛的位置和角度是在這個地方”,實現(xiàn)工程師關心的是“知道眼睛在這個地方和這個人的年齡和心理狀態(tài)后,眼睛的睫毛如何表達,深度,陰影如何刻畫”。而且,在實現(xiàn)工程師具體去設計以后,架構圖上的那些線,是要逐步消隱的。
說起來,我這里寫的這個提綱,也是一種“架構”:我的演講90分鐘,包含更多的細節(jié),但我怎么保證我的演講可以聚焦,并完整傳遞一個邏輯給聽眾?我就需要寫一個更短的邏輯,在這個短邏輯中保證我的表述是自洽的。否則我可能絮絮叨叨90分鐘,其實什么東西都沒有傳遞出去。而有了這個框架,我中間借題發(fā)揮,舉很多的例子,深入講某個例子的細節(jié),都不會偏離我要講述的主題。
從架構這個角度說,我的描述如果不能對準同一個主題,這個“產(chǎn)品”整體就不呈現(xiàn)有效的“功能”。
具體對于每個架構設計,對于不同層次的架構設計,我們可能有不同的方法來“繪制”(這個整體總結),但基礎原理都是這樣的:用粗線條先勾勒總體邏輯。
作為“形而上”的設計,架構設計的給人的感覺沒有那么瓷實,但架構設計仍是一種設計,它不是脫離邏輯而存在的。我在很多的架構評審或者分析會上,會聽到這樣的說法:這個地方說得不清楚,我們后面有詳細介紹,如果您關心,我們跳到后面去給您講?
這樣說就是不懂設計了,用上面那張人體架構圖來說,我跟你說你這個人的框架沒有設計好,你說我們來看看眼睛?——我不看眼睛,我就要在這層抽象上看到邏輯通了——這才是設計。設計就必須有邏輯鏈。否則架構設計就沒有意義了,我們還不如直接設計細節(jié)。
架構設計是下圖示意的一個連續(xù)的過程:
本節(jié)小結:理解架構是一種形而上的邏輯非常重要,因為架構語言中說的一個東西不是那個東西本來的意思,而是對細節(jié)的預判和無數(shù)經(jīng)驗的總結。所以我們必須理解,沒有足夠的細節(jié)經(jīng)驗,是不能成為架構師的。這種經(jīng)驗甚至不一定是某種細節(jié)設計的經(jīng)驗,而是對細節(jié)反饋的經(jīng)驗。
約束,關聯(lián)和邏輯自洽
作為形而上的設計,我們要理解架構,就需要有足夠高的抽象思維能力。這一點能力,在座的各位,應該都是有的。因為我們這么多年的教育,本來就是在教這個能力,所以每位大學生畢業(yè)生都應該有這個能力。我要提出這一點,是要避免各位在我們后面討論抽象邏輯的時候覺得我說得太玄,或者覺得自己還沒有這部分知識,要先去“學習”一下才開始深入思考我討論的問題,這樣我就無法把我的觀點傳遞給你們了。
如果各位(unlikely)是混文憑出來的,我沒有什么辦法。但我想大部分的人,可能僅僅學了很多具體的推理方法,沒有有意識去這些推理可以被“抽象”為形而上的邏輯。我想提醒各位的是:不要被這些抽象的概念嚇住了,其實這些東西你本來就懂的。
從形而上的角度來說,我們通過“邏輯”進行預判和交流。所有的“邏輯”,本質上是約束的引入。比如,我們說“你肯定餓壞了,來,吃點面包”。這個邏輯設定了一個判斷上的約束:“你餓了”。如果這一點不成立,這整個邏輯就不成立。你認定了“你餓了”這個約束,你的“設計”——“吃點面包”——才是成立的。設計需要有約束才能進行設計。
我們做任何一個設計,都必然來自一個約束。就算你寫一個“Hello World”,你都引入了一個“約束”:在我運行這個程序的時候,在屏幕上出現(xiàn)點有規(guī)律的東西,證明我們能控制這個系統(tǒng)。
我們在白紙上畫一個人,它也有一個約束:“畫個人”。畫個人是我們后面做所有的事情的基礎,我們不是畫貓畫狗,不是畫正弦曲線和坐標系。有些約束我們甚至不一定會注意它:比如我們是用筆來畫它的,不是用刀子來刻它的。但這個無法深究,因為我們關注的東西總是有限的。我們關注的是,我們建起一個邏輯鏈,可以說:“因為要這樣,所以我這樣了”,我們這里提到的“要這樣”是什么。
“畫個人”是我們的約束,這個人坐著還是站在,是我們的“自由”,但我們選擇了一個“自由”,我們就增加一個約束了:如果我們決定讓這個人坐著,這個人的是手和腳的距離就被約束了。整個“畫人”的過程,本質上是不斷增加約束的過程,當這個“人”被畫好了,所有的約束就變成了“事實”,不可改變了。
在我們這個討論空間中,它是“最高約束”,因為你也不能改變它了。架構設計,是管理這個約束加入的過程,因為先引入的約束,會控制我們后面引入的約束。由于整個實施的時間線很長,我們要避免不受控制的約束增加過程,導致后面我們怎么都無法加入剩下的邏輯,最后這個目標就達不到了。
這里理念從“函數(shù)式編程”的角度特別好理解,參考:https://zhuanlan.zhihu.com/p/173631835。架構設計就是函數(shù)帶參時的情形,細節(jié)設計就是Curry化的過程,每個細化就是消除一個參數(shù)維度,收窄整個自由空間。
f本身是對自由度的一個約束(圖中曲面的范圍),當我們收窄它其中一個維度(比如把z收縮為4,甚至可以是某個范圍),剩下的邏輯就會簡單,但自由度也就更低了。
用畫人來類比的話,我們先約束整個人的“姿態(tài)”和環(huán)境光源的特點(點光源還是面光源等)和位置,我們就決定了眼睛,手腳的姿態(tài),透視和光影了,這樣畫眼睛和手腳的時候,我們知道如何刻畫細節(jié)。但如果我們先畫眼睛和手腳,各自有自己的姿態(tài)和對光源的理解,這個眼睛和手腳放到一起,這就不像是個人了,這個“畫人”的目標就永遠不能達成了。
這種一個約束,控制了其他約束的情形,在架構的語言中,就稱為“關聯(lián)”。關聯(lián)就是說,如果我修改了一個邏輯的“約束”,其他邏輯的約束也會跟著更改,那么,這兩個邏輯,就存在“關聯(lián)”。否則,我們就認為他們沒有“關聯(lián)”。
關聯(lián)不是我們一般工程師想象的那樣,互相有函數(shù)調用,有消息通訊就叫關聯(lián)(這些只是關聯(lián)的一種)。關聯(lián)是個哲學的概念,常常出現(xiàn)在語義上的,比如提升速度的要求,導致應用方法的改變,介質層和會話層也有關聯(lián)。我們關注某些東西有沒有關聯(lián),我們關注的是在我們討論的那個邏輯角度,我們是否在乎它們的“共同修改”。
協(xié)議分層,就是一種典型的分離關聯(lián)的方法。比如TCP/IP的網(wǎng)絡(IP)和鏈路(link)層,IP層只知道IP地址,反正我告訴你我要發(fā)到這個IP地址去,其他東西我一概不知,所以你用令牌環(huán)還是Ethernet層我的邏輯都是通的(約束是IP層接口),無論你是UDP還是TCP通訊,都和MAC地址無關,我也不知道你在傳輸數(shù)據(jù)的時候需要有一個Token在介質上分發(fā)。
但丟開這些信息不管,只要你能在link層上向我保證每個數(shù)據(jù)報是無損的(但可丟失),基于這個約束,我就有足夠的“依賴”(其實就是約束的別名)來建立我的邏輯了,我可以和對端用端口區(qū)分應用,可以用滑動窗口來保序來防丟失,可以用特定的原語進行連接建立。這都是看我要把某些約束放在我這一層,還是放在別人那一層。而決定這一點的,是有哪些重疊的約束,我們通過分解多個獨立的邏輯鏈,保證每個邏輯鏈的約束都不多,這樣我們保證這個邏輯鏈的自洽的成本最低。
分層以后,下層多一個“路由”的概念,不會改變高層原來那些“握手”,“鑒權”這些概念,下層和高層在各自的“約束”和“依賴”中可以獨立構成完整的邏輯,而不需要每次都把邏輯細分下去。
架構設計本質是對約束和關聯(lián)的控制,讓不同的“目標”承載在不同的邏輯上,減少跨邏輯的關聯(lián)。比如你當然可以把“低功耗控制”這個目標放到TCP層,但耗電多少這個約束是在物理層手上的,你要建立這個邏輯鏈,就要從物理層拿到這個約束,TCP和物理層的“關聯(lián)”就加重了。
但如果你完全把低功耗放在物理層,TCP的流被分散在每個SerDes鏈路上的,物理層對此無能為力,它也沒法把功耗降下來。這樣,我們就可能需要一個Channel的抽象(我這里只是比喻,不是現(xiàn)實),讓IP“僅”知道合并一些數(shù)據(jù)流有助于功耗的降低……
這個整個設計過程,脫離具體的具象就架構設計談架構設計,根本沒有結果,我們之所以這樣分解模塊、約束和關聯(lián),完全看我們面對的具體約束是什么。這里,起關鍵作用的,是我們的“目標”,也就是那個“畫人”的根本約束。除了這個根本約束,其他的約束都是設計者自己引入的。我們要避免作繭自縛,就必須不斷對比這個“目標”,看看什么真的來自這個“目標”,哪些只是我們圖建邏輯的方便,自己強行引入的。所以,如果你沒有學會其他深入的架構方法,那就保證你學會兩點:
第一,永遠把你的原始目標,放在你的設計的最前面。時時刻刻對比你是否針對了這個目標進行了設計。
第二,無論你做什么層面的抽象,保證你的邏輯在這個層面上邏輯自洽。換句話說,任何時候,都要問:我這個邏輯,是否是在我設定的約束和條件下,最好的選擇,是否所以可能發(fā)生的情形都被考慮到了。后面一點是基礎,這解決你的邏輯是否有破綻,你做一個get(int)的函數(shù),這個int所有可能的取值,都應該在你的考慮范圍內(nèi),而不是僅僅考慮int>0的情形。但另一方面,int>0這個約束同樣可以來自你高層約束,而不是來自這個變量的自然約束。
前面說過,我們架構設計的作用,就是降低每個獨立設計邏輯的依賴和難度。而這個難度,就在這里這個“邏輯自洽”上。你基于IP這個抽象做TCP這個協(xié)議,下面到底是Token Ring還是CSMA/CD,你完全不用管,你的邏輯鏈要窮舉所有的可能性就是比較容易的,否則你根本無法保證你的邏輯鏈是嚴密的,因為要窮舉的可能性太多了。
如果再考慮技術發(fā)展(比如現(xiàn)在SSD存儲很貴,明年技術進步,整個成本變了呢?),工程師的能力逐步提升,開發(fā)階段和銷售階段的要求不同,行業(yè),政策等態(tài)勢的變化,你就會發(fā)現(xiàn),做一個“嚴密”的邏輯鏈,是非常非常困難的事情。我們只是在降低風險,不是在找一種“必然”,但沒有這種基本的降風險設計,說要做成一個產(chǎn)品,完全是瞎扯蛋。
本節(jié)總結:我們要保證一個設計是設計,必須首先保證這兩點:對準目標,邏輯自洽。不能保證這兩點,你的所謂設計就只是夢游,還不如直接進行形而下的具體設計。而且,這還不僅僅是浪費時間,而是引入無效約束以后,完全限制了整個構架的的發(fā)展。
DFD/STD建模原理
DFD/STD方法是軟件發(fā)展早期,存量約束很少的時代的產(chǎn)物,現(xiàn)在用它的人已經(jīng)比較少了。我們可以不用,但它包含的原理其實是非常重要的,對于我們建立構架思想,或者在做具體的模塊級的設計仍是必須掌握的基礎能力。
前面說過,構架設計本質上是找到核心約束(目標),然后基于這個目標引入后續(xù)的約束。那么,對于計算機系統(tǒng),它的核心約束是什么呢?
答案是:把一種形態(tài)的信息,轉化為另一種形態(tài)的信息。
· 播放電影的一種實現(xiàn)是把視頻編碼轉化為顯存數(shù)據(jù)和音頻數(shù)據(jù)
· 客戶習慣學習是把用戶的購買和瀏覽信息,加上商品的分類轉化為用戶的興趣商品分類
· 電梯控制是把多個不同層的上下請求轉化為電梯的運動和停止控制信號
· ……
這是計算機作為一種“信息系統(tǒng)”的唯一作用。
除此以外,沒有其他核心的控制要素。
電影編碼一定要H.264嗎?一定要VC-1嗎?對用戶來說不關心,關鍵是能把視頻數(shù)據(jù)轉化為圖像。圖像一定要用電視嗎?一定要用液晶屏嗎?也不是核心約束,你可以再選。唯有把視頻變成看得見的東西,才是核心約束。
客戶習慣學習用戶的購買信息需要用網(wǎng)絡傳輸嗎?還是直接把硬盤連過來拷貝?還是到了晚上夜深人靜的是時候InfiniBand同步?這都是自由度,不自由的是你總得把客戶看過的商品,看了多久,用的IP地址或者ClientID給我,這我才能從中提出這個興趣出來。
這是DFD方法的核心。DFD方法是從這個角度來設計約束的:用戶要我把什么轉化為什么?我有足夠的數(shù)據(jù)進行這種轉化嗎?不夠的時候,我從哪里補上這些數(shù)據(jù)?這種轉化的邏輯,可以分成多少個獨立的邏輯?這些邏輯可以分別留在哪些層次、模塊里面獨立管理?
這就會產(chǎn)生DFD圖,所有數(shù)據(jù)邏輯都通了,剩下的邏輯就都是“我擁有這幾個數(shù)據(jù),如何轉化為他們要的那幾個數(shù)據(jù)”的問題了,這整個就是個數(shù)學問題。
應該說,我們大部分時候做架構最好的進展,就是能把一個問題變成一個數(shù)學問題,因為這樣這個問題就可以做到最嚴密了。比如下面提到的狀態(tài)機問題,就是典型的數(shù)據(jù)問題提取,如果我們能建立這個模型,基本上我們就不怕有什么錯了。但真正讓人害怕的是比如指令集,虛擬化這種設計,狀態(tài)和條件無數(shù),幾乎就沒有數(shù)學方法來完整判斷我們做的是不是就真的沒有破綻了。
而狀態(tài)機方法是DFD方法之外一個完全獨立的方法。一般用來處理接口破綻的:DFD建模完成后,你就要設計外部接口,而外部接口是否可靠呢?你只分析了你這樣提供功能是可以給用戶返回正確的結果的?但是否有情形導致你的輸出是不對的?用STD方法你可以窮舉所有可能的輸入和你當時所處的狀態(tài),這樣你對你的邏輯鏈是否有效就比較有把握了。
DFD和STD是脫離所有進一步“自由”之外的核心約束。它和你用什么語言啦,怎么分模塊啦,接口是消息還是調用啦,這些人為約束沒有任何關系,你愛怎么設計就怎么設計。
這種在現(xiàn)在這個“后軟件時代”是不太合適的,現(xiàn)在的軟件太完善了,你決定選擇用MySQL來存數(shù)據(jù),你就得接受用一個X Protocol來連接它,選定了X Protocol,你就要選語言,就得選OS平臺,然后你的輸入就得滿足關系數(shù)據(jù)庫來描述你的持久化數(shù)據(jù)……在系統(tǒng)層面,現(xiàn)在你的依賴都是成片成片的。這個時候,你還紙上談兵地說“我的核心依賴是……”就很假了,你的物理依賴其實一開始就已經(jīng)被決定了,這時自由度更高的4+1視圖方法就更容易被接受了。
但即使我們有4+1視圖方法,我們?nèi)杂斜匾煤萌W習一下DFD/STD方法。因為這是4+1方法的基礎,它仍是我們整個信息系統(tǒng)真正的核心約束的提取方法,比如前面這個問題,MySQL真的不滿足我們的需要,我們可以換掉MySQL,換掉關系型數(shù)據(jù)庫,換掉OS的,這是左右我們創(chuàng)新的基礎,4+1是下一層的方法,它接受了“人為約束”是約束,不考慮打破這個約束,但DFD方法是真正在控制一個“期望”(用戶需求)如果被自由設計的時候,可以如何創(chuàng)新,如何改變現(xiàn)在的約束。
4+1視圖建模原理
4+1視圖是后軟件時代的產(chǎn)物,就是軟件已經(jīng)極度豐富了,你隨便做點什么,都是在已有的軟件的基礎上做的,而且常常你還不能一次想好怎么做,都是見一步,走一步的。這需要另一種控制架構的方法。
4+1視圖是把最關鍵4個全局控制拿出來,然后一個功能,一個功能拿上去推演,看約束和邏輯會不會沖突。所以它不叫“五大視圖”,因為Use Case不算一個完整的邏輯。Use Case只是一個持續(xù)補充的,不完整的“需求列表”。我們用這些單個的需求去試試,我們的引入的設計邏輯,是否是可以完整自洽的。這個“完整自洽”是要落實在另外那四個視圖上的。
4大視圖在關注設計的哪些方面呢?首先,邏輯視圖,我又把它稱為概念空間建模,這其實關注的是用戶接口。所以我有個建議:如果你的邏輯抽象能力不那么強,就先別去學那么多復雜的方法,你直接試試寫用戶手冊。
你想辦法用真心服務客戶的態(tài)度,給使用者說明怎么用你這個系統(tǒng)。真心服務客戶的態(tài)度不是讓你學電商那些機器人一樣的客服,態(tài)度一流,就是不給你解決問題。真心服務客戶是把客戶當戰(zhàn)友,戰(zhàn)友的陣地守不住,你也一樣死。這樣你才會深怕他聽不懂,而不是故意用你那些專業(yè)術語在他面前裝逼。
概念空間建模很多時候不需要詳細到用戶手冊這個層次,比如我這里這個文檔也是概念空間建模:https://zhuanlan.zhihu.com/p/150489110
我重點抓住的是一個異構的程序在原來Linux對同構的程序在進程線程管理,內(nèi)存占用,異常和中斷處理,調試等問題上是否還有原來的意思。這如果你還分不出哪些概念才是左右發(fā)展的,那些是細節(jié),那么用戶手冊是最容易實施的控制概念空間的方法。
你要介紹一個數(shù)據(jù)庫,什么是用戶,密碼,連接,數(shù)據(jù)庫,表,行,列,條件,index……你自然是要說清楚的,這個東西不通,你的代碼怎么可能可以通?
你要介紹一個加速器,什么是設備,虛擬設備,上下文,通道,引擎,請求,響應,同步,異步……這些你不用心說清楚,你怎么可能說得明白請求你一個虛擬設備復位,會影響多少個應用程序?
這個設計是躲不過去的。如果你這個邏輯沒有說清楚,直接就做設備初始化,軟件上下文分配,中斷處理,等你把這些功能都細化起來,你跟我說你能保證邏輯不沖突?你開玩笑吧?
第二個我們關注的視圖是開發(fā)視圖,這是開發(fā)和維護的組織。最基礎的一個模型是部件分解。前幾天我評審了一個硬件設計,要求在總線上設計一個“地址分配器”,我問,你這個分配器工作在哪里?他說,可以在總線交換機上,也可以在其中一個服務器上。
我就說,這就是兩個交付了:在總線交換機上,這你要求總線交換機有一個CPU,可以跑這個程序,這個系統(tǒng)的OS應該是RTOS,我們就要做RTOS的選型,這個分配器必須和這個RTOS綁定升級,而在每個節(jié)點上那個,必須是一個節(jié)點應用,很可能是一個服務器OS的Daemon或者內(nèi)核模塊。后者我們有自由度可以頻繁升級,前者不行。兩個都支持就要用短板做約束,這個地址分配算法必須相對穩(wěn)定……開發(fā)視圖就是抓這種邏輯的。
但部件分配僅僅是開發(fā)視圖最容易的部分。現(xiàn)代大型商業(yè)軟件這個部分最難的是這些部件的升級和組合關系:一個系統(tǒng)包含多個部件,把維護時間拉長到幾年,每個部件都會發(fā)生升級,升級以后是否可以互相匹配?版本數(shù)量減少,用戶升級自由度降低,版本數(shù)量增加,維護成本大力增加,修改一個Bug,要測試120種可能組合,每個測試先要加載12個小時網(wǎng)絡才能運行起來,你怎么玩?
這個問題常常是我在架構設計中工作量最大的部分,很多架構師碰到這個問題就退了,就開始“抽象”了,忽略版本,用一條虛偽的線和抽象的框框來代表這些變體,實際情形就是到時誰要得急就做誰的,等到最后展開無數(shù)組合的時候發(fā)現(xiàn)搞不定了,就只能解釋“就是這樣的”了。所以你看到很多產(chǎn)品只能撐住POC,為了性能可以換個kernel,換個編譯器,換個庫,“性能提升30%,支持A功能,B功能……”,其實這種市場轉眼就會丟失,根本沒法維護。復盤的時候說:“都是因為用戶不肯用我某個版本……”,扯吧,你整個交付邏輯就不通。
比如這種:
這種圖形是市場部用來和小白客戶溝通的,你拿來當“設計”?你設計什么了?為了讓市場人員可以吹這個牛,架構師是要把所有可能的版本組合全部推演出來,變成開發(fā)部的工作量的。市場吹一句話,是開發(fā)部幾百人月的投入,你架構師也他么只吹一句話?那怎么可能可以處理這些組合呢?結果肯定是只能有一個組合可以用,其他組合都純YY么。
這種把市場吹的分層邏輯,變成一組版本和版本直接的配套關系,就是開發(fā)視圖要解決的關鍵問題。
第三個視圖是處理視圖。這個模型一般用來分析并行化,一個業(yè)務邏輯,有些邏輯是必然串行的,你加CPU,加節(jié)點,加加速器是沒有用的。這種東西,你總得合并在一個流中。還有些業(yè)務不是這樣的,你如何分解邏輯?哪部分分解到什么節(jié)點上?
這是個純算法問題,我這里倒沒有什么可以補充的。但可以看到,它其實也是一個比較核心的抽象邏輯,和需求強相關,受人為引入約束的關系也是比較有限的(當然沒有DFD那種約束那么硬,因為它不是個功能問題,而是個性能問題)
這個視圖一般沒有什么工具,我自己做出來大部分時候都是ER圖(ER圖其實可以畫成對象圖的)和大批的文字說明。
最后一個視圖是部署視圖。我個人對這個視圖用得不多,因為一般前面三個模型已經(jīng)完全限制這個視圖的選擇了,這其實沒有設計的必要。當然,這完全看你進程做的是什么設計,對于比如“數(shù)據(jù)中心建設”這樣設計來說,部署視圖的價值就會大于開發(fā)視圖。
可以看到,4+1視圖方法其實是一種學術上不那么嚴格的實用方法,但它卻是我們進行一個大型系統(tǒng)需要考慮問題的最基本約束考量。否則,想想你可以如何規(guī)整和邏輯完整地考量你一個設計到底缺少了哪一環(huán)?怎么能確定你的系統(tǒng)可以持續(xù)用下去?
對于每個具體的設計,可以你會使用其中一部分視圖,或者你會引入其他視圖,比如可靠性設計,安全性設計,這些都需要額外的視圖來表達的。視圖本質是一個獨立的角度,保證我們最開始要解決的問題:某些問題,一開始進入細節(jié),我們必然會走偏,會留下巨大的破綻(安全性是最典型的情況)。
總結
架構的目的是在混沌中制造規(guī)律,使我們可以控制龐大復雜的系統(tǒng),自然發(fā)展的東西總是混沌而沒有規(guī)律的,好比一個樹林,肯定是看不到一點平地的,而人控制自然,就會磨平這種復雜性,會制造平直的地面,見方見圓的房子,這樣人的腦子可以對它們有很簡單的預期。簡單是設計的目的,復雜是“專業(yè)”的無可奈何。這時很多從設計進入架構的工程師意識不到的問題。
在本文中,我們初步為讀者點出架構設計的關注重點是什么,這一點我認為比掌握一些具體的工具使用方法重要得多。作為形而上的設計,方向錯了,完全起的就是反作用。我希望通過本文,能讓更多的工程師感受到架構設計的重要性,在進行設計的時候,總從架構的角度做一些建模。
如果你實在覺得頭緒太多,那就從用戶手冊開始,至少先抽象出來,你在一個什么上下文中中,對外的依賴是什么,你提供了什么功能……你看到了整體,你才能看得到你的細節(jié),否則你總在你的細節(jié)中出不來,這終究是走不遠的。
這個前提,首先其實你是的心確實是在這個設計上,而不是給你的同事,領導“證明”你不差,你很厲害,不是你的錯誤,你沒有功勞也有苦勞……這些小聰明,能幫你一時,終究不能幫你做成真正的難事。人生苦短,去日苦多,你終究會后悔的。
CloudOS —— 關注應用架構設計的本質
現(xiàn)代大型商業(yè)軟件架構設計最難的,是這些部件的升級和組合關系:一個系統(tǒng)包含多個部件,把維護時間拉長到幾年,每個部件都會發(fā)生升級,升級以后是否可以互相匹配?版本數(shù)量減少,用戶升級自由度降低,版本數(shù)量增加,維護成本大力增加,修改一個Bug,要測試120種可能組合,每個測試先要加載12個小時網(wǎng)絡才能運行起來,請問你怎么玩?
這就是為什么 CloudOS(一站式云原生開發(fā)平臺) 如此重視架構設計的原因。
kaiyun開云創(chuàng)新 CloudOS (一站式云原生開發(fā)平臺) 支撐應用的全生命周期管理,包括需求、架構設計、編碼、測試、部署、運維、服務治理;在架構設計上采用微服務、模塊化、可插拔模式,并提供開放 API。靈活、開放的軟件架構可以滿足企業(yè)的多種應用需求。
在架構設計方面:
· 支持以應用開發(fā)為中心,對系統(tǒng)服務架構進行組件化設計和編排,通過拖拽的形式快速搭建應用;
· 復雜的軟件架構、服務間調用和依賴關系一目了然。
高度將企業(yè)研發(fā)流程標準化:
· 形成開發(fā)模板和任務分發(fā)機制,通過開發(fā)模板把企業(yè)常用的規(guī)范進行打包,架構師設計好整體架構后分派任務給不同開發(fā)組;
· 形成API統(tǒng)一管理能力并制定相關測試用例,定義好每個服務接口的API規(guī)范及相關測試用例,對下游開發(fā)成果進行強約束;
· 模塊研發(fā)人員以接口規(guī)范為開發(fā)契約,甚至不需要知道最終服務于何類業(yè)務。
了解CloudOS更多內(nèi)容,請下載《CloudOS云原生技術解決方案白皮書》