開頭先來個小故事:張三是一個程式設計師,在金九銀十的季節去了一家新公司就職。新的公司看起來前景不錯,做的產品也屬於行業前沿,張三發誓自己要在此一展鴻圖,用自己精湛的開發技術為公司的上市添磚加瓦。
張三就職的第一天,公司就開放了程式碼的許可權,他熟悉起公司的核心專案。結果卻驚呆了,張三發現公司的專案就像是一個垃圾場,各種程式碼堆成山,而他要做的事情,就是去維護這些老專案,在那一刻,張三內心的幻想瞬間破滅。
但在維護了一段時間專案之後,事情出現了轉機。有一天,新專案下來,老闆任命張三為負責人,他內心狂喜,終於可以證明自己了。
"我一定要讓程式碼顯得優雅,跟爛程式碼說再見。"
剛開始,張三用了各種設計模式,瘋狂抽象業務,越做越有勁,感覺一身的才學終於有了展示的機會。但專案是多人合作的,隨著時間的流逝,和專案的不斷迭代,很多新人不再按照預定的規範來開發程式碼。
為了方便,微服務如雨後春筍般一個個往外面冒,開發人員在程式碼裡填充了一個又一個if語句。於是,張三開始手動地限制那些不符合規範的程式碼提交。可是專案時間的壓力越來越大,張三最終迫於交付壓力又放開了限制。雖然專案順利的交付完成,但是奇怪的程式碼卻永久地留在了專案中。
慢慢地,原始精美的設計開始變得越來越臃腫,邏輯變得複雜無比。沒有人敢去重構,也不可能重構了。終於,張三實在無法忍受,辭職去了一家新公司就職,新的公司看起來前景不錯,做的內容也是行業前沿的產品,張三再次發誓自己要在新公司一展鴻圖,用自己精湛的開發技術為公司的上市添磚加瓦...
這樣的故事在網際網路行業內一遍一遍地上演,似乎任何專案隨著時間演進,一個個補丁打到最後都會變成“屎山型”專案,充斥著各種歷史遺留問題,新功能開發越來越慢,最終無法演進走向專案的終結。有些網際網路公司會為延長專案的生命週期,在某個節點聘請資深的軟體架構師,他們往往熟讀《重構》,用各種各樣的技術手段去延緩這個過程。
最近我在網上衝浪的時候發現了一個叫做"產品架構"的概念,再結合曾經做過的一個個專案,突然有了些許感悟。
研發人員習慣用技術解決問題,但問題的解法是多樣的,有時候只需換一個度切入。當然,無論用什麼方法,歸根到底,都是人的問題,這裡只是提供一種思路,僅供參考。
產品架構是啥
像軟體架構一樣,產品設計也是有架構的。
在做專案的時候,我們覺得從技術上,所有的問題都能得到解決,但是整個專案卻在不知不覺間一步步的走向“屎山型”專案。按照研發的思維,問題的根源是抽象還不夠,技術水平不行,需要更強大的架構師來重構。
聘請了資深的軟體架構師後,一開始專案似乎變得好了一些,但最終結果並沒有發生改變,只是延緩了而已,到了某個階段也只能拋棄,重新開始。
覆盤後會發現,我們的主要精力都在解決技術上的問題,而忽略了產品層面。按照網上的一種說法,產品架構就是在充分理解產品使用者需求基礎上對產品資料流轉的邏輯梳理。
而我對產品架構的理解是從"理念世界"開始的。程式設計是用計算機能夠理解的語言來描述現實事物,計算機能夠理解的語言是什麼?是邏輯。在程式設計的時候,研發人員需要在腦海中構思出事件的全貌,並且用邏輯的語言將它描述出來。
在西方的哲學裡面有一個"理念世界"的說法,大概意思是人們做的任何事情,都是在腦海中預先構建出事物的本體,再到現實中對預先構建的內容進行模仿。這與我們程式設計的過程很相似,那麼產品是否也遵循這個過程?
回想起以前做專案時的思考方式,發現確實如此,我們或多或少都需要在腦海中構建出產品的執行軌跡。但是在做專案的時候,作為研發的我們都在想如何用技術解決問題,卻忽略了更重要的東西,任何產品都是為了解決客戶的問題而存在,解決客戶的問題是根本,無論用什麼手段......
如何設計產品架構
在設計之前,先解決人的問題,什麼樣的人適合做產品架構?
產品架構就是在充分理解產品使用者需求基礎上對產品資料流轉的邏輯梳理。
所以這個人需要具備以下素質:
- 能夠調研並理解使用者需求的能力
- 能夠知道產品的核心價值
- 能夠理解產品執行原理
- 面向物件設計思維
有了這些素質,就可以開始構建"理念世界"了。
構建理念世界
構建"理念世界"其實就是將現實中將要發生的事情,用面向物件設計思維將事情轉換成純粹的邏輯描述,這個過程叫抽象。
舉個例子,如果我們需要做一個流量治理型別的產品,抽象過程大概是這樣的:流量治理基本分為2個大的內容,流量監控和流量管理,這是核心價值。
而傳統的流量治理工具基本都是採用SDK的方式實現,它們普遍具有以下的問題:
- 侵入性強
- 治理功能不全
- 內容多、門檻高
- 中介軟體演變困難
- 版本碎片化嚴重
- 升級成本高
如果能解決此型別的問題,將會使得服務網格在流量治理解決方案上會優於SDK的方式,這是比較優勢。
有了上面的分析,可以得出:如果希望產品可以快速升級且侵入性弱,勢必不能與客戶的程式碼進行強繫結,需要一種與語言無關,又能夠做到流量監控,流量管理的手段,只能去作業系統上面找。
如果能操縱作業系統上的某些功能,使得流量在進入服務之前,先進入編寫的程式中,就做到了語言無關。
思路大概是這樣:一個請求進來,先被作業系統轉發到編寫的程式中,然後我們自己編寫的程式會將資料上報到某個東西儲存起來,最後程式轉發到真正的服務中,流量監控就做完了。同時,還需要一個用於儲存上報資料的東西,它需要具備持久化的能力。
在這個流程當中,使用了一種設計模式,叫sidecar模式,就用sidecar稱呼我們自己編寫的程式好了,儲存的那個就叫資料庫。
接下來推導一下流量控制的邏輯,要做到流量控制,需要用到sidecar,畢竟流量已經被作業系統轉發到了sidecar上面,我們可以做過處理之後再轉發到真正的服務當中。那麼就需要一個另外的東西,它來告訴sidecar要怎麼對流量進行處理,畢竟每個sidecar需要處理的東西是不同的,而且策略內容需要持久化,不然找不到與sidecar的對應關係,這個東西叫做控制端。
所以流程大概變成:控制端配置流量控制策略,控制端將策略下發到sidecar上,一個流量請求過來,被操縱系統轉發到sidecar,sidecar先上報流量資料到資料庫,然後根據流量策略對流量進行處理,最後將請求轉發到真正的服務中。
在完全理想的狀態下,透過這樣一個流程,基本實現了流量治理的核心能力,並且這個流程相比SDK的方式更具有優勢,這就是所謂"理念世界"的構建過程,純粹的邏輯描述。
驗證理念世界
"理念世界"是否正確的唯一衡量標準是它是否完全正確的描述了現實,就像面向物件思維裡面的類和物件的關係,"理念世界"是對現實的抽象。
要想知道抽象的好不好,有一個非常有效的辦法。隨便找幾個人,把你的邏輯說一遍,如果表述的過程是順暢的,對方能夠理解並且沒有感覺到邏輯上的遺漏,這個抽象就是比較好的。
在做專案的時候,可以把這個過程儘量的描述給不同崗位的人,一邊加深團隊成員對產品的理解,一邊又透過不斷的表述來完善這個流程沒有考慮完善的內容。
如何落地
當"理念世界"被建立,就需要在現實中對它進行模仿,在軟體工程學當中,這一步就要開始脫離設計,到實操的階段。一般專案分2類,一類是從零開始,一類是存量專案。
從零開始的專案
從零開始的專案在動手之前,一般會面臨2個問題,從哪開始?要模仿到什麼程度?
透過流程可以發現以下是一切的基石。
1.操縱作業系統上的某些功能,使得流量在進入服務之前,先進入我們編寫的sidecar中
2.sidecar
3.資料庫
所以在沒有外部特殊情況干擾的時候流量監控功能肯定要優先於流量控制功能做,這是從哪開始。
至於做到什麼程度主要依託於時間,人員的關係,看實際情況把握。但無論做多少,只要方向是對的,對整個 產品的迭代都是具有正向的意義。
透過這張圖,服務劃分變得很清楚,在交給研發時,每個服務的邊界也有明確的規定。就算研發人員出現新入職或者水平良莠不齊的現象,在這個框架內所能造成的破壞力也有限,不會對整個產品造成結構性的問題,在未來的某個時候只需要找一個足夠強的研發重新寫一遍,問題就都解決了。
存量專案
存量專案的落地就十分的複雜,歷史遺留害人不淺......
大的思路應該是先用"抽象"映照現實,看看到底現在的程式碼是否完全符合"抽象"的"流程",先搞清楚現狀再想辦法修枝剪葉。
如果有新的需求到來時,還是要先抽象,任何正當的需求都是符合邏輯的,如果抽象出來不符合邏輯,那肯定是需求挖掘的不夠,不能盲目的加程式碼。
還是那個例子,如果需要新增一個對sidecar的監控,那流程就會變成這樣。
但是監控單獨拎出來是否有必要?如果沒有必要的話流程可以變成這樣。
這2種形態沒有優劣之分,可以結合具體情況做選擇。
總結
如果有了解到服務網格領域的朋友應該很早就發現,上訴說的例子就是一個弱雞版Istio的誕生。
我嘗試著從需求出發,純粹的邏輯推導Istio的架構。很多有名的開源專案為什麼歷經這麼多年,反而越來越精煉,這裡面一定有值得探討的地方。
本文只是提供一種解決問題的方法,解決問題的核心還得看人,一群大佬,無論用什麼方法做出來的東西都精美而優雅。