老舊系統重構技巧,輕鬆搞定遺留程式碼
作者:丁儀
來源:https://chengxuzhixin.com/blog/post/xi_tong_zhong_gou_ji_qiao_gao_ding_yi_liu_dai_ma.html
前幾天偶然看到一位網友發的內容,說是老系統改了一行程式碼就崩潰了,著實令人頭禿。越是成功的公司,越是有大堆的老系統和無法統計的遺留程式碼,尤其是基礎服務相關的程式碼,那簡直是按下葫蘆浮起瓢的現實版本。創業公司倒是好一點,沒有歷史包袱。我們也經常重構老舊程式碼,不為別的,就是怕放太久發黴。恰好最近也在做系統重構,總結下我們在做的事情和一些技巧。
程式碼也會發黴
會發黴的不只是食物,程式碼也會。我們通常稱為腐化。腐化的過程每天都在發生,一個緊急需求,一個新同事加入,一個變態的問題修復,一個共建專案,等等。腐化,是永遠無法避免的,就像宇宙的熵增不可逆一樣。面對腐化,架構師往往會加上一個防腐層。如果你的系統還沒有防腐層,趕緊考慮考慮。即便有防腐層,也招架不住歲月的摧殘,就像頭上那日漸稀少的秀髮,這就是命啊。
所以,我們需要重構。逆熵增需要做大量的功,要對混亂的程式碼重新梳理,使其恢復條理清晰、架構分明的優良狀態。
梳理,還是梳理
重構前花大量時間對歷史邏輯做梳理,而且要細緻。古人曰“工欲善其事,必先利其器”。梳理好的邏輯就是重構的指路明燈。哪些要丟棄,哪些要優化,哪些要重構,哪些要產品重新定,哪些是風險點,在梳理好後就基本明瞭了。梳理帶來的不只是邏輯的浮現,可能還有架構的方向。通過梳理,能夠明確發現業務邏輯,甚至可以定義出新的領域模型、值、事件等。想想銀河紀元時代,拿著銀河系實時星圖作戰,就知道梳理有多重要了。
回放,對比變化
重構之後,測試要全面覆蓋。這時候,回放就非常重要了。阿里也開源了一個回放工具 jvm-sandbox-repeater。GitHub 地址https://github.com/alibaba/jvm-sandbox-repeater。通過回放,可以在預發環境 debug 線上問題,可以看到線上真實流量在預發環境的實際表現。通過對比,可以發現重構後哪些地方和之前不一樣了,尤其是頁面渲染和持久化的資料。
回放做好以後,還可以作為日常釋出的快速驗證。只要本次回放和上次正常回放差異不大,基本上風險就已經很小了。
架構,以終為始
既然做重構了,架構方面就要好好設計。儘量摒棄錯綜複雜的歷史邏輯,設計新的架構方案。以提高研發效率、降低維護成本為最終目標,所有的重構設計都圍繞著這個目標展開。沒有什麼是不能改的,如果不能,那就加兩個更牛逼的程式設計師。如果重構後還保留一坨屎一樣的遺留程式碼,真不知道重構的意義是什麼。重構就是要以終為始,在新的架構設計中,讓遺留程式碼重新投胎以獲得新的生命。
改善,程式碼重構
優秀的程式設計師是需要不定期對已有程式碼做或多或少的重構的。在《重構 改善既有程式碼的設計》一書中,作者已經給了很多重構的具體方法。重複程式碼抽出、過長函式拆分、模型重新設計、封裝欄位、封裝集合、以State/Strategy取代型別碼、方法移動位置等諸多技巧,這裡就不展開了。我覺得每個程式設計師都應該好好學習下這本書,然後深入實踐下程式碼級重構。正如書評所說“雖不應翻著重構手冊幹活,但需對本書中提到的70多個重構方法成竹在胸”。
速度,速戰速決
遺留程式碼很多已經像網貸一樣了,越陷越深。投入資源做重構所獲得的回報,實際上比繼續維護老程式碼高的多。重構的過程要快,過程中日常需求儘量暫停。重構的工作量很大,但是對速度要求也很高。如果一邊重構,一邊線上還在做需求變更,很可能陷入困境,甚至在重構後丟失線上邏輯。梳理做好了,回放做好了,程式設計師就可以按照計劃快速重構,多上幾個人,確保快速完成。
心態,膽大心細
前面的工作都做好了,那接下來就是幹了。
放心大膽地幹,不要慫。這段程式碼看不懂怎麼辦,改!看回放。這段程式碼又臭又硬怎麼辦,改!看回放。
改的時候,也要心細一點,好好理解下原有的業務邏輯。在戰略上藐視敵人,也要在戰術上重視敵人。做好 code review,讓瞭解的人一起看改動,或者團隊成員一起把把