如何在遺留專案中實現靜態程式碼分析器而不影響團隊積極性

如何在遺留專案中實現靜態程式碼分析器而不影響團隊積極性
嘗試靜態程式碼分析器很容易。 但要實現它,尤其是在大型舊專案的開發中,需要技巧。 如果做得不正確,分析人員可能會增加工作量、減慢開發速度並降低團隊的積極性。 讓我們簡單談談如何正確地將靜態分析整合到開發過程中,並開始將其用作 CI/CD 的一部分。

介紹

最近我的注意力被《在不讓團隊不知所措的情況下開始靜態分析」。一方面,這是一篇值得熟悉的好文章。另一方面,在我看來,它仍然沒有提供關於如何在一個有大量數據的項目中輕鬆實現靜態分析的完整答案。文章說,您可以接受技術債並僅在新程式碼上工作,但沒有回答稍後如何處理該技術債。

我們的 PVS-Studio 團隊對此主題發表了自己的看法。 讓我們看看實作靜態程式碼分析器的問題最初是如何出現的,如何克服這個問題,以及如何輕鬆地逐步消除技術債。

問題

啟動並查看靜態分析器如何工作通常並不困難[1]。 您可能會在程式碼中看到有趣的錯誤,甚至可怕的潛在漏洞。 您甚至可以修復某些問題,但許多程式設計師會放棄。

所有靜態分析儀都會產生誤報。 這是靜態程式碼分析方法的一個特點,對此我們無能為力。 在一般情況下,這是一個無法解決的問題,正如賴斯定理所證實的那樣[2]。 機器學習演算法也無濟於事[3]。 即使一個人不能總是分辨出這個或那個程式碼是否錯誤,那麼你也不應該期望程式會出現這種情況:)。

如果靜態分析器已配置,則誤報不是問題:

  • 禁用不相關的規則集;
  • 一些不相​​關的診斷已被禁用;
  • 如果我們談論的是 C 或 C++,那麼巨集會被標記為包含特定的結構,這些結構會導致在使用此類巨集的每個地方出現無用的警告;
  • 自己的函數被標記為執行類似於系統函數的操作(它自己的模擬 Memcpy 的printf)[4];
  • 使用註釋專門禁用誤報;
  • 等。

在這種情況下,我們預期誤報率較低,約 10-15% [5]。 換句話說,十分之九的分析器警告將表明代碼中存在真正的問題,或至少是「氣味濃烈的代碼」。 同意,這個場景非常令人愉快,分析器是程式設計師真正的朋友。

如何在遺留專案中實現靜態程式碼分析器而不影響團隊積極性
事實上,在一個大型專案中,最初的畫面會完全不同。 分析器針對遺留程式碼發出數百或數千條警告。 不可能快速了解這些警告中哪些是相關的,哪些是不相關的。 坐下來開始處理所有這些警告是不合理的,因為這種情況下的主要工作將停止數天或數週。 通常,團隊無法承受這種情況。 還會有大量的差異破壞變更歷史。 快速批次編輯程式碼中如此多的片段將不可避免地導致新的拼字錯誤和錯誤。

最重要的是,這種對抗警告的壯舉毫無意義。 同意該專案已成功運行多年,其中大部分關鍵錯誤已得到糾正。 是的,這些修復非常昂貴,必須進行調試,收到有關錯誤的負面用戶回饋,等等。 靜態分析器將有助於在編碼階段快速且廉價地修復許多此類錯誤。 但目前,無論怎樣,這些錯誤已經被修復,分析器主要偵測舊程式碼中的非關鍵錯誤。 該程式碼可能不會被使用,也可能很少使用,並且其中的錯誤可能不會導致明顯的後果。 也許按鈕的陰影在某個地方顏色錯誤,但這不會影響任何人使用該產品。

當然,再小的錯誤也還是錯誤。 有時,錯誤可能隱藏真正的漏洞。 然而,放棄一切並花費數天/數週的時間來處理幾乎不顯現出來的缺陷似乎是一個可疑的想法。

程式設計師看著、看著、看著所有這些關於舊工作程式碼的警告……他們認為:我們可以不用靜態分析。 讓我們去寫一些新的有用的功能。

以他們自己的方式,他們是對的。 他們認為首先必須以某種方式消除所有這些警告。 只有這樣,他們才能從定期使用程式碼分析器中受益。 否則,新的警告就會被舊的警告淹沒,而沒有人會注意到它們。

