攜程Alchemy程式碼質量平臺:提前在開發階段暴露程式碼問題

陶然陶然發表於2022-12-02

   一、背景

  隨著敏捷開發,DevOps開發模式的流行,程式碼質量分析作為研發質量保證體系的重要組成部分,不僅能有效的降低因頻繁迭代帶來的故障風險,而且對整個工程團隊的效能提升有著巨大的價值。

  攜程很久以前就已經開始進行DevOps的建設,透過Gitlab CI/CD在開發提交程式碼觸發的流水線pipeline中引入靜態掃描、單元測試、整合測試等流程,在開發過程中打造了一套閉環的程式碼質量保障體系。其中,在靜態程式碼分析階段引入了SonarQube,並且透過對原有SonarQube程式碼規範庫中的規範進行篩選和擴充套件,形成了自己的程式碼規範庫。但是在實際應用過程中,我們發現仍然有一些問題需要最佳化解決:

  在開發過程中,程式碼規範只能透過開發人員自我約束,缺少統一的平臺對各應用程式碼的潛在風險問題統一進行分析,且問題難以定位到開發人員進行治理。

  程式碼單元測試透過率和程式碼覆蓋率都很高,但仍然存在一些在單元測試階段應被發現的問題未暴露出來,導致上線後出現bug,單元測試用例的質量缺乏有效性及可靠性保證。

  隨著專案的發展,開發人員為了避免影響已有功能,在開發過程中大量複製貼上,導致出現很多難以維護的重複程式碼,且程式邏輯結構過於複雜,修改邏輯牽一髮而動全身,可維護性差。

  程式碼中充斥著大量的sql拼接,以及一些不規範的寫法導致潛在的問題,需要對此類程式碼進行治理。

   二、平臺介紹

  Alchemy平臺是一個程式碼質量分析平臺,提供Infer分析、程式碼分析、自定義掃描、程式碼搜尋等功能,其中程式碼質量分析內容包含程式碼行,sonar問題, infer問題,UT規則,重複程式碼以及圈複雜度等。使用者可以根據自己的需求在平臺上進行掃描項配置,並檢視應用的程式碼質量分析結果。

  為了及時獲得對提交程式碼變更的質量反饋,作為DevOps中重要的一環,Alchemy平臺與Gitlab CI/CD相結合,將靜態程式碼分析提前至開發提交或合併程式碼階段。開發人員提交程式碼至Gitlab,觸發流水線相關任務執行,任務執行完成之後可以對某些指標(如增量程式碼引入的空指標)設定紅線進行卡點,如果指標在指定範圍內,允許合併程式碼併發布,如果指標超過了紅線設定範圍,則不允許合併程式碼,開發人員修復問題後再次提交程式碼進行流水線的整合釋出。掃描分析結果可以在Gitlab或者Alchemy平臺上展示,幫助開發人員在快速迭代的同時保證程式碼質量。  

靜態程式碼掃描流程

   三、系統架構

  Alchemy平臺包含Alchemy-client、Alchemy-service和Alchemy-web。其中,Alchemy-client為掃描指令碼,包含Infer分析,UT掃描,重複程式碼掃描、自定義掃描等功能,整合到Docker映象中,Alchemy-service提供資料儲存、分析等後臺服務,且依賴程式碼搜尋服務CodeSearch-Service實現程式碼搜尋功能,Alchemy-web負責頁面互動。

  開發人員提交程式碼,觸發Gitlab CI/CD中靜態程式碼分析job在GitRunner中執行,執行時先從Docker倉庫下載映象,啟動容器後執行Alchemy-client指令碼,指令碼會根據平臺配置來執行相應的掃描任務,掃描完成後,將結果上傳至Alchemy-service,儲存到mongodb資料庫,最終在前端頁面展示分析結果。  

