開發人員使用遺留程式碼庫指南

PetterLiu發表於2024-10-25

image

您是否曾經在開始新工作時,面對複雜的程式碼庫不知從何下手?你並不孤單。我們中的許多人都曾有過這樣的經歷--試圖理清仍在執行業務主要部分的過時程式碼。2024 年 Stack Overflow 的一項調查發現,超過 80% 的開發人員經常與遺留程式碼打交道,因此這是我們這個行業面臨的共同挑戰。大多數遺留軟體都有其價值,因為它們仍在使用並擁有客戶。在文章的其餘部分,我們將討論您可能面臨的典型問題,如過時的技術、缺失的文件和堆積如山的技術債務。更重要的是,我們將分享一些實用步驟,幫助你理解和駕馭這些舊系統。探討包括 GitHub Copilot 這樣的人工智慧助手在內的現代工具如何讓生活變得更輕鬆。那麼,讓我們開始吧。

瀏覽遺留程式碼庫


假設你剛加入一個新團隊,面對的是一個龐大的程式碼庫,其存在時間比你的大多數同事都要長。文件很舊,最後一次更新是在 2009 年。最初的開發人員早已不在人世,但這個系統卻為關鍵業務運營提供了動力。如何解決這個問題?根據 Stack Overflow 在 2024 年進行的一項調查,超過 80% 的開發人員經常與遺留程式碼打交道,這也是我們這個行業面臨的普遍挑戰。我們中的大多數人都有接觸過遺留程式碼庫的經歷,或者你目前正處於這種情況下。這種經歷的強度因不同的因素而異,例如程式碼庫的範圍有多廣、程式碼有多好、是否有測試、公司裡是否有人可以詢問等。遺留程式碼有不同的定義。有人說它是由團隊或開發人員繼承的程式碼,也有人說它是沒有測試的程式碼,甚至還有人說 “程式碼一寫出來就是遺留程式碼”。它通常是指仍在使用,但可能需要當前開發團隊充分理解、充分記錄或維護的程式碼。


處理遺留程式碼時面臨的挑戰


遺留程式碼通常會面臨不同的挑戰,例如

1.過時的技術或程式語言

遺留程式碼可能是使用過時的技術(不再受支援)、不遵循現代實踐或不再受廣泛支援或維護的程式語言編寫的。

2.沒有文件

在某些情況下,遺留程式碼可能沒有足夠的文件或根本沒有文件,這使得開發人員更難理解其工作原理或如何在不引入新問題的情況下對其進行修改。

3.大量技術債務

遺留程式碼通常會積累技術債務,即維護或重構程式碼所需的額外工作成本,從而使程式碼從長遠來看更容易維護。技術債務的例子包括過時的庫、複雜的邏輯、死程式碼等。

4.整合問題

將遺留程式碼與較新的系統或技術相結合可能會出現問題,因為它可能依賴於過時的應用程式介面、庫或資料格式。

5.測試挑戰

傳統程式碼可能需要更充分的測試,因此很難確保修改或整合不會引入新的錯誤或迴歸。

然而,在這種情況下,我們通常會感到不知所措,甚至不知從何下手。第一步是先了解程式碼,然後再採取行動。


理解遺留程式碼的推薦方法


以下是您可以採用的方法:

1. 閱讀技術文件


收集現有文件,包括架構圖、程式碼註釋和使用者手冊。與具有程式碼庫經驗的團隊成員交談,以便更好地瞭解其歷史、開發選擇、程式語言和已知問題。嘗試瞭解專案的業務方面以及這些程式碼應該做什麼。

推薦工具: Confluence、用於架構圖的 Draw.io、用於團隊文件的 Notion


2. 識別和分析熱點


關注熱點,即程式碼中經常更改的部分,因為這很可能就是你要工作的地方。與使用者和同事交談。嘗試找出業務需求並寫下所有內容。要求你的經理或團隊領導分配給你一個錯誤修復或小功能,讓你儘早接觸程式碼庫,或者與你的隊友一起開展任何活動,如拉取請求審查,讓你主動學習程式碼庫,而不是被動地逐行閱讀。

有用的工具: Git blame、用於熱點分析的 CodeScene、用於程式碼質量度量的 SonarQube


3. 建立開發環境


