資料結構而非演算法是程式設計的核心 - theartofmachinery

banq發表於2019-07-10

這是2006年Linus Torvalds的一句話

我是圍繞資料設計程式碼的一個巨大的支持者,我認為這是git相當成功的原因之一......事實上,我會聲稱一個糟糕的程式設計師和一個好的程式設計師區別:他是否認為他的程式碼或他的資料結構更重要。糟糕的程式設計師擔心程式碼。優秀的程式設計師擔心資料結構及其關係。


這聽起來很像埃裡克雷蒙德2003年的“代表規則”

將知識摺疊成資料,因此程式邏輯可以是愚蠢和健壯的。


這就是他對1989年Rob Pike這個想法的總結:

資料占主導地位。如果您選擇了正確的資料結構並組織好了,那麼演算法幾乎總是不言自明的。資料結構而非演算法是程式設計的核心。


從1975年開始引用弗雷德布魯克斯

表達(Representation )是程式設計的本質
有時,戰略突破將是一種新的演算法,例如Cooley-Tukey快速傅立葉變換成對n 2組的n log n排序。
更常見的是,戰略突破將來自重做資料或資料表的表示。這是您的計劃的核心所在。告訴我你的流程圖並隱藏你的資料表,我將繼續被神秘化誤導。告訴我你的資料表,我通常不需要你的流程圖; 因為他們會很明顯。


因此,聰明的人在近半個世紀裡一次又一次地這樣說:首先關注資料。但有時感覺就像每個人忘記的最著名的智慧程式設計建議。
讓我舉一些例項:

無法實現的高度可擴充套件系統
有一個系統從一開始就設計為處理CPU密集型負載,具有令人難以置信的可擴充套件性。沒有什麼是同步的。一切都是透過回撥,任務佇列和工作池來完成的。
但是存在兩個問題:第一個問題是“CPU密集型負載”卻不是真正CPU密集型的 : 一個任務在最壞的情況下耗費了幾毫秒。所以大部分架構都弊大於利。
第二個問題是雖然它聽起來像一個高度可擴充套件的分散式系統,但它不是一個 - 它只能在一臺機器上執行。為什麼?因為非同步元件之間的所有通訊都是使用本地檔案系統上的檔案完成的,這現在是任何擴充套件的瓶頸。
除了以“簡單”的名義提倡本地檔案之外,原始設計根本沒有說明資料。大部分文件都是關於處理負載“CPU密集度”“顯然”所需的所有額外架構。

面向服務的體系結構仍然是面向資料的
這種系統遵循微服務設計,由具有REST風格API的單用途應用程式組成。一個元件是儲存文件的資料庫(基本上是對標準表單和其他電子文書工作的響應)。當然它暴露了用於基本儲存和檢索的API,但很快就需要更復雜的搜尋功能。設計人員認為將此搜尋功能新增到現有文件API將違背微服務設計的原則。他們可以將“搜尋”稱為“獲取/放置”的不同型別的服務,架構上不應該將它們結合在一起。此外,他們計劃用於搜尋索引的工具與資料庫本身是分開的,因此建立新服務也對實現有意義。
最後,建立了一個包含搜尋索引的搜尋API,該索引基本上是主資料庫中資料的副本。此資料正在動態更新,因此透過主資料庫API改變文件資料的任何元件都必須更新搜尋API。沒有競爭條件的REST API不可能做到這一點,所以無論如何,這兩組資料時不時地不同步。
儘管承諾了架構圖,但兩個API透過其資料依賴性緊密耦合。後來人們認識到搜尋索引應該是統一文件服務的實現細節,這使得系統更易於維護。在資料層面“做一件事”,而不只是在動詞層面。(banq注:如何在資料層面實現唯一職責?透過DDD等其他方法都是可借鑑的方式,DDD模型是一種對資料的組織處理方式)

奇妙的模組化和可配置的泥球
這種系統是一種自動化部署管道。原始設計人員希望製作一個足夠靈活的工具來解決整個公司的部署問題。它被編寫為一組可插拔元件,配置檔案系統不僅配置了元件,還充當了DSL,用於程式設計元件如何適應管道。
快進幾年,它變成了“那..那個程式”了:有一長串已知的錯誤,沒有人曾經修復過。因為害怕破壞那個程式的一切而不敢接觸那個程式的程式碼。沒有人使用DSL的任何靈活性。使用該程式的每個人都複製貼上了其他人使用的相同的已知工作配置。
出了什麼問題?儘管原始設計文件使用了諸如“模組化”,“解耦”,“可擴充套件”和“可配置”之類的詞語,但它從未說過任何有關資料的內容。因此,元件之間的資料依賴性最終使用全域性共享的JSON blob以臨時方式處理。隨著時間的推移,元件對JSON blob中或不存在的內容做出了越來越多的無證假設。當然,DSL允許將元件重新排列成任何順序,但大多數配置都不起作用。

教訓
我選擇了這三個例子,因為它們很容易解釋。
顯然很多人仍然認為我寫這篇文章是為了取笑他人。實際上和我一起工作的人會知道我對我正在修理的東西更感興趣,而不是責怪那些完成大部分工作的人,但是,好吧,這就是我對工程師的看法。

“是否談論資料產生的問題?”對於良好的系統設計來說,這是一個非常有用的試金石。

它對於檢測虛假專家建議也非常方便。困難,凌亂的系統設計問題是資料問題,所以錯誤的專家喜歡忽略它們。他們會向你展示一個非常漂亮的架構,但不談論它適合哪種資料,以及(至關重要的)它不是什麼型別的資料。

例如,假專家可能會告訴您應該使用pub / sub系統,因為pub / sub系統是鬆散耦合的,而鬆散耦合的元件更易於維護。這聽起來不錯,會產生漂亮的圖表,但它卻是倒退的想法。釋出/訂閱不會使您的元件鬆散耦合; 釋出/訂閱 的鬆散耦合,這可能會或可能不會匹配您的資料需求。

另一方面,精心設計的面向資料的架構有很長的路要走。函數語言程式設計,服務網格,RPC,設計模式,事件迴圈等等都有它們的優點,但我個人看到像枯燥的舊資料庫這樣的工具 負責更成功的軟體運送。

(banq注:作者沒有看到函數語言程式設計 設計模式等都是處理資料的方式,資料很重要,我們不能忽視,一旦我們重視了,就需要有一套解決複雜資料的方式,這是作者沒有談到的,會讓人產生資料表設計很重要錯覺,其實資料表很重要,但是處理設計出資料表的方式更重要,這也是DDD等模式正規化的根本!)

相關文章