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

什麼樣的軟體架構是好的?

 

“All models are wrong, some models are useful” ——George Box
沒有放之四海皆準的好與壞的標準。下麵我對於衡量軟體架構好壞的AAA原則:
  • 可考核(Accountable):好的軟體架構讓每個團隊都有自己負責的業務標的

  • 可自主(Autonomous):好的軟體架構讓每個團隊都一定的自主性可以獨立往前跑,而不總是被其他團隊阻塞

  • 可復用(Amortized):好的軟體架構鼓勵對未來投資,使得基礎設施的成本可以被攤銷

 

可考核>>可自主>可復用。在上世紀90年代,代碼復用是面向物件社區的熱門話題。然後SOA和DDD又來告訴我們“可自主”才是最重要的。但是我發現實踐中,無論是“可自主”還是“可復用”都很模棱兩可。很難用這兩個原則去說服其他人,用X的方式來分解問題會比用Y的方式來分解問題更好。但是如果你說,這麼分解可以讓每個團隊更可考核,就顯得特別理所當然。

 

開發者無法估算工作量

 

“可考核性”是一切的關鍵。我認為“缺乏可考核性”是現在的軟體開發樣式最大的危機,這個問題比”無法管理所謂的複雜性“還要更嚴重。
開發者是無法估算工作量在行業里也不算什麼秘密了。這帶來了很多根本性問題:
  • 因為我們無法知道真正多少人才是必須的,所以中層管理總是比著招聘人頭上限,盡可能的加人。為什麼會這樣做?很簡單,他們的薪酬和他們所管理的人頭數是成正比的。

  • 把軟體重構得”更可維護“沒有商業價值。什麼叫可維護性?問題如果解決不了,扔更多的人進去總是可以解決的。軟體工程又不是造火箭,能有多難?根本無法證明重構可以節省多少人力,因為就沒有可對標的重構前的應投入人力。

要解決這個問題,我認為不是去搞明白開發工作量的評估的魔法。恰恰相反,如果我們和業務負責人是以同一個團隊的方式來工作,我們就壓根不需要去估算工作量。每個軟體開發團隊都有應該有“唯一的一個”對應的業務團隊,業務團隊背什麼樣的OKR,技術團隊就背什麼樣的OKR。要讓團隊可考核,最重要的是只對一個業務負責。

上面是一個典型的組織架構圖。每個小團隊的OKR,要和其上一級團隊的OKR對齊。OKR裡面的關鍵產出要是可度量的,才能讓每個團隊真正對某個事情負責。
典型的壞的軟體架構是這樣的:有大量的微服務團隊。業務負責人總是需要直接去找多個微服務團隊才能達成他的標的。每個需求都需要和多個不同的軟體團隊重覆溝通。每個技術團隊都沒法清楚地說明白他們以及他們的微服務負責的業務標的是什麼。正因為如此,技術們無法說清楚自己對業務到底有什麼價值。
讓我們再強調一遍:軟體架構的“頭號標的”應該是讓每個分解出來的團隊都能夠有業務標的去負責。

 

Bounded Context

 

在大的尺度上,架構就是分解Bounded Contexts(參見領域驅動開發,DDD)。這就是把業務的組織架構圖體現到軟體的世界里:
以電商領域為例,業務被分解為上面這些Bounded Contexts。沒有一個技術團隊可以改寫橫跨這些Bounded Contexts的業務流程的。這並不是啥壞事情,大的問題被分解為了小問題,業務和技術在一個Bounded Context的範圍內,攜手朝著共同的標的去努力。

 

虛擬空間和智慧體

 

一個Bounded Context對於一個團隊來說仍然太大了。至少在微服務的心智下是這麼認為的。如何把它進一步分解為更可管理的小塊呢?我的模型是“虛擬空間和智慧體”。我們做為程式員所做的事情,簡單來說就兩個:
  • 虛擬空間

  • 有點智慧的“機器人”和我們人類一起在虛擬空間里交互

虛擬空間和我們肉身所處的物理空間是一樣的,它都是構建在因果關係上的。有兩種法則主導這些因果:
  • 自然法則:大自然自身的內在規律

  • 社會法則:一個人造的體系,人們通過模仿自然法則創造出類似穩定的規則系統去構建穩定的社會秩序