建立一個與生產設定非常相似的本地開發環境。確保可以在本地構建和執行應用程式,並訪問必要的資料庫、服務和配置檔案。在推向生產環境之前,請務必嘗試在開發/測試環境中所做的工作。

有用的工具: 用於容器化的 Docker、用於日誌記錄的 ELK Stack、用於監控的 New Relic 或 Datadog

4. 確保擁有所有必要的工具


檢查版本控制系統,檢視所接觸檔案的歷史更改記錄。如果沒有,第一步就是建立它。我們需要它來了解過去的更改及其背後的原因。接下來,確保你有一些持續整合和錯誤跟蹤系統。

推薦堆疊: Git、Jenkins/GitHub Actions、Azure DevOps

5. 關注入口點和關鍵功能


確定應用程式的入口點,如主方法或初始化指令碼。跟蹤這些入口點的執行路徑,以瞭解應用程式的流程。使用整合開發環境、偵錯程式和日誌框架等除錯工具來跟蹤問題並更好地理解程式碼庫。
除錯方法: 使用日誌框架、逐步除錯和效能剖析工具

6. 識別依賴項和模組


分析程式碼庫,識別依賴項、庫和框架。瞭解系統中每個模組或軟體包的目的和功能。熟悉主要元件及其互動,建立系統架構的高層地圖。

有用的工具: Structure101、Java 專案的 JDepend、JavaScript 的 npm-dependency-graph

7. 使用功能標誌


使用功能標誌feature flags的目的是為了在出錯時關閉程式碼(即回滾策略),並使您能在想啟動時啟動程式碼。有了特性標誌,你就不必等待下一次(正式)釋出。不過,要注意清理它們,因為它們會帶來新的複雜性(例如,建立一個文件來跟蹤它們)。

image

  • 場景描述:在處理遺留程式碼時,重構和遷移是常見的任務。使用Feature Flags,可以在不中斷服務的情況下,逐步將舊程式碼替換為新程式碼。
  • 意義:這種方式確保了系統的平滑過渡,降低了重構和遷移過程中的風險。同時,透過逐步替換和驗證,可以確保新程式碼的正確性和穩定性。


8. 謹慎編寫測試和重構


遺留程式碼庫通常缺乏足夠的測試覆蓋率。不要碰任何未經測試的東西!在進行任何修改之前,編寫單元測試和整合測試,確保修改不會破壞現有功能。重構時,應從小規模的增量更改開始,避免可能會引入新問題的大規模重寫。這種方法被稱為 “Strangler Fig”。

Strangler Fig(榕樹模式或絞殺者模式)是一種設計模式,由Martin Fowler在2004年首次提出(2019年改名為Strangler Fig Application)。Strangler Fig模式描述了一種逐步而非一次性進行系統遷移的優雅方法。在軟體環境中,它涉及在舊系統的邊界周圍構建一個新系統,並允許逐步用新系統的元件替換舊系統的部分。隨著舊系統的功能被新系統逐步取代,最終新系統將完全取代舊系統的所有功能,使舊系統停用。

構建外層:建立一個外層來攔截請求前往後端舊版系統。外層可將這些請求路由到舊版應用程式或新服務。
逐步遷移:將舊系統的功能逐步遷移到新系統。這可以透過新增新功能到新系統,並相應地更新外層路由來實現。
同步更新:確保外層與遷移保持同步,以便正確路由請求。同時,需要確保外層不會成為單一故障點或效能瓶頸。
停用舊系統:當所有功能都已遷移到新系統後,可以安全停用舊版系統。

如果發現方法過長,應將其分解為新的、更短的方法。你還應該清理死程式碼,刪除魔法數字,並應用其他清潔程式碼原則。測試方法建議:

1)為現有行為編寫特性測試
透過測試來明確和驗證軟體當前的行為特徵,以確保在後續的開發和維護過程中不會意外地改變這些行為。特徵測試是一種測試型別,它關注於軟體系統的特定行為或功能,並驗證這些行為或功能是否按照預期工作。與單元測試不同,特徵測試通常更加宏觀,涉及多個模組或元件的互動,並關注於系統的整體行為。特徵測試的目的是確保軟體系統的關鍵行為在不同場景下都能保持一致和正確。

