剛剛大幅度裁員的Uber文章:軟體架構被高估,清晰和簡單的設計被低估 - Gergely Orosz

banq發表於2019-09-19

我在設計和構建大型系統方面獲得了公平的份額。我參與了重寫Uber的分散式支付系統,在Xbox One上設計和釋出Skype以及開源RIB,Uber的移動架構框架。所有這些系統都經過了徹底的設計,經歷了多次迭代,並進行了大量的白板和討論。然後,這些設計歸結為一份設計檔案,在我們開始建造之前,該檔案已經傳閱以獲得更多反饋。
所有這些系統規模都很大:數百名開發人員構建它們 - 或者在它們之上 - 它們為每天數百萬人使用的系統提供支撐。他們也不只是綠地專案。支付系統重寫必須取代現有的兩個支付系統,由數十個系統和數十個團隊使用,所有這些系統都沒有任何業務影響。重寫Uber應用程式是一個專案,幾百名工程師同時工作,將現有功能移植到新架構。
讓我先從一些可能聽起來令人驚訝的事情開始。首先,這些設計都沒有使用任何標準軟體架構規劃工具。我們沒有使用UML,也沒有使用4 + 1模型ADRC4也沒有使用依賴關係圖。我們建立了大量的圖表,但沒有一個遵循任何嚴格的規則。只是簡單的舊框和箭頭,類似於描述資訊流這一個概述類結構和元件之間的關係。同一設計文件中的兩個圖表通常具有不同的佈局,並且經常由不同的工程師新增和修改。
其次,擁有該設計的團隊中沒有架構師。沒有IT架構師企業架構師。沒錯,優步和Skype /微軟都沒有放手軟體架構師的職位。高階工程師,如工程師,預計仍會定期編碼。對於所有專案,我們確實有經驗豐富的工程師參與。但是,沒有人擁有該架構或設計。雖然這些經驗豐富的開發人員推動了設計過程,但即使是最初級的團隊成員也參與其中,通常會挑戰決策並提供其他討論的替代方案。
第三,我們幾乎沒有參考常見的架構模式和常見軟體架構文獻中引用的其他術語,例如Martin Fowler的架構指南。沒有提到微服務,無伺服器架構,應用程式邊界,事件驅動架構等等。其中一些確實在頭腦風暴期間出現。但是,沒有必要在設計文件中引用它們。

科技公司和創業公司的軟體設計
那我們怎麼做的呢?為什麼我們不遵循眾所周知的軟體架構方法所建議的方法?
我和其他科技公司FANG(Facebook,亞馬遜,Netflix,谷歌)以及小型初創公司的同行工程師進行了討論。大多數團隊和專案 - 無論大小 - 都採用了類似的設計和實施方法:

  1. 從業務問題開始。我們想要解決什麼?我們試圖建立什麼產品?為什麼?我們如何衡量成功?
  2. 頭腦風暴的方法。與團隊一起並透過多個會話,找出可行的解決方案。保持這些頭腦風暴小。從較高的水平開始,降到較低的水平。
  3. 白板你的方法。讓團隊聚集在一起,讓一個人制定團隊融合的方法。您應該能夠在白板上清楚地解釋系統/應用程式的體系結構,從高層開始,根據需要深入探討。如果你對這個解釋有困難,或者說不夠清楚,那麼細節上還需要做更多的工作。
  4. 根據您在白板上的說明,透過簡單的文件和簡單的圖表來編寫它。將行話保持在最低限度:您甚至希望初級工程師瞭解它的含義。使用清晰易懂的語言書寫。在優步,我們使用類似RFC的文件和基本模板。
  5. 談論權衡和替代方案。良好的軟體設計和良好的架構都是為了做出正確的權衡。沒有設計選擇本身的好壞:這一切都取決於背景和目標。您的架構是否分為不同的服務?提到為什麼你決定不使用一個大型服務,這可能會帶來一些其他好處,比如更直接,更快速的部署。您是否選擇使用新功能擴充套件服務或模組?權衡構建單獨服務或模組的選擇,以及該方法的優缺點。
  6. 在團隊/組織內傳播設計文件並獲得反饋。在優步,我們曾經向所有工程師傳送所有軟體設計檔案,直到我們大約有2,000人。現在我們變得更大,我們仍然非常廣泛地分發它們,但我們已經開始更多地平衡訊號/噪聲比。鼓勵人們提問並提供替代方案。務實設定合理的時間限制來討論反饋並將其納入需要的地方。可以在現場快速解決直接的反饋,而更詳細的反饋可能更快地在現場解決。