這與編譯器警告的類比相同。 他們建議將編譯器警告的數量保持在 0 並不是沒有道理的。如果有 1000 個警告,那麼當有 1001 個時,就沒有人會注意了,而且也不清楚去哪裡尋找這個最新的警告。

如何在遺留專案中實現靜態程式碼分析器而不影響團隊積極性
這個故事中最糟糕的事情是,如果此時上面有人強迫您使用靜態程式碼分析。 這只會削弱團隊的積極性,因為從他們的角度來看,額外的官僚複雜性只會造成阻礙。 沒有人會看分析儀的報告,所有的使用都只是「紙上談兵」。 那些。 形式上,分析被內建到 DevOps 流程中,但實際上這對任何人都沒有好處。 我們在攤位上聽到了與會者的詳細故事。 這樣的經驗可能會阻礙程式設計師在很長一段時間內(甚至永遠)使用靜態分析工具。

實施和消除技術債

事實上,即使在大型舊專案中引入靜態分析也沒有什麼困難或可怕的。

CI / CD

此外,分析儀可以立即成為持續開發過程的一部分。 例如,PVS-Studio 發行版包含用於方便地以您需要的格式查看報告的實用程序,以及向編寫有問題的程式碼部分的開發人員發出的通知。 對於對從 CI/CD 系統啟動 PVS-Studio 更感興趣的人,我建議您熟悉相應的內容 部分 文件和一系列文章:

但讓我們回到實施程式碼分析工具的第一階段出現大量誤報的問題。

修復現有技術債並處理新警告

現代商業靜態分析器可讓您僅研究新程式碼或更改程式碼中出現的新警告。 這種機制的實作方式各有不同,但本質是一樣的。 在PVS-Studio靜態分析儀中,此功能的實現如下。

為了快速開始使用靜態分析,我們建議PVS-Studio使用者使用批量抑制警告的機制[6]。 整體思路如下。 使用者啟動分析儀並收到許多警告。 由於一個已經開發多年的專案仍然存在,正在開發並且正在賺錢,那麼報告中很可能不會有太多表明嚴重缺陷的警告。 換句話說,關鍵錯誤已經透過更昂貴的方法或客戶的回饋以某種方式修復。 因此,分析器目前發現的所有內容都可以被視為技術債務,試圖立即消除它是不切實際的。

您可以告訴 PVS-Studio 認為這些警告暫時無關緊要(為以後保留技術債),並且它將不再顯示它們。 分析器會建立一個特殊文件,其中保存有關尚不感興趣的錯誤的資訊。 現在,PVS-Studio 將僅針對新的或更改的程式碼發出警告。 而且,這一切都是巧妙實施的。 例如,如果在原始碼檔案的開頭添加一個空白行,那麼分析器就會明白,實際上什麼都沒有改變,並且將繼續保持沉默。 此標記檔案可放入版本控制系統中。 文件很大,但這不是問題,因為經常儲存它沒有意義。

現在,所有程式設計師都會看到僅與新程式碼或更改程式碼相關的警告。 因此,正如他們所說,您可以從第二天開始使用分析儀。 您可以稍後返回技術債務,並逐步修正錯誤並配置分析器。

這樣,在大型舊專案中實施分析器的第一個問題就已經解決了。 現在讓我們弄清楚如何處理技術債。

錯誤修復和重構

最簡單、最自然的事情就是留出一些時間來分析大量被抑制的分析器警告並逐步處理它們。 在某個地方你應該修復程式碼中的錯誤,在某個地方你應該重構以告訴分析器程式碼沒有問題。 簡單的例子:

if (a = b)

大多數 C++ 編譯器和分析器都會抱怨這類程式碼,因為他們實際上想要寫的可能性很高 (a==b)。 但有一個不言而喻的約定,而這通常會在文件中註明,即如果有額外的括號,那麼就認為程式設計師故意編寫了這樣的程式碼,無需發誓。 例如,在 PVS-Studio 診斷文件中 V559 (CWE-481) 明確指出以下行將被認為是正確且安全的:

if ((a = b))

另一個例子。 這段C++程式碼中是否忘記了? 打破 或不?

case A:
  foo();
case B:
  bar();
  break;

PVS-Studio 分析儀將在此發出警告 V796 (CWE-484)。 這可能不是一個錯誤,在這種情況下,您應該透過新增屬性給解析器一個提示 [[失敗]] 或者例如 __attribute__((失敗)):

case A:
  foo();
  [[fallthrough]];
case B:
  bar();
  break;

