什麼是遺留代碼?遺留代碼是指已經存在且需要再次使用的源代碼。它不一定是糟糕的代碼,但通常需要一些努力才能集成到較新的系統中。這意味着您需要有效的方法來解決遺留代碼的問題。
您處理遺留代碼的機率有多大?鑑於 TIOBE流行度指數排名前10的編程語言大多已存在至少20年,因此,您遇到遺留代碼的機率非常高。(Go語言是個例外,它首次出現於2009年。)
↑ 隨時間變化的TIOBE流行度指數-C++
您不能總是依賴創建遵循現代編程實踐的新代碼。
本文旨在為您提供幫助,詳細介紹什麼是遺留代碼、處理遺留代碼的最佳實踐、如何編寫經得起時間考驗的新代碼,以及使處理遺留代碼更為輕鬆的工具。
什麼是遺留代碼?
遺留代碼是指從他人或舊版本軟件中繼承而來的源代碼。它還可以是任何您不理解或不知道如何測試,且難以修改的代碼。
這是一個簡單定義。處理遺留代碼可能會有許多潛在的問題需要解決。在《高效處理遺留代碼》一書中,Michael C. Feathers給出進一步的定義,指出要了解一段遺留代碼能做什麼是很困難的:
“對我來説,遺留代碼就是未經測試的代碼。” —— Michael C. Feathers
沒有測試,您就無法知道代碼滿足了哪些要求,以及如何將其應用到新的項目中。這意味着需要更多的努力來理解它、調整它,並編寫新的測試來驗證它是否仍然有效。
但是,這些定義忽略了這樣一種情況:您有舊的測試代碼,但它們都不符合現代要求或新標準。或者,這些代碼仍然有價值且合規,但您不知道如何將其集成到新的系統中。
想象一下,您必須將一箇舊的接口驅動程序移植到新的應用程序堆棧——您可能已經編寫了驅動程序,但卻不瞭解堆棧。
這就是為什麼我們上述對遺留代碼的定義更加全面且注重問題,我們將繼續探索有效的方法來解決這些差距,並將您的遺留代碼轉化為新的、可用的功能。
為什麼有效處理遺留代碼是一項挑戰?
在處理較舊或不熟悉的代碼時,最大的挑戰可能是你對它的假設。
您可能認為代碼很糟糕,編寫代碼的人不知道自己在做什麼,本可以做得更好。
但事實上,代碼之所以如此,通常是有原因的。如果您不是編寫者,可能並不知道其中的原因。
以下是處理遺留代碼時的一些常見挑戰:
- 維護難題 — 遺留代碼通常會增加系統的整體技術債務,使其更難維護或修改。這可能是由於代碼採用了過時的編程實踐、使用了舊的語言版本、算法效率低下或缺乏文檔。技術債務持續得越久,就越難維護。
- 集成問題 — 自遺留代碼創建以來,系統或業務已經發生了變化。當今世界有不同類型的連接性、雲平台、數據格式、功能安全標準、安全指南等,所有這些都需要仔細規劃才能正確地集成。
- 性能和可擴展性問題 — 遺留代碼可能無法針對當今的硬件進行優化,也無法利用較新的軟件技術和平台選項。必須考慮並解決遺留代碼與其環境之間的任何瓶頸問題。
- 安全風險 — 舊代碼很可能是在未考慮現代安全實踐或不瞭解當今威脅形勢的情況下開發的。它也可能不支持安全更新和補丁,從而容易受到已知和潛在漏洞的攻擊。
- 缺乏專業知識 — 開發人員離開組織的情況並不少見,這可能會導致他們的代碼無人支持且缺乏文檔。供應商可能會消失,圍繞開源軟件包的社區也可能會枯竭。在缺乏這些知識的情況下,嘗試維護和升級遺留代碼需要花費時間和精力。
在改進遺留代碼庫時必須小心謹慎。不能只針對一個區域快速修復,或運行現有的測試並希望它們通過。可能存在一些您不知道的依賴關係或無法預測的意外行為。
因此,瞭解何時維護或更改遺留代碼至關重要。
處理和重構遺留代碼的9個技巧
您不可能在一夜之間改進繼承的代碼。但是,可以採取循序漸進的措施來改進它。
首先,瞭解為什麼重用代碼,這會有所幫助。如果是由於財務或資源限制,除了繼續下去,您別無他法。中斷關鍵系統的風險可能會阻礙進展,但也可能有機會規劃向新代碼庫的緩慢過渡。
通常,堅持使用遺留系統往往是出於對變革的抵制。團隊安於現狀,尤其是工作繁忙時,人們不願意遷移到新的工作方式。在這種情況下,瞭解如何有效地處理遺留代碼以消除誤解或顧慮,就顯得尤為重要。
無論您是剛剛起步,還是已經處理了一段時間,您都應該遵循以下九個技巧。
- 測試遺留代碼
瞭解代碼的一種方法是創建特徵測試和單元測試。您也可以使用代碼質量工具(如靜態代碼分析器)來檢查代碼,以識別潛在問題。
這將幫助您瞭解代碼的實際作用,還能揭示功能、性能、安全性和編碼標準方面任何可能存在問題的區域。一旦瞭解了代碼,您就可以更有信心地進行量化更改、記錄異常和更新。
- 審查文檔
審查原始需求和功能文檔有助於瞭解代碼的來源。包括查看從需求管理工具到內聯代碼註釋的所有內容。
這些文檔可幫助您瞭解代碼當前的工作方式,並識別與新預期功能之間的差距。當需要做出更改時,這些信息有助於防止意外更改引入不良行為,或危及更大的系統。
- 僅在必要時重寫代碼
重寫整個繼承的代碼庫可能很“誘人”,但這通常是個錯誤。
如果不完全瞭解代碼庫的工作原理以及與外部世界的交互情況,重寫代碼可能會引入新的錯誤並導致依賴項問題。此外,重寫所有內容也需要耗費大量的時間和程序員。
最好對代碼重寫採取審慎的態度,基於高度信心和用於驗證行為的測試來選擇性地修改組件。
- 嘗試重構遺留代碼
比重寫代碼更有效的是重構代碼,且最好是逐步進行。
重構是改變代碼結構的過程,同時不改變其功能或外部行為。示例包括:
- 簡化隨時間變得過於複雜的條件表達式。
- 刪除硬編碼的字符串和值。
- 改進函數調用,使其更易於理解。
- 在函數之間移動功能,以消除代碼重複或避免一個組件承擔太多責任。
這些操作可以清理代碼,使其更易於理解。它還能夠消除潛在錯誤,減少項目的整體技術債務。
在重構遺留代碼時,最好注意以下事項:
- 重構具有單元測試的代碼,以便你知道自己擁有什麼。
- 從代碼的最深處開始,這樣重構是最容易的。
- 重構後進行測試,以確保沒有破壞任何東西。
- 有一個安全網(例如持續集成),以便可以恢復到之前的版本。
- 在不同的審查週期中進行更改
不要一次性更改太多。在同一審查週期內重構遺留代碼和功能性變更是個壞主意,因為它們會變得過於複雜,難以管理、測試和修復。
此外,限制更改範圍會使代碼審查更容易。對於審查員來説,孤立的更改要比一大堆更改要明顯得多。
- 與其他開發人員合作
對於一些代碼庫您可能不太瞭解,但您的同事可能很瞭解。向最瞭解代碼庫的人諮詢要快得多。
因此,如果可能的話,請與比您更瞭解它的人合作。多一個人看代碼,可以幫助你更好地理解代碼。
- 保持新代碼的整潔
有一種方法可以避免代碼出現更多問題——那就是確保新代碼是整潔的。它應遵循最佳實踐編寫,並通過自動化測試以確保符合編碼標準。
您無法控制繼承代碼的質量,但您可以確保所添加的代碼是整潔的。
- 使用AI
一種較新的技術是使用AI將遺留代碼轉換為新的語言,查找優化,檢測未使用的代碼等等,甚至可以要求生成式AI為您重構遺留代碼。
一個大問題是,您能信任AI來編碼嗎?重構遺留代碼是一項風險很高的操作,而AI在訓練方式和理解內容方面引入了新的變數。
好消息是正在取得進展。DARPA的Translating All C to Rust(TRACTOR)項目正在研究如何使用大語言模型(LLM)和其他技術,來通過將C代碼轉換為Rust以減少其內存安全漏洞。
“你可以訪問任何一個LLM網站,與其中一個AI聊天機器人聊天,你只需要説’這裏有一些C代碼,請把它翻譯成安全的慣用Rust代碼’,剪切、粘貼,然後就會有一些東西出來,而且通常很好,但並不總是如此。”
——Dan Wallach 博士,DARPA TRACTOR項目經理
- 進一步研究
隨着時間的推移,處理遺留的代碼庫會變得更容易。初級開發人員可能不理解為什麼沒有重構代碼庫(而且可能很想重構)。但是高級開發人員會知道什麼時候該放手不管。
更多地瞭解代碼庫將有助於您改進代碼庫。
一個良好的起點是Michael C. Feathers的《高效處理遺留代碼》,其中包含一些有關如何更改舊代碼庫的良好示例。
另一個良好來源是Martin Fowler所著的《重構:改進現有代碼的設計》。這本書提供了許多有效重構遺留代碼的技巧。
如何預防遺留代碼問題
防患於未然總是比較好的,因此在創建新代碼時,這裏有一些小貼士可供參考:
- 採用編碼標準 — 行業公認的編碼標準提供了最佳實踐,有助於避免出現更多問題。雖然這些標準通常被強制用於安全關鍵型應用,如 ISO 26262 和 MISRA,但它們對於在任何組織中培養“面向未來”的思維方式都非常重要。
- 記錄和註釋代碼 — 有用的解釋、提示和指南可使未來的開發團隊更容易訪問和維護代碼。
- 使用版本控制 — 版本控制對於維護和跟蹤代碼庫的更改至關重要。瞭解遺留代碼的歷史記錄,有助於您更好地理解它,並更輕鬆地在團隊之間協調重構。
- 運行自動化(持續)測試 — 在發佈代碼之前,進行全面的自動化測試至關重要。這可確保代碼隨着時間推移進行更改後,仍能保持功能性和可靠性。
- 遵循代碼安全最佳實踐 — 使用安全的編碼技術、安全測試工具和靜態分析工具,可以最大限度地降低代碼泄露的風險,並在整個生命週期內保持代碼安全。
有效處理遺留代碼的工具
您總是會需要處理遺留代碼——或者規避它。畢竟,代碼的存在是有原因的。它可以工作。而且,其結果可能足夠好,以至於你可以忽略已知的問題。
當然,也有充分的理由對代碼進行修改。您可能正在添加功能、修復漏洞或改進設計。
理想情況下,您會持續重寫那些舊的或不熟悉的代碼,直到它們完全無誤。但這很可能是不現實的。
因此,您需要做的是找出哪些可以更改,其他的就不要管了。
靜態分析
一種方法是使用代碼質量工具,如靜態代碼分析工具。您可以設置一個基線,然後對新代碼運行分析,以確保代碼的乾淨整潔。您還可以抑制代碼庫中的分析結果。
例如,Helix QAC和Klocwork等工具就使這一操作變得非常簡單。
分析遺留代碼
Helix QAC 可以根據規則(通常是編碼標準)檢查您的代碼庫。對於違規的診斷結果,您可以根據嚴重程度確定它們的優先級。這意味着您可以集中精力,優先修復錯誤最多的部分。
設置基線
您還可以將代碼庫設置為基線。也許代碼本身沒有問題,你想讓它保持不變。設置基線意味着代碼庫不會被納入診斷。相反,您可以專注於查找新代碼中的問題,並確保代碼是乾淨的。
↑ Helix QAC使設置基線變得輕而易舉
確保遺留代碼合規
在某些情況下,您可能會將源代碼從一個項目重用到另一個項目。但有些源代碼不是按照編碼標準開發的。如果您需要實現合規性(例如 MISRA),這可能會產生問題。通過使用 Perforce靜態代碼分析器(例如適用於C/C++的Helix QAC,或適用於C、C++、C#、Java、JavaScript和Python的Klocwork),您可以輕鬆查看代碼中的錯誤所在。
有效處理遺留代碼需要花費時間和精力,但這是一項必要的任務。
與其將其視為 “我不得不使用的糟糕代碼”,不如考慮遺留代碼的潛在價值,並逐步對其進行重構、測試和重新運行。當已有輪子被證明有用時,就沒有必要再重新發明輪子。
獲取更多Helix QAC&Klocwork產品支持,請諮詢Perforce中國授權合作伙伴——龍智:
官網:www.shdsd.com
電話:400-666-7732
郵箱:marketing@shdsd.com