為什麼我們的方法與軟體架構文獻中通常提到的方法不同?實際上,對於大多數架構指南而言,我們的方法原則上並沒有那麼不同。幾乎所有指南都建議從業務問題開始,概述解決方案和權衡:這也是我們的工作。我們不做的是使用許多架構師或架構書籍所倡導的許多更復雜的工具。我們使用最簡單的工具:Google Docs或Office365等工具,儘可能簡單地記錄設計。

(banq注:如果文字可以簡單記錄設計,那麼需要那麼多單詞字母幹啥?文學作品幹嘛能寫那麼多廢話?文字的問題在於其瑣碎細節,圖形的區別在於其抽象,協助理解。這麼做的危害是無法讓新人更快加入複雜的專案,因為一地雞毛啊,太難了。這大概也是Uber裁員的一個原因,人員冗餘,新人加入無法形成生產力。)

我認為我們方法的主要區別歸結為這些公司的工程文化。高度自治和層次分明是科技公司和初創公司所共有的特質:對於更傳統的公司而言,有時候不那麼真實。這也是這些地方在流程驅動設計中採用更嚴格的規則進行更多“基於常識的設計”的原因。

我知道銀行和汽車公司,開發人員在沒有進入鏈條的情況下積極勸阻他們做出任何架構決策,從幾個級別的架構師那裡獲得簽約,他們正在監督幾個團隊。這成為一個較慢的過程,架構師可能會被許多請求所淹沒。因此,這些架構師使用常見文獻中描述的更多工具,建立更正式的文件,希望使系統更加清晰。這些檔案也強化了一種自上而下的方法,因為對於不是架構師的工程師來說,使用正式方法質疑或挑戰已經記錄的決策更加令人生畏,他們並不精通。所以他們通常不會這樣做。公平起見,這些公司經常希望最佳化開發人員更多的可交換資源,允許他們在短時間內重新分配人員來處理不同的專案。不同的工具在不同的環境中工作得更好也就不足為奇了。

簡單,無框架的軟體設計超過架構模式
設計系統的目標應該是簡單。系統越簡單,理解起來就越簡單,找到問題就越簡單,實現它就越簡單。描述的語言越清晰,設計就越容易理解。避免使用團隊中每個成員都不理解的術語:經驗最少的人應該能夠同樣清楚地理解事物。
(banq注:DDD統一語言,不要形成不同人的行話,如果有行話就要統一定義)

乾淨的設計類似於乾淨的程式碼:它易於閱讀且易於理解。編寫乾淨程式碼有很多好方法。但是,您很少會聽到有人建議您開始在您的程式碼中應用Gang of four設計模式。清潔程式碼從單一責任,明確命名和易於理解的約定開始。這些原則同樣適用於清晰的架構。
(banq注:好像還是注重架構設計,清潔架構 單一職責屬於軟體架構,只是用程式碼替代文件說話,但是圖形化的文件還是有作用的,有利於新的設計師快速掌握原有系統的設計路徑,發現方向性問題,否則會形成一個自閉的自以為是的軟體架構,軟體架構只要你編寫程式碼就會自然形成,關鍵是如何更容易讓別人理解)

那麼架構模式的作用是什麼?我認為它們在編碼設計模式方面同樣有用。他們可以為您提供有關如何改進程式碼或架構的想法。對於編碼模式,當我看到一個模式時,我會注意到一個單例模式,當我看到一個充當外觀的類時,我會抬起眉毛並深入挖掘,只進行呼叫。但我還沒有想到“這需要一個抽象的工廠模式 ”。事實上,我花了很多時間來理解這個模式的作用並且讓我的“啊哈!” 在使用大量依賴注入之後 - 這是少數幾個領域之一,這種模式實際上很常見且很有用。我也承認,雖然我花了很多時間閱讀和理解四人幫設計模式,但他們對成為一名更好的編碼器的影響要小於我從其他工程師那裡得到的反饋。
同樣,瞭解常見的架構模式也是一件好事:它有助於縮短與人們的討論,他們以與您相同的方式理解他們。但架構模式不是目標,它們不能替代更簡單的系統設計。在設計系統時,您可能會發現自己意外地應用了一個眾所周知的模式:這是一件好事。之後,您可以更輕鬆地參考您的方法。但你要做的最後一件事就是採用一種或多種架構模式,將其用作錘子,尋找釘子來使用它。
在工程師觀察到在某些情況下如何進行類似的設計選擇之後,架構模式就誕生了,並且這些設計選擇也是使用類, 然後選擇命名,記錄下來,並進行廣泛討論。架構模式是解決方案解決後出現的工具,希望能讓其他人的生活更輕鬆(如何更容易讓別人理解)。作為一名工程師,您的目標應該是更多地解決解決方案並透過它們進行學習而不是選擇閃亮的架構模式,希望這將解決您的問題。