識別關鍵行為:首先,需要識別軟體系統中的關鍵行為,這些行為可能是使用者經常使用的功能,或者是系統的核心業務流程。
編寫測試用例:針對每個關鍵行為,編寫相應的測試用例。測試用例應該覆蓋該行為的所有重要場景和邊界情況。
使用自動化測試工具:儘可能使用自動化測試工具來編寫和執行特徵測試。這可以提高測試效率和準確性,並減少人為錯誤的可能性。
驗證測試結果:執行測試用例並驗證結果是否符合預期。如果測試失敗,則需要檢查程式碼並修復問題,直到測試透過為止。


2)為計劃更改的區域新增單元測試
單元測試是軟體測試中最基礎的測試型別之一,它針對軟體中的最小可測試單元(通常是函式或模組)進行測試。單元測試的主要目的是驗證程式碼的行為是否符合預期,確保程式碼的正確性和穩定性。透過單元測試,可以在早期階段發現潛在的問題和錯誤,從而降低軟體釋出後的風險。

識別需要測試的區域:首先,需要明確計劃修改的程式碼區域,並識別出哪些部分需要進行單元測試。
編寫測試用例:針對需要測試的區域,編寫相應的測試用例。測試用例應該覆蓋該區域的所有重要功能和邊界情況。
執行測試並驗證結果:在修改程式碼之前,執行測試用例並驗證其結果是否符合預期。如果測試失敗,則需要修復程式碼直到測試透過。
在修改後重新執行測試:在修改程式碼後,重新執行測試用例以確保修改沒有引入新的錯誤。如果測試失敗,則需要檢查修改並修復問題。

3)對關鍵路徑實施整合測試

關鍵路徑是指在軟體測試過程中,從開始至結束的最長時間路徑。它代表了測試過程中的瓶頸,決定了整體測試的時長和進度。關鍵路徑上的測試任務通常具有較高的優先順序和重要性,一旦這些任務延遲或出現問題,將對整個測試計劃產生重大影響。

整合測試是在單元測試的基礎上,將所有模組按照設計要求組裝成系統進行測試的過程。它的主要目的是檢查模組之間介面的正確性、模組之間資料的傳遞以及系統功能的完整性。透過整合測試,可以確保軟體在關鍵路徑上的各個模組能夠正確協同工作,從而實現整體功能。

4)使用突變測試驗證測試質量

突變測試的核心思想是對程式的原始碼或目的碼進行小的改動,並把這種改動產生的截然不同的錯誤行為(或怪異行為)作為預期。如果測試程式碼沒有覺察到這種小改動帶來的錯誤,就說明這個測試是有問題的。透過這種方式,突變測試可以幫助找到那些可能被忽略的錯誤和弱點。

衡量測試質量:透過改變原始碼並觀察測試程式碼的反應,可以評估測試的完整性和有效性。如果測試能夠成功檢測到這些小的改動(即變異),則說明測試具有較高的質量。

定位程式碼弱點:突變測試還可以幫助開發者定位程式碼中的弱點和冗餘部分,從而提高程式碼的質量和效率。


9. 記錄你的發現

在探索程式碼庫的過程中,記錄下您的發現和見解。這些文件將幫助您和您的團隊更好地理解系統,並更有效地進行未來的更改。此外,如果有人要求你徹底重寫應用程式,請說 “不”!尤其是在規模較大的情況下。即使有一些合理的理由,這通常也是一項重大且不可預測的工作。

推薦工具: 架構決策記錄(ADR)、用於 API 文件的 Swagger、軟體源中的 README.md 檔案。

  • 概念:ADR,即Architectural Decision Records,意味著記錄架構決策的一種實踐。它涉及透過持續記錄軟體架構決策過程中重要的資訊,以便未來的開發者和決策者可以理解為何當時會作出這樣的選擇。
  • 目的:ADR的主要目的是提供一種機制,讓團隊成員能夠記錄下為何一個特定的技術、模式或者架構被選擇,併為未來的專案參與者留下足夠的上下文資訊。

一個典型的ADR文件通常包括以下幾個重要部分:

  • 標題:簡潔明瞭地描述決策的主題。
  • 背景:提供決策的背景資訊,包括問題的提出、相關的需求和約束條件等。
  • 決策描述:詳細闡述所作出的決策,包括選擇的技術、模式或架構等。
  • 狀態:描述決策的當前狀態,如已實施、待實施、已廢棄等。
  • 後果:分析決策可能帶來的後果,包括正面影響和潛在風險。