比如引力是自然法則。而“借錢要還”是社會法則。兩者的工作方式是類似的,給定某些前因,根據法則,就必須有某些後果。我們使用C/C++/Java/GO/……等來描述這些法則。從光線跟蹤演算法到word文本編輯器到電商交易平臺,從構建規則的角度來說是差不多的。“法則”必須是靜態的可預測的,就像用水泥構建了我們的真實世界一樣。
在我們構建的虛擬空間智商,我們作為人類彼此之間進行交互,例如社交網絡和交易。由人類扮演的角色正逐步被我們縮寫的人工智慧的”機器人”所替代。例如,之前是人工的編輯去挑選內容,現在可能是機器人來產生新聞,給你準備每天開屏的首頁。“機器人”正變得越來越複雜,某天他們會從虛擬空間里出來,直接走向物理空間。
“虛擬空間”和“機器人”這兩種軟體代碼的工作方式差異性是很大的。“虛擬空間”從原因推匯出結果,來維護自然和社會的秩序。“機器人”的工作方式是相反的,它收集事實反推出模型來最大化其標的。把智慧的部分和系統的其他部分明確地區分出來至關重要。我們作為人類希望規則是靜態的從而構建出穩定的預期。如果“法則”總是不斷在變,“虛擬空間”看起來就像是“魔法空間”,它就變得和我們從真實空間獲得的生活體驗很不一樣了。
軟體開發中的Model,View,Controller(MVC)的概念可以用來解釋“虛擬空間”。人類和“機器人”是所謂的智慧體。Model根據自然和社會法則定義的因果去維護資料的完整性。View和Controller提供了便捷的接口給人類和“機器人”去交互。

 

所有權==著作權

 

“虛擬空間”這部分仍然太大了。業務流程可能會有很多個步驟,例如:

而且不同的Bounded Context的業務流程之間也是有集成關係的:

可考核性問題的根源是編程語言里缺乏對完整因果鏈的直接描述能力。我們可以在白板上畫一個清楚的業務流程圖,但是在寫代碼的時候就不需要切分成很多細碎的服務和函式來表達。之所以工作流引擎總是被拿出來考慮,因為它的描述能力和要解決的問題有良好的映射。但是BPMN並不是一種編程語言。
步驟與步驟之間有很強的因果關係。在產品詳情頁展示的促銷,也應該體現在購物車裡,也應該體現在收銀頁面上,也應該體現在最終的收據里。我們使用的“function”的概念,頂多只能用來描述500ms內發生的事情的因果關係。對於前面所述的業務流程,我們切分成了很多個步驟,同時又按照使用方的不同,切成成了很多個面向用戶的服務。從而因果關係就被隱藏在這些龐雜的實現細節之中了。軟體跑起來就像一場接力賽,一個服務把職責接過來,搞一搞之後,又傳遞給另外一個服務。理想的情況是,代碼本身就應該體現流程圖,讀起來就像流程圖。
更糟糕的是,現在的切分方式並沒有明確的劃線的原則。這就頻繁導致了團隊之間關於誰應該負責什麼的爭論。高度政治化的組織氛圍導致了開發者情緒上的沮喪。同時,具有諷刺意味的是,在大家彼此搶活的同時,又因為職責切分得太碎,導致又沒有一個團隊能夠對全域性負責。
對於解決這個問題,目前能夠做到的“最佳實踐”就是在一堆微服務團隊上架一個門麵團隊。“所有權==著作權”,我們只願意對自己所寫的東西負責。這個人性,無法改變。為了給這些可憐的家伙具有所有權的感覺,我們必須允許一層很薄的代理層,或者叫所謂的調度服務來把微服務給“屏蔽”在後面。但是這種代理一層的做法經常導致了很低的團隊自主性。
理想的編程語言,應該能夠提供“function”一樣的東西去直接描述業務流程。業務上的同時行進的併發流程應該可以像多執行緒編程一樣,用訊息傳遞的方式來描述。這樣,我們可以給每一個可切分出來的業務流,分配一個獨立的軟體團隊去端到端負責。他們可以對自己負責的事情100%負責。這些人和業務運營人員,以及編寫出來的“機器人”合在一起作為同一個團隊,共同負責這個業務流的收益和虧損。而不是單獨把技術摘出來,成為一個共享的成本中心。

 

協作單元

 

除此之外,還有一個事情是有問題的。之前由編程語言提供的模塊化單元,例如assembly/package/class這些,就是我們團隊之間彼此協作的單元。然而現在不是這樣了。現在越來越多的人,要求軟體模塊有獨立版本,能夠獨立的部署。因為這樣才能支持多個團隊的獨立性。這就導致了大量的微服務的做法。
但是我們是否“總是”需要用不同的編程語言不同的工具來實現微服務?語言的差異和彼此割裂的工具導致跨團隊溝通更加困難。你可以擁有你的流程,擁有你的服務,但是這不阻礙你和你的伙伴們用同一門語言啊。一門編程同時扮演了3個角色:它連接了機器,它連接了開發者,它同時又連接了團隊。今天編程語言更多是僅僅作為一種連接機器和開發者個體之間的工具,團隊之間宏觀上是彼此割裂的。
解決方案應該是把軟體作為一個整體來思考,而不是被狹隘的“操作系統行程”的視角給限制了。構建新的微服務的成本,應該和後臺用function啟動一個執行緒沒有多大區別。理想的編程語言里,我們有各種各樣的function,但是執行機制不同。
原文鏈接:https://zhuanlan.zhihu.com/p/46372932
赞(0)

分享創造快樂