25,000,000行的程式碼就問你敢不敢動?!
你經歷過絕望嗎?
近日,Hacker News 上發起了一個名為“你見過最糟糕的程式碼是什麼?”(https://news.ycombinator.com/item?id=18442637)的話題,引發了無數網友回憶討論,甚至還再次讓軟體巨頭 Oracle 登上頭條。
25,000,000 行的程式碼就問你敢不敢動?!
日前,我們還在說如今的 Oracle 慘遭亞馬遜、Salesforce 棄用,究其根本原因,不是因為亞馬遜等企業為了省錢,而是因為 Oracle 資料庫逐漸滿足不了他們業務的發展需求。
在 Oracle 內部,相比每隔六個月就更新一次的 Java,Oracle 資料庫版本的更新頻率可以用 2-3 年甚至更久來表示。就在上文所述的 Hacker News 話題中,來自 Oracle 的程式設計師為我們解釋了其中的緣由,龐大的 Oracle 資料庫並不像外人看得那麼簡單,修復 Bug 可以分分鐘讓人奔潰。
該程式設計師以 Oracle 資料庫 12.2 版本為例,它擁有了近 2500 萬行的 C 程式碼。
每次更新,你需要在不破壞現有測試 1000 次的情況下更改產品中的單行程式碼。就 Oracle 資料庫產品而言,是好幾代程式設計師在有限的期限內編寫的這些程式碼,但與此同時,這些程式碼中也充斥著大量的垃圾程式碼。
非常複雜的邏輯、記憶體管理、上下文切換等都與數千個 flag 一起儲存。整個程式碼都帶有神祕的巨集命令,如果沒有使用筆記本而是手動擴充套件相關的巨集,那麼你就無法清楚地明白這些巨集。甚至可能需要一天到兩天才能真正理解某個巨集的作用。
有時你需要了解 20 個不同 flag 的值和效果來預測程式碼在不同情況下的行為方式。有時多達數百個 flag!“我並不誇張。”該程式設計師表示道。
Oracle 這個產品仍然存活並且可以供企業和開發者使用的唯一原因是數百萬次測試!
接下來,該程式設計師分享了 Oracle 資料庫開發人員的日常:
- 開始處理一個新的 Bug。
- 花兩週的時間試圖瞭解 20 種不同的 flag,這些 flag 以神祕的方式相互作用,造成了這個困境。
- 再新增一個 flag 來處理新的特殊情況。新增幾行程式碼來檢查此 flag 並解決有問題的情況,避免該 Bug。
- 將更改提交到包含大約 100 到 200 臺伺服器的測試伺服器叢集,這些伺服器將編譯程式碼,構建新的 Oracle 資料庫,並以分散式方式執行數百萬個測試。
- 下班回家。第二天來上來,繼續做其他事情。測試可能需要 20 小時到 30 小時才能完成。
- 一天結束,下班回家。再來上班時,檢查前天的整合測試結果。如果幸運的話,將會大約有 100 個失敗的測試。如果運氣不好,將大約會有 1000 個失敗的測試。隨機選擇一些測試並嘗試瞭解你的假設出了什麼問題。也許還有 10 多個 flag 要考慮才能真正理解 Bug 的本質。
- 新增一些 flag 來嘗試解決問題。再次提交更改以進行測試。再等 20 到 30 個小時。
- 另外,重複以上步驟大概兩週左右,直到你能得到將這些 flag 組合起來的“神祕咒語”(沒有錯誤發生)。
- 終有一天,你會成功,帶來測試失敗為零的結果。
- 針對你新更改的部分新增 100 多個測試,以確保下一個不幸接觸這段新程式碼的開發人員永遠不會破壞你的修復程式。
- 完成最後一輪的測試提交工作。然後提交以供稽核。審查本身可能還需要 2 周到 2 個月。所以現在繼續討論下一個 Bug。
- 在 2 周到 2 個月之後,當一切都完成後,程式碼將最終合併到主分支中。
以上是在 Oracle 修復 Bug 的程式設計師日常的非誇張描述。現在想象一下開發新功能會有多麼恐怖。開發一個小功能需要 6 個月到一年(有時是兩年!比如新增一種新的身份驗證模式,比如支援 AD 身份驗證),現在也可以理解為什麼 Oracle 資料庫的更新速度永遠追不上 Java 了。
而對於這款產品可以商用也真的是一個奇蹟。到了最後,這名程式設計師崩潰地說:我不再為 Oracle 工作了。永遠不會再為 Oracle 工作了!
對於這一現狀,更有不少網友表示了同情:
@nathan_f77:這絕對是瘋了。 我甚至無法想象程式碼庫的複雜性。我認為我的 Rails 測試套件已經很慢了,因為它需要 4 分鐘。如果我用 C 或 C ++ 編寫它可能是 10 秒。
我無法想象一個 C / C ++ 的應用程式,其中測試套件在具有 100-200 臺伺服器上需要 20-30 小時。如果你僅更改一次之後突破 100-1000 次測試,那麼它就不像獨立的模組化那樣了。
測試執行間隔 30 小時! 我絕對不會接受這份工作, 因為光聽起來,就像是地獄。
rm -rf 的怨念
那如果說在 2500 萬行的程式碼上動刀,光是測試就已經如此複雜了,除了之外,是否還有比這更可怕的程式碼?
必須有!
讓很多程式設計師後悔到想剁手的“rm -rf”絕對要算一個,糟糕的不是命令列本身,而是它帶來的後果。此前,不僅有順豐程式設計師的刪庫跑路事件,就連前MegaEase 創始人&CTO 陳浩(微博@左耳朵耗子)也未能逃脫該命令列帶來的魔咒。
那年寫 Unix Shell 指令碼,本想刪除一些臨時的子目錄,如:rm -rf ${mydir}/ ,結果呢,我沒檢查 ${mydir} 這個變數是否為空,於是呢,在某種情況下,這變數真的為空了,於是,我成了團隊的千古罪人。
那些年,我們見過和創造的“渣渣”程式碼
論起是否遇到過糟糕的程式碼時,天下的程式設計師似乎有著極高的相似性,在此,更有知乎網友(https://www.zhihu.com/question/30776912)吐槽:
@小豬:
if (b == true) {...}
我不常寫 C,不知道 C 程式設計師是不是覺得這種寫法是理所當然的,但當我在 Java 程式碼中頻繁的看到這種程式碼的時候,我真的很無力。
@周越:
(a != b) ? b : a
@侯傑:
enum FiveLine
{
Gold,
Wood,
Water,
Fire,
Earth,
};看列舉名字不知道五行(hang)是什麼鬼,看了列舉內容恍然大霧,原來是五行(xing)……
@玻璃杯中的魚:
// 以下所有left代表右
// 以下所有right代表左
寫在最後
在程式設計師的日常生活中,面對參差不齊的程式碼,Debug 成功了叫創新,改 Bug 失敗叫掉坑,但是,如今的大牛哪一個又不是在寫 Bug 與 Debug 中博弈過來的呢,也正是有了這些糟糕的程式碼才能讓彼時的菜鳥們真正得以歷練,而對於歷練過程中需要注意什麼,對此,CSDN 也曾發文從程式碼的基本規範和約束、程式設計思想、版本迭代與重構、設計模式等角度,為大家一一講清如何才能成長為優雅的大牛程式設計師。
你曾經又寫過哪些讓你後來捂臉的糟糕程式碼?歡迎下方留言,分享那些年的菜鳥歲月。
點選“閱讀原文”,開啟APP 閱讀更順暢
【完】
公開課預告
◆
文字分類
◆
文字分類問題是企業在NLP領域中處理文字資料時經常會遇到的一個問題,很多時候,我們需要將文字資訊進行分類,或提相關的介面以供外部進行文字上傳,在針對於使用者所上傳的文件資訊就需要進行文件內容的分類,那麼針對於這個需求我們就需要使用到文字分類的相關模型和演算法進行處理。在文字分類領域中的模型和演算法有很多。本次演講就是從這個角度入手,通過對比來闡述不同的演算法、模型在實際的應用過程中的區別,以及在文字分類實踐中所遇到的各種坑。
推薦閱讀