可以說這樣的程式碼修改並沒有修復bug。 是的,這是事實,但它做了兩件有用的事情。 首先,分析儀報告消除了誤報。 其次,程式碼對於參與維護的人員來說變得更容易理解。 這非常重要! 僅此一點,就值得進行一些小的重構,以使程式碼更清晰、更易於維護。 由於分析器不知道是否需要“break”,因此其他程式設計師也不清楚。

除了錯誤修復和重構之外,您還可以專門抑制明顯錯誤的分析器警告。 可以禁用一些不相關的診斷。 例如,有人認為警告毫無意義 V550 關於比較浮點/雙精度值。 有些人將它們列為重要且值得研究的[7]。 哪些警告被認為是相關的,哪些是不相關的,由開發團隊決定。

還有其他方法可以抑制誤報。 例如前面提到的宏標記。 所有這些在文件中都有更詳細的描述。 最重要的是要明白,如果你逐步、有系統地處理誤報,那麼它們並沒有什麼問題。 絕大多數無趣的警告在配置後就消失了,只剩下真正需要仔細研究的地方和程式碼中的一些變更。

此外,如果出現任何困難,我們總是幫助客戶建立PVS-Studio。 此外,在某些情況下,我們自己消除了錯誤警告並糾正了錯誤[8]。 為了以防萬一,我決定提一下,這種擴展合作的選擇也是可能的:)。

棘輪法

還有另一種有趣的方法可以透過消除靜態分析器警告來逐步提高程式碼品質。 最重要的是,警告的數量只會減少。

如何在遺留專案中實現靜態程式碼分析器而不影響團隊積極性

記錄靜態分析儀發出的警告次數。 質量門的配置方式是現在您只能輸入不會增加操作次數的代碼。 因此,逐漸減少警報數量的過程是從調整分析儀和修正錯誤開始的。

即使一個人想作一點小作弊,並決定通過改進舊的第三方代碼而不是消除新代碼中的警告來通過質量關卡,這並不可怕。 儘管如此,棘輪朝一個方向旋轉,缺陷的數量會逐漸減少。 即使一個人不想修復自己的新缺陷,他仍然需要改進相鄰程式碼中的某些內容。 在某些時候,減少警告數量的簡單方法就會結束,而真正的錯誤將會被修復。

Ivan Ponomarev 在一篇非常有趣的文章中更詳細地描述了這種方法“在流程中實作靜態分析,而不是用它來找出錯誤”,我建議任何有興趣提高程式碼品質的人閱讀該書。

文章作者也有關於這個主題的報告:「連續靜態分析".

結論

我希望讀完這篇文章後,讀者能夠更接受靜態分析工具,並希望將其應用到開發過程中。 如果您有任何疑問,我們隨時準備著 建議 我們的靜態分析儀 PVS-Studio 的使用者並協助其實作。

對於靜態分析是否真的方便有用還有其他典型的疑問。 我在《開發過程中引入PVS-Studio靜態程式碼分析器的原因》一書中試圖消除大部分疑慮[9].

感謝您的關注並前來 下載 並嘗試 PVS-Studio 分析儀。

附加連結

  1. 安德烈·卡爾波夫。 如何快速查看 PVS-Studio 分析器為 C 和 C++ 程式碼產生的有趣警告?
  2. 維基百科。 賴斯定理.
  3. 安德烈·卡爾波夫,維多利亞·哈涅娃。 使用機器學習進行程式原始碼靜態分析.
  4. PVS-工作室。 文件. 附加診斷設置.
  5. 安德烈·卡爾波夫。 使用 EFL Core Libraries 範例的 PVS-Studio 分析器的特徵,誤報率為 10-15%.
  6. PVS-工作室。 文件. 分析儀訊息的批次抑制.
  7. 伊凡·安德里亞辛。 關於我們如何測試 X 光血管內手術教育模擬器計畫的靜態分析.
  8. 帕維爾·葉列梅耶夫,斯維亞托斯拉夫·拉茲梅斯洛夫。 PVS-Studio 團隊如何改進虛幻引擎程式碼.
  9. 安德烈·卡爾波夫。 在開發過程中引入靜態程式碼分析器PVS-Studio的原因.

如何在遺留專案中實現靜態程式碼分析器而不影響團隊積極性

如果您想與英語讀者分享這篇文章,請使用翻譯連結:Andrey Karpov。 如何在遺留專案中引入靜態程式碼分析器而不會讓團隊洩氣.

來源: www.habr.com

添加評論