有一種特定的軟體,沒有人會寫部落格來介紹它。它在俄亥俄州的製造公司負責處理薪資。它排程一個你從未到過的城市裡的火車。它自2011年起就投入生產,經歷了三位CTO的更迭和私募股權收購,維護它的人談論它的方式就像老水手談論一艘見過風浪的船。閱讀過這個不會在現實生活中崩潰的變更安全系統藍圖讓我想起我們有多少研究這些系統,以及我們在這個行業發表的內容有多少是關於相反的——新地開發項目、重寫、相當於開箱視頻的架構。無聊的軟體贏了,而我們幾乎從不問為什麼。
我們一直忽略的生存者偏差
走過任何會議日程,計算一下關於五年前以上系統的演講。你會在用完手指之前就沒有時間了。行業對新鮮感的結構性偏好,悄悄扭曲了年輕工程師認為良好架構看起來的樣子。他們從被寫到的系統中學習,這些系統不僅僅是當前正在建造的,這意味著他們正在從尚未有時間失敗的系統中學習。
那些有時間失敗卻未被修復的系統,往往會共享一些在履歷上看起來不時髦的特徵。它們使用較舊的資料庫。它們中間某處有一個巨石式架構,沒有人試圖將其拆分。它們的部署流程涉及的人力比當前正統觀點認為可接受的還要多。它們依然在運行。有趣的问题是這些系統是否符合當前標準,有趣的问题是它們理解了而我們總是忘記的事情。
變化為一種物理力量
工程師往往抽象地思考變化——一個功能請求、一次重構、一次遷移。但變化更像是一種作用在結構上的物理力。它有方向、大小和頻率。一個系統吸收小而頻繁的變化與吸收罕見但巨大的變化行為不同,就像每天處理交通的橋樑與預備應對地震的橋樑行為不同一樣。將所有變化視為等同是團隊在它們的架構——這個架構能順利處理數百次小部署——在單次大規模遷移中崩潰時感到驚訝的原因。
這種敘述方式出現在許多關於這個主題的最有用長篇寫作中。IEEE電腦學會出版的系列有關韌性工程學 持續回到同一觀察點:複雜系統的失敗模式幾乎從不關乎組件本身。它們關乎組件之間的耦合,而耦合正是每次有人發布小修補時,悄然累積改變的東西。橋樑類比不是比喻。它是實際的機制.
舊代碼庫做對了什麼
我花了幾年時間在開發一個處理區域清算所財務結算的系統。它的核心在我還不夠開車的時候就已經寫好了。接觸它在前六個月讓人恐懼,接下來的每個月都讓人清晰。那個代碼庫的一些模式一直伴隨著我,我以來在遇到的每個長期運行的系統中都看到它們。
- 從未有人跨越過的界限。 不是由靜態程式分析工具或程式碼審查強制的界限。而是由跨越它們需要寫入不同數據庫,而這些數據庫由不同團隊在不同大樓擁有的事實所強制。物理上的分離促進了誠實的架構.
- 記錄讀起來像是一份自白。 每個重要行為都記錄了它即將執行的內容、它接收的輸入以及它的決定。不是為了除錯 — 是為了負責任。當六週後某事出錯時,你可以重建推理過程,而不僅僅是結果。
- 對於巧妙代碼的病態恐懼。 高級工程師們會例行地拒絕那些正確、經過良好測試且效率更高的 pull requests,理由是到 2029 年凌晨 2 點正在偵錯這段程式的人不會理解它。他們幾乎總是正確的。
- 故意花費數月時間的遷移。 花了幾週雙寫,又花了幾週雙讀,在舊路徑最終被移除前,有一段很長的驗證時間。遷移很無聊。這正是重點.
- 對共享可變狀態過敏。 不是因為性能,也不是因為並發理論,而是因為共享的可變狀態是機構記憶走向死亡的所在。兩個系統觸及同一行時,最終會對這行代表的意思產生分歧。
假裝改變無成本的成本
目前的工具讓變更感覺很便宜。容器在秒內啟動。功能旗標讓你可以發布不執行任何操作的程式碼,稍後再啟用它。基礎設施作為程式碼表示你只需要一個指令就能重現一個環境。所有這些都是真的,但這些都不會讓變更實際上變得便宜。它讓發布變更的行為變得便宜。後續的成本會以需要思考結果系統的人的認知負荷的形式出現。
計算機協會已發表一篇關於此的長篇實證研究,並在其ACM Queue 档案中收集了有關運作複雜度的資料 是目前有關團隊系統累積變更後實際發生情況的最具基礎性寫作之一。重複出現的模式並非系統因單一錯誤決策而失敗。它們失敗是因為每一個決策個別來說都是合理的,這些決策的累積重量超過了任何一位工程師能夠在腦中承載的範圍,而團隊仍然持續發布,因為工具讓它們感覺一切沒有問題。
一個實用的重解釋
如果你從那些超越原創作者的系統中學到一件事,那就是:為那個沒有背景資訊就接手這段程式碼的人進行優化。不是那個上週寫出它的你,也不是那個下個季度在設計仍然新鮮時維護它的你。是那個陌生人。是2028年那個試圖弄清楚某個特定功能為何存在,以及是否安全刪除的新員工。你做的每一個選擇,對那個人來說,要么是一份禮物,要么是一種稅收。可生存的系統,是那些大多數選擇都是禮物的系統。
這不是對舊程式的浪漫看法。舊系統確實有問題——它們累積了無用的路徑,它們編碼了過時的假設,它們讓原本困難的事情更加困難。但它們有一個綠地項目沒有的優勢,那就是它們經歷了現實的考驗。它們曾經錯誤,被糾正,再次錯誤,再次被糾正,而所有糾正的殘留物是一種智慧,任何架構圖都無法捕捉。大部分時候,工作不是要取代那種智慧。而是要擴展它。
誰也不教的紀律
這裡沒有這樣的課程。沒有這樣的認證。沒有這樣的框架,如果採用,會讓你的系統生存下來。這種學問更接近於一種感覺——一種習慣,每次你即將提交時,都會問,你正在做的改變是系統可以吸收的,還是會悄悄累積成未來的負擔。擁有這種感覺的工程師,在短期內往往發布得比同儕慢,但在長期內卻劇烈地快,因為他們不會不斷地償還他們沒有意識到的債務。
那些從不願離開的系統並非運氣好。它們是由一群嚴肅對待未來的人所建立,而在一個大多數只重視當下的事業中。如果你想建立一些能持續存在的事業,就研究那些乏味的軟體。閱讀那些已經運行十五年的程式的來源碼。注意它們不做什麼。注意每一個檔案中隱藏了多少約束。這種嚴謹性就坐在程式碼庫中,等待有人將其視為嚴謹性,而不是需要更換的舊事物。