Architectural Decision Records(ADR)在IT行業中具有重要的作用,它能夠幫助團隊記錄和管理架構決策,提升決策透明度和專案一致性,促進團隊協作和專案維護。在實施過程中,應關注文件的清晰簡潔性、及時更新性以及團隊文化的推廣等方面。

10. 定期進行程式碼審查

程式碼審查可以透過對拉取請求的註釋、面對面聊天或遠端影片聊天來完成。你可以與工程師同事、工程經理或任何熟悉程式碼庫的人一起進行。在此瞭解如何正確進行程式碼審查。

專注於一件事

記住一次只專注於一件事。為了防止在堆積如山的程式碼中不知所措和迷失方向,我建議首先只專注於程式碼庫的一個部分,理解它,然後再轉向下一個部分。

更多請閱讀

《修改程式碼的藝術Working Effectively with Legacy Code》 作者 Michael Feathers

重構: 改進現有程式碼的設計》,Martin Fowler 著

整潔程式碼》 “羅伯特-馬丁(Robert C. Martin)著


使用人工智慧AI工具瀏覽遺留程式碼庫


如今,你可以使用不同的人工智慧工具來幫助你瀏覽遺留程式碼庫,例如 GitHub Copilot。它能從註釋和程式碼中理解上下文,幫助你更快地編寫程式碼,減少錯誤。在處理遺留程式碼時,Copilot 可以

1)提供符合現有模式的程式碼補全。
2)為不熟悉的程式碼片段提供解釋建議。
3)為文件不完善的程式碼生成測試和文件。

如何使用?首先,你需要為不同的整合開發環境安裝它:

Visual Studio Code: 從 VS Code Marketplace 安裝。
JetBrains IDE: 使用 JetBrains Marketplace 中的外掛。
Neovim: 按照 GitHub Copilot Neovim 程式碼庫上的說明進行操作。

然後,你可以使用以下策略來瀏覽程式碼。

1. 繪製地圖


使用人工智慧來理解不熟悉的程式碼。以下是一些可以嘗試的示例:

image

2. 為程式碼編寫單元測試


在深入研究之前,讓人工智慧幫你建立安全網:

image

3. 安全地重構程式碼


我們可以要求 Copilot 重構或更新程式碼段。您可能會遇到難以閱讀的複雜條件邏輯,比如下面這樣的情況:

image

您可以請求 Copilot 使用 C# 中的現代開關表示式進行重構。

image

4. 生成文件


要求人工智慧記錄更改,這可以在程式碼之外完成。這可能是人工智慧工具最強大的功能之一,因為它能使程式碼和文件保持同步。

image


人工智慧方法的缺點


在缺點方面,我們在向人工智慧提問時應小心謹慎,因為它們可能會因 LLM 模型中的幻覺而產生不好的結果,然後你需要再次提問,但在某種程度上,它們可以幫助你瞭解該往哪裡走。正如最新的《
ThogughtWorks 技術雷達》第 31 卷所指出的,有一種誤解認為人類可以完全取代以人工智慧為夥伴的結對程式設計,這導致了對編碼輔助思想的過度依賴、生成程式碼的程式碼質量問題以及更快的程式碼庫增長速度。此外,目前在 GitHub Copilot 等人工智慧工具中缺少的是對程式碼庫更廣泛的理解,以及在提出修改建議時對業務邏輯和依賴關係的考慮。當這些工具更好地理解程式碼庫、文件等內容時,它們將產生驚人的結果。這些結果將幫助我們將關注點從單純的編碼轉向解決問題。

因此,當我們想使用 LLM 完成編碼任務時,我們應該問問自己:我想解決什麼問題?我想解決什麼問題,人工智慧是最佳解決方案嗎?如果答案是肯定的,那就使用它。此外,考慮到這些工具每天都在不斷改進,偶爾也要檢查一下。總之,像 GitHub Copilot 這樣的人工智慧工具可以透過提供即時見解、建議和改進來幫助你處理遺留程式碼。普林斯頓大學、麻省理工學院和微軟的研究表明,雖然 Copilot 並不是萬能的,但將其整合到工作流程中可以將工作效率提高 26%。


