翻譯《有關程式設計、重構及其他的終極問題?》——40.開始使用靜態程式碼分析.md
翻譯《有關程式設計、重構及其他的終極問題?》——40.開始使用靜態程式碼分析
標籤(空格分隔):翻譯 技術 C/C++ 作者:Andrey Karpov 翻譯者:顧笑群 - Rafael Gu 最後更新:2018年09月28日
40.開始使用靜態程式碼分析
閱讀一位靜態程式碼分析器的開發者寫的一大段文字,卻不知道如何使用靜態程式碼分析,這是非常奇怪的。所以這次我們就來說說如何使用靜態程式碼分析。
下面的程式碼摘自Haiku專案(從BeOS專案繼承而來)。這段程式碼包含的錯誤被PVS-Studio分析器診斷為:There are identical sub-expressions to the left and to the right of the ‘<’ operator: lJack->m_jackType < lJack->m_jackType(譯者注:大意為“<”操作符兩邊的變數是一樣的)。
int compareTypeAndID(....)
{
....
if (lJack && rJack)
{
if (lJack->m_jackType < lJack->m_jackType)
{
return -1;
}
....
}
解釋
這只是一個平常的打字錯誤,在表示式的右邊,理應是rJack,卻被寫成了lJack。
這種打字錯誤的確比較簡單,但實際產生這種情況的原因卻很複雜,這可能牽扯到程式設計風格等一系列問題,但即使知道什麼問題導致,也無助於解決。大家就是這麼眼睜睜的犯下類似錯誤,你卻無能為力。
很重要的是,我們要意識到,這種問題不是特定的人或者特定的專案才有。毫無疑問,所有人都會犯類似錯誤,即使在正規專案總的專家們也會犯。我說這些是有證據的,你可以看到類似最簡單的A == A這種打字錯誤,都可以在如下專案中被發現:Notepad++,WinMerge,Chromium,Qt,Clang,OpenCV,TortoiseSVN,LibreOffice,CoreCLR,Unreal Engine 4等。
因此這類問題是真實存在的,不光是在實驗室中的學生專案中。當一些人告訴我說那些有經驗的程式設計師不會犯下這類錯誤時,我就給他們傳送了這個連結。
正確的程式碼
if (lJack->m_jackType < rJack->m_jackType)
建議
首先,讓我們說一些無用的敲門:
- 程式設計時要很小心,不要讓錯誤偷溜進你的程式碼(說的好聽,但毫無用處)
- 使用好的程式碼風格(事實上,不存在一種程式設計風格可以避免變數名的拼寫錯誤)
那麼,那些是真正有用的呢:
- 程式碼複查(譯者注:就是我們一般直接使用英文說的code review)
- 單元測試(TDD)(譯者注:TDD就是敏捷開發中的測試驅動)
- 靜態程式碼分析
我不得不說,以上每種策略都有它的長處和短處,這就是為何最好、最有效的辦法就是把他們一起使用。
程式碼複查能幫助我們找出大量的不同錯誤,並且,能幫助我們提高程式碼的可閱讀性。但不幸的是,這種策略的代價時非常昂貴的,而且比較無聊,最後也不能給出一個完全有效複查的保證。比如,下面的程式碼打字錯誤就非常難以被發現:
qreal l = (orig->x1 - orig->x2)*(orig->x1 - orig->x2) +
(orig->y1 - orig->y2)*(orig->y1 - orig->y1) *
(orig->x3 - orig->x4)*(orig->x3 - orig->x4) +
(orig->y3 - orig->y4)*(orig->y3 - orig->y4);
理論上,單元測試可以拯救我們。但只在理論上有這個可能。因為實際上,檢查所有的執行路徑是不現實的;除此之外,一個測試本身也有可能包含錯誤:)
靜態程式碼分析器也會有問題,而且也不是智慧化的。一個分析器可能忽略一些錯誤,另一方面,還有可能顯示一些實際上正確的錯誤。但除了這些問題外,靜態程式碼分析器其實能算得上是一種真正有用的工具,它可以在初期就可以發現大量的錯誤。
一個靜態程式碼分析器可以被用來做價效比高的程式碼複查。使用程式而非程式設計師來做程式碼複查,然後更全面的建議檢查特定的程式碼片段。
當然,我很願意建議大家使用我們開發的PVS-Studio程式碼分析器,但這並非世界上唯一一款程式碼分析器,還有其他很多免費或付費的同類工具。比如你可以嘗試使用一下免費、開源的分析器Cppcheck。你可以在Wikipedia上找到大量的同類工具:靜態程式碼分析工具列表。
注意:
- 錯誤的使用一個靜態程式碼分析器可能反而會讓你頭疼。比如一種典型的錯誤就是“儘量多的得到檢查結果的警告訊息”。這是我經常收到的建議,所以就得到了一個很多很多的錯誤警告列表,對於這種情況,這兩篇文章A和B會有幫助。
- 一個靜態程式碼分析器應該被當成基本工具使用,而不僅僅是每次使用一下,或者當專案情況越來越糟糕了才使用。相關的的解釋可以看C和D這兩篇文章。
真的,嘗試用用靜態程式碼分析工具吧,你會喜歡上他們的,他們是非常好的清潔工具。
最後,我很願意推薦大家讀一下John Carmack的文章:靜態程式碼分析。