更好地設計系統
我聽說很多人都在尋求有關在架構和設計系統方面做得更好的建議。一些有經驗的人會建議閱讀有關架構模式和閱讀有關軟體架構的書籍。雖然我絕對建議閱讀 - 特別是書籍,因為它們提供的內容比短篇帖更深 - 我有一些建議,更多的是動手而不僅僅是閱讀。

  • 拉隊友在白板前面討論你的設計方法。制定你正在做的事情以及為什麼要做事。確保他們理解。當他們這樣做時,請求他們的反饋。(banq注:白板確實可以快速形成設計結果,但是這樣的設計結構能否經得起推敲,或者是否雙方陷入一個坑而沒有意識到,多年以後,人們尋找原因時,無法重新當年你們在白板面前決定這樣設計的原因了,當然創業公司通常倒閉得快,沒有多年以後的假設)
  • 將您的設計寫在一個簡單的文件中,並與您的團隊分享,並徵求反饋意見。無論你正在做多麼簡單或複雜的事情,可能是一個較小的重構或大型專案,總結一下。以對你有意義的方式和其他人可以理解的方式做到這一點 - 為了靈感,這就是我在Uber看到它的方式。以允許評論的格式與您的團隊分享,例如Google文件,Office365或其他。讓人們新增他們的想法和問題。(banq注:文件如果能簡單就無法說清楚,如果說清楚了就無法簡單,這是文字這種語言形式的缺陷,否則需要數學幹嘛呢?)
  • 設計兩種不同的方式,並對比兩種設計。當大多數人設計一個架構時,他們採用一種方法:拍腦袋想出來的。但是,架構不是黑白的。請想出第二個可以工作的設計。對比這兩者,解釋為什麼一個比另一個好。簡要列出第二個設計作為考慮的替代方案,爭論為什麼決定反對。(banq注:短時間一天內能想出兩個方案,這樣的人是天才,不是普通人)
  • 明確你做出的權衡,為什麼要做出這些權衡,以及你為之最佳化的內容。要明確存在的約束,並且必須考慮到這些約束。
  • 回顧其他人的設計。做的更好。假設您擁有一種文化,人們透過白板和會議或文件分享他們的設計,那麼請從這些評論中獲得更多。在評審期間,大多數人只是試圖接受,成為單向觀察者。因此,他們會要求澄清不清楚的部分的問題。向他們詢問他們考慮過的其他替代方案。問他們他們採取了什麼樣的權衡以及他們假設的約束。扮演魔鬼的擁護者並提出另一個可能更簡單的選擇 - 即使它不是一個更好的選擇 - 向他們詢問他們對你的建議的看法。即使你沒有像設計它那樣考慮設計,你仍然可以增加很多價值並學到更多東西。(banq注:類似DDD事件風暴)

最好的軟體設計簡單易懂。下次你開始一個新專案,不是思考:“我將如何構建這個系統,我應該使用哪些經過實戰考驗的模式以及我應該用哪種正式方法記錄它?” ,想想“我怎麼能以一種容易讓任何人理解的方式提出最簡單的設計?”。(banq注:模式與架構正是讓別人理解的通用解決方案,如果你採取特殊的解決方案,那更不容易讓別人理解,需要理解你的方案與通用模式方案的區別,你自己都沒有發現區別,別談別人了)
軟體體系結構最佳實踐,企業體系結構模式以及描述系統的形式化方法都是有用的工具,有朝一日可能會派上用場。但是在設計系統時,請從簡單開始,儘可能保持簡單。儘量避免更復雜的架構和正式工具本身引入的複雜性。(banq注:從簡單開始是天性,沒有誰願意一開始為難自己,但是危險在於,自以為從簡單開始就是正確的,堅持從簡單開始,最後搞複雜了,如果複雜情況可以被人的強迫症改變,世界上就真簡單了)

相關文章:

uber/cadence:Cadence是一種分散式,可擴充套件,持久且高度可用的流程編排引擎
Cadence是一個好東西,可惜很多人認為學習曲線比較高,文件比較難理解,這大概就是Uber的特色
 

相關文章