Alchemy架構圖

   四、功能

  4.1 Infer分析

  Infer是Facebook出品的一個靜態分析工具,可以分析Java、Objective-c或者C程式碼,報告潛在的問題,包括空指標,資源洩漏等。Alchemy平臺將Infer引入程式碼靜態分析階段,目前已支援全量和增量分析兩種模式。

  全量模式需分析應用倉庫中的所有程式碼,能分析出所有程式碼引入的潛在問題,對於程式碼量較大的應用,由於需要分析所有程式碼檔案,掃描時間比較長,在一定程度上影響開發釋出進度,且對未修改的程式碼進行了非必要的重複分析,在程式碼修改量較少的情況下造成資源浪費。因此,我們嘗試加入快取機制,並引入了增量分析模式,增量模式需要獲取本次提交修改的檔案,在分析階段只針對這些改動檔案進行分析,能大大節省分析時間。Infer分析流程如下:  

Infer分析流程圖

  在分析過程中,首先判斷是否為第一次分析,如果沒有分析歷史記錄,則系統預設採用全量模式,否則需判斷Infer掃描配置,若配置為全量模式,則分析此程式碼工程的全部檔案,若配置為增量模式,需獲取此次提交修改的檔案列表,編譯過程完成之後,在分析階段指定檔案列表進行分析。獲取到分析出的問題列表後,判斷問題所在的行是否為修改行,如果是,則記錄為本次修改導致的新增問題,否則為歷史遺留的全量問題。

  在實際應用中,針對封裝的判空方法,透過新增@TrueOnNull或@FalseOnNull註解,可識別物件的判空操作。但對於第三方包的判空方法,如CollectionUtils.isEmpty(), 由於未新增註解,即使新增判空方法,仍會被誤識別為空引用。因此,Alchemy平臺加入了忽略操作,針對此類問題進行二次確認,避免重複誤判。  

Infer誤判結果

  4.2 UT規則掃描

  單元測試是DevOps流程中一個非常重要的環節,我們可以利用透過率和程式碼覆蓋率等指標來衡量單元測試用例的完整程度,卻很難保證用例的有效性。阿里巴巴java開發手冊規定,單元測試不允許使用System.out來進行人肉驗證,必須使用斷言assert來驗證。

  在實際的開發過程中,開發人員把主要的時間用在寫業務邏輯程式碼上,在編寫單元測試用例時,往往容易忽略對結果的驗證,雖然透過率和程式碼覆蓋率很高,但上線後仍然出現未對介面結果進行驗證而導致嚴重問題的情況。無效的單元測試用例包含以下幾種:

  空函式:函式體為空;

  空斷言:用例中實現了對被測介面的呼叫邏輯,但未對介面返回結果進行驗證;

  偽斷言:用例中使用類似assertTrue(True)的假斷言。

  透過掃描空斷言、空函式、偽斷言等問題,能判斷該用例是否對程式碼邏輯進行必要的驗證。Alchemy平臺支援單元測試用例的有效性驗證,目前,平臺支援Java、Kotlin、Groovy和Nodejs,同時也支援全量和增量2種掃描結果,全量結果即為所有測試用例中不滿足規則的用例,增量結果為本次提交修改的測試用例中不滿足規則的用例。  

UT掃描流程

  對單個單元測試檔案的掃描流程如圖。首先根據檔案字尾判斷語言型別,然後根據不同語言型別規則獲取該檔案中的用例資訊,包含case名稱、起止行、作者、最近修改時間、函式內容等,針對函式內容,先判斷用例是否有斷言,如果有,則判斷是否為偽斷言,如果未斷言或者被判為偽斷言,還需進一步根據用例的起止行,結合本次提交的改動資訊,分析該用例是否為增量改動的用例,如果是則標記為增量問題,最後將結果推送給gitlab,在合併程式碼或釋出時根據紅線配置進行卡點。掃描結果如圖所示。  