總結

遺留程式碼通常指的是那些歷史悠久、可能由不同團隊在不同時期編寫的程式碼,它們往往缺乏統一的架構、文件和測試覆蓋。這些程式碼可能因為技術債務、維護困難、效能瓶頸等問題而成為專案發展的阻礙。因此,探討處理遺留程式碼的方法對於提升軟體質量、降低維護成本、加速新功能開發等方面都具有重要意義。

意義一:提升軟體質量
遺留程式碼往往存在大量的技術債務,如未解決的bug、冗餘程式碼、缺乏文件和測試等。透過處理遺留程式碼,可以識別和修復這些問題,從而提升軟體的整體質量。高質量的程式碼不僅減少了出錯的可能性,還提高了系統的穩定性和可靠性。

意義二:降低維護成本
遺留程式碼通常難以理解和維護,因為它們可能缺乏清晰的文件和註釋,或者使用了過時的技術和工具。透過重構、模組化、新增文件和測試等手段處理遺留程式碼,可以使程式碼更加易於理解和維護。這降低了維護成本,提高了開發效率,並使得團隊能夠更快地響應市場需求和變化。

意義三:加速新功能開發
遺留程式碼可能包含大量的技術障礙,這些障礙會阻礙新功能的開發和部署。透過處理遺留程式碼,可以消除這些障礙,為新功能開發創造更加順暢的環境。這有助於加速新功能的開發和部署,提高產品的競爭力。

意義四:促進技術演進
隨著技術的不斷髮展,新的工具、框架和程式語言不斷湧現。處理遺留程式碼可以使得系統更加容易採用新技術,從而保持系統的先進性和競爭力。透過逐步替換過時的技術和工具,可以使得系統更加靈活、可擴充套件和易於維護。

意義五:提高團隊協作效率
遺留程式碼往往存在多個版本和分支,這使得團隊協作變得複雜和困難。透過處理遺留程式碼,可以整合這些版本和分支,使得團隊協作更加順暢和高效。這有助於提高開發團隊的凝聚力和協作效率,促進專案的順利推進。

探討處理遺留程式碼的方法在軟體工程中具有重要意義。它不僅有助於提升軟體質量、降低維護成本、加速新功能開發等方面,還有助於促進技術演進和提高團隊協作效率。因此,在軟體工程中,我們應該重視並妥善處理遺留程式碼問題。



今天先到這兒,希望對雲原生,技術領導力, 企業管理,系統架構設計與評估,團隊管理, 專案管理, 產品管理,資訊保安,團隊建設 有參考作用 , 您可能感興趣的文章:
構建創業公司突擊小團隊
國際化環境下系統架構演化
微服務架構設計
影片直播平臺的系統架構演化
微服務與Docker介紹
Docker與CI持續整合/CD
網際網路電商購物車架構演變案例
網際網路業務場景下訊息佇列架構
網際網路高效研發團隊管理演進之一
訊息系統架構設計演進
網際網路電商搜尋架構演化之一
企業資訊化與軟體工程的迷思
企業專案化管理介紹
軟體專案成功之要素
人際溝通風格介紹一
精益IT組織與分享式領導
學習型組織與企業
企業創新文化與等級觀念
組織目標與個人目標
初創公司人才招聘與管理
人才公司環境與企業文化
企業文化、團隊文化與知識共享
高效能的團隊建設
專案管理溝通計劃
構建高效的研發與自動化運維
某大型電商雲平臺實踐
網際網路資料庫架構設計思路
IT基礎架構規劃方案一(網路系統規劃)
餐飲行業解決方案之客戶分析流程
餐飲行業解決方案之採購戰略制定與實施流程
餐飲行業解決方案之業務設計流程
供應鏈需求調研CheckList
企業應用之效能實時度量系統演變

如有想了解更多軟體設計與架構, 系統IT,企業資訊化, 團隊管理 資訊,請關注我的微信訂閱號:

image_thumb2_thumb_thumb_thumb_thumb[1]

作者:Petter Liu
出處:http://www.cnblogs.com/wintersun/
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線,否則保留追究法律責任的權利。 該文章也同時釋出在我的獨立部落格中-Petter Liu Blog。

相關文章