【helloworld程式設計師】動一行,修半年,我的程式碼八代單傳
文章來源:哈囉我的程式員(公眾號) 作者:小七
在程式碼界,有一個令程式設計師聞之心驚、談之色變的存在—— 祖傳程式碼(legacy code) 。
相信很多接觸程式設計的人都對祖傳程式碼有著難以言表的恐怖體驗。如果不改,就難以實現新的需求,支撐新的業務。但一旦改了,新出現的bug絕對能讓人失去理智。

剛改完一行祖傳程式碼
也正是出於以上的原因,祖傳程式碼才會經由一個個程式設計師之手,代代相傳,生生不息。

那麼問題就來了: 祖傳程式碼為什麼動不得?
回答這個問題之前需要弄清楚一個點,那就是並不是所有的祖傳程式碼在修改後都會出現bug。很多程式碼之所以能被“祖傳”下來都是因為其嚴謹而實用。
但是,更多的程式碼之所以會成為祖傳程式碼,都是因為其邏輯混亂,再加上缺乏註釋,導致後來接手的人不敢輕易動手重構,於是相關人員彼此之間心照不宣,只管用不管改,促使程式碼被祖傳了下來。

於是,第二個問題就來了: 既然祖傳程式碼出現了問題,為什麼還能被執行和使用?
出現這種情況的原因一般有兩種:
一、外包不靠譜
系統的執行不是隻寫程式碼實現功能就完事了,還要考慮到後期的可維護性。而系統架構是極其複雜的,並非一個外包就能完美解決的。
對產品需求的瞭解是一個長期的過程,需要長時間與產品打交道。而大部分外包都遵循著成本最小的原則,缺乏對產品充分的瞭解,導致最後的成品只是樣子貨,禁不起再利用。
二、缺乏可用文件
小七之前提到過,養成寫文件和為程式碼添加註釋的習慣,可以提高程式碼的可閱讀性。但很多人對自己的記憶力和理解能力有著迷之自信,常常抱著“功能都實現了,為啥還要花時間寫程式碼”的心態,能不寫註釋就不寫。以至於後面的人接手專案的時候完全不明白某部分程式碼的意義,從而出現理解偏差,導致邏輯混亂,影響新功能的順利實現。
一般情況下,如果程式碼構成比較簡單,或許還能推匯出其中的邏輯,但如果寫這串程式碼的是個“天書派”程式設計師,那就只能自求多福了。因為他可能自己都不知道為啥當初要寫這行程式碼。

除了上面這兩點,還有很多因素會導致祖傳程式碼被延續下來,比如程式碼作者離職,比如程式設計師為了保住飯碗(國內還真有這種現象)通過公共函式使邏輯複雜化,再比如邏輯出錯但不影響執行所以被保留了下來等等。
出於種種原因,稍有歷史的網際網路公司業務都離不開祖傳程式碼。也因此,很多歷史遺留問題也被傳承了下來。
亞馬遜 的工程師將他們公司的程式碼形容為“ 一座很大的屎山,你見過的最大的山,每次你想修正一個 bug,你的工作就是爬到屎山的正中心去。 ”
亞馬遜的平臺架構是用C++寫的,C++的一大缺點就是缺乏自省。而亞馬遜有超過五千萬行 C++ 程式碼,所以一旦出現bug,解決方法就不是找到問題程式碼然後刪除重寫那麼簡單。更別說,有人可能好不容易爬到了屎山的正中心,然後拉了一坨新的屎。
在網際網路圈子裡,最常見到祖傳程式碼的還是遊戲行業。即使是 暴雪 這樣的遊戲大廠也逃不開被祖傳程式碼支配的命運。
暴雪的魔獸世界(簡稱WOW)在12年前就進入國內了,從最早的版本開始就支援預設16格揹包。

但是,隨著遊戲的不斷更新,16格初始揹包顯然不能滿足玩家的需求,於是大家紛紛發郵件建議暴雪增加初始揹包格數。
然而,WOW在當時已經是一款很老的遊戲了,以至於暴雪自己都不記得是哪個挨千刀的程式設計師寫的揹包程式碼。所以揹包擴容的事就不了了之了。
直到今年1月份,暴雪終於找到了那行程式碼,增加了4個揹包初始格。而代價就是數不清的全新的遊戲bug。

除了亞馬遜和暴雪以外,很多人估計也都知道:微軟的windows其實也是用的祖傳問題程式碼。因為要考慮到平臺之間互相的可操作性,所以windows作業系統是建立在年復一年持續的程式碼維護基礎上。說白了就是隻添磚加瓦,不修復地基。
可能是意識到歷史問題實在太多,直到2014年6月,微軟才專門招人對遺留程式碼進行修復。

歷史遺留問題是最難解決的問題,而偏偏祖傳程式碼就是這樣的問題。你永遠不知道你接手的程式碼有著怎樣奇異的身世。
你以為祖傳程式碼很悲催,但更悲催的是它已經八代單傳;你以為八代單傳很悲催,但更悲催的是它已經斷了香火;你以為斷了香火很悲催,但更悲催的是它可能根本就是無字天書。
所以,如果遇到很噁心人的祖傳程式碼,不要想著推倒重寫,先找到寫程式碼的人,狠狠地揍一頓再說。
反正重寫又不加工資。

文章來自公眾號:哈囉我的程式設計師 東半球最有趣的程式設計師聚集地