UT掃描結果

  4.3 重複程式碼掃描

  重複程式碼即為重複或近似的程式碼,在開發過程中,開發人員為了避免影響現有功能,使用複製貼上快速完成開發任務,導致出現大量的重複程式碼。重複程式碼不僅讓程式碼量大增,造成編譯速度慢,而且佔用大量儲存空間,如果想要修改其中一段程式碼邏輯,則需要同時修改多個地方,容易遺漏,可維護性差。

  當前市面上有很多程式碼檢測工具,如Simian,PMD-CPD,CloneDR等,由於在實現演算法上有所不同,不同工具所能檢測的重複程式碼型別也不盡相同。我們利用PMD-CPD掃描程式碼倉庫,可以檢測出單檔案或多個檔案中除了空格、註釋、換行以及變數名以外內容完全一致的程式碼段資訊,這些資訊包含檔案路徑、程式碼段內容、起止行以及作者資訊,詳情結果如圖所示。  

重複程式碼詳情結果

  4.4 自定義規則掃描

  Alchemy支援對自定義規則的掃描,透過配置自定義正規表示式和掃描範圍,識別程式碼檔案中滿足配置規則的程式碼段,可用於掃描程式碼中的拼接SQL,敏感詞等,並且可將不合規的程式碼定位到相關開發人員。  

自定義掃描流程

  單個檔案掃描流程如圖,首先判斷檔案是否在掃描範圍內,若不在則直接跳轉掃描下一個檔案,否則讀取檔案內容,同時根據檔案型別獲取對應的自定義規則,匹配滿足規則的程式碼段資訊,包含程式碼段內容、嚴重程度、起止行、作者等。在某些場景下,需要設定子規則進行二次匹配,比如掃描update未指定where條件的sql語句,可先根據規則找到update語句,然後根據子規則判斷是否帶where條件,最終記錄二次匹配的結果。

  4.5 程式碼分析

  使用不同工具統計的程式碼質量指標可能分散在不同的平臺,對這些指標進行全面分析的過程中難免會有所遺漏,特別是對於未設定釋出卡點的指標,開發人員可能並不會關注它們,導致程式碼存在大量的潛在問題未被分析治理。

  Alchemy程式碼分析模組可以對程式碼不同維度的指標進行統計分析,包括程式碼行、單元測試、infer問題、Sonar問題、重複程式碼、圈複雜度等。使用者可以在程式碼分析頁面檢視各維度問題分佈情況,從而對專案的整體風險指標進行更全面的分析,可以根據問題的嚴重程度設定優先順序進行針對性的治理。  

程式碼分析結果

  4.6 程式碼搜尋

  在開發過程中,對於一些公共操作如中介軟體的使用方式,開發人員可能需要四處尋找接入文件。Alchemy提供程式碼搜尋功能,可以幫助開發人員根據關鍵詞來查詢收錄專案中的程式碼使用示例,使用者可以根據專案倉庫、程式碼語言以及作者等條件進行細分查詢。在編碼過程中,命名規範是一個容易被忽視的問題,使用Alchemy的變數命名功能,使用者可以根據不同語言,搜尋中英文關鍵詞來獲取推薦的規範命名參考,能極大地提高開發效率。  

程式碼搜尋結果

   五、結束語

  在本文中,我們介紹了Alchemy平臺提供的程式碼靜態分析,程式碼探索以及透過與Gitlab CI/CD整合帶來的持續整合能力,可以在開發階段暴露出更多的程式碼潛在問題和風險,並及時反饋給相關人員。目前攜程酒店已接入專案800+,且在開發提交程式碼和釋出階段將分析的潛在問題接入了卡點流程。在後續的工作中,我們將從以下幾個方向進行進一步的最佳化:

  在程式碼分析層面支援更多語言;

  開發IDE外掛,在編碼階段實時掃描程式碼;

  繼續深挖程式碼風險指標,並引入評估機制。

來自 “ 攜程技術 ”, 原文作者:Lyan;原文連結:http://server.it168.com/a2022/1202/6778/000006778545.shtml,如有侵權,請聯絡管理員刪除。

相關文章