從代碼審查視角看軟件質量
理論基礎
軟件質量是軟件與明確地敘述的功能和性能需求、文檔中明確描述的開發標準以及任何專業開發的軟件產品都應該具有的隱含特性相一致的程度。
作為軟件開發人員怎樣保證所研發的軟件產品是一個高性能、無缺陷的的產品,從開發者的編碼角度考慮,編碼前需要有清晰的架構設計質量和詳細功能流程保證、編碼的時候需要保證所編碼的功能質量,編碼后需要保證測試質量能夠功能能得到驗收。整體架構設計易于擴展、模塊之間耦合性低、易于復用,代碼簡潔易懂,易于維護 是軟件開發者對高質量軟件產品的一個代名詞。
影響軟件質量的整體的因素有:軟件需求缺陷、軟件架構設計缺陷、編碼缺陷、文檔缺陷、錯誤地修復功能問題。
一個高質量的軟件產品,離不開整個團隊多個角色的配合,我認為真正關注軟件質量的角色主要老板、開發管理經理;軟件使用者、軟件需求方;軟件開發團隊。
軟件質量基礎
軟件質量從軟件開發者的視角,它主要細分為:過程質量、結構質量、功能質量。
過程質量這個主要涉及到:及時的交付軟件、不超出軟件開發成本預算、可信地交付軟件。
結構質量這個主要涉及到:代碼的可維護性、代碼的可理解性、代碼性能、代碼安全性、代碼可測性。
功能質量這個主要涉及到:滿足架構設計的需求、軟件沒有功能缺陷、軟件有足夠好的性能、軟件易于學習和使用。
結構質量和功能質量的提升主要依賴于做合理的架構設計審查、代碼審查。
解決或提升軟件質量的方案:對架構設計審查、代碼審查、單元測試、新功能驗證測試、壓力測試、系統測試、客戶現場功能驗證。
高質量的代碼設計
1、合理的代碼模塊層級;
2、代碼需綜合考慮、約束:各模塊的大小、模塊的復雜度、接口的大小、模塊之間的共享資源;
3、高內聚低耦合:消除重復功能代碼、分離代碼變化方向、縮小代碼依賴范圍、向穩定的方向依賴;
4、代碼統一的代碼風格:代碼樣式的統一、命名風格統一、詞匯的統一;
5、整潔代碼:代碼可讀性高、沒有壞味道、代碼保存簡單和直接原則、功能類或函數盡可能小;
6、熟悉開發語言和標準庫函;
7、可信安全編碼:代碼內存安全、資源安全、線程安全;
8、避免代碼中出現未定義行為;
9、防止代碼緩存溢出:檢查緩沖區長度大小、探測內存、調用安全的系統函數(例如strcpy、strcat是不安全的,strncpy、strncat是安全的:它們通過限制緩沖區的數據大小 來保證緩存安全);
10、防止堆棧溢出:檢查空指針、檢查返回值、檢查字符串類型轉換、輸入數據的檢查、內存分配的檢查;
11、整數安全:有符號和無符號混用檢查;
12、避免代碼邏輯漏洞。
如何做代碼審查
1、結對編程:通過相互技術分享、技術傳播能夠有效的防止編碼錯誤,但是這種結對編程的人力成本相對較高。
2、組織正式的代碼審核會議:為試圖尋找代碼的缺陷提供一種非常結構化的流程,通過會議形式,它還可以用于發現軟件需求缺陷和軟件設計缺陷,這種方式代碼審查效果較好。
3、代碼走查:通常由經驗豐富的工程師對需要審查的代碼進行檢查,這種方式人力成本相對較低。
4、基于靜態代碼分析:基于文本和模式匹配(通過檢查對代碼規范的遵守),基于源代碼抽象語法樹的分析(檢查代碼中數據類型問題、未初始化問題;檢測進行控制流和數據流分析)。
5、基于動態代碼分析:根據代碼功能需求構建測試用例、使用覆蓋率檢查工具檢查用例對代碼的覆蓋率、使用動態代碼檢查工具檢查代碼;
6、靜態代碼和動態代碼分析工具:結合靜態分析工具和動態分析工具,有效利用各種工具長處,更早發現代碼問題;
7、代碼審查三要素:代碼度量分析、靜態代碼檢查、動態代碼檢查
代碼審查重點
1、代碼規范的檢查:檢查軟件產品中的代碼風格是否統一、代碼中是否存在不符合規范的代碼。
2、代碼度量檢查:檢測軟件中代碼的復雜度、代碼嵌套的深度、代碼扇入扇出度量(面向對象中扇入指的是派生類的梳理,面向對象中扇出指由一個類衍生出類的數量)、代碼繼承樹的深度(DIT繼承深度)、類的加權方法、對象間的耦合度
3、代碼設計缺陷檢查:代碼中是否存在空指針、是否存在內存溢出的代碼、代碼類型轉換是否存在錯誤、函數的返回局部變量的引用、代碼中未定義的行為、代碼中是否存在申請的內存空間未釋放、線程死鎖、線程競爭。
4、代碼壞味道檢查:代碼中的函數功能太長、代碼中函數中過長參數列表、類功能和數據過于龐大、啞數據類和對象(啞數據就是不含有行為,只有數據的對象)、代碼中switch表達式過于太長太驚悚、代碼中平行的繼承體系、代碼中存在重復代碼。
5、代碼和設計需求是否存在背離情況
6、代碼是否符合架構的設計
代碼度量分析
1、代碼中函數的復雜度過大:可能代碼中函數本身實現過于復雜、可能因為架構設計過于復雜,導致代碼中函數功能過于復雜;
2、函數嵌套過多或過深的情況:函數很有可能出錯、需要仔細進行人工評審代碼;函數需要進行重構(使用衛戍句進行優化代碼邏輯;優化條件邏輯;提取函數;架構設計出現壞味道,需要重構架構);
3、注釋比例過低(注釋和語句比例或注釋和圈復雜度的比例):在代碼中有些復雜的邏輯需要添加一定的注釋說明,否則影響代碼的可理解性和可閱讀性。
4、模塊的扇入過大:代碼中的模塊是公共模塊,需要進行人工評審模塊接口是否是穩定和安全;模塊承擔過多職責,應該考慮遵循單一職責,分解模塊的職責;
5、模塊的扇出過大:檢查代碼中是否有多個模塊都依賴于本模塊所依賴的幾個模塊,應該把被依賴的多個模塊合并為一個模塊,進行重構依賴的接口;
6、類的繼承樹過深:應該考慮在代碼的繼承樹的深度上是否有新的變化方向;考慮設計新的策略類,或設計其他模塊實現優化繼承樹過深問題;
7、子類過多:檢查子類的實現中是否有共同的地方,先考慮提出公共的中間子類;檢查是否可以通過Bridge模塊、裝飾模式、組合模式等結構型模式重構代碼。
使用提權函數降低函數復雜度,用表驅動的方式降低圈復雜度、利用多態減少圈復雜度
認知代碼復雜度:嵌套越深、復雜度越高;判斷條件越復雜、復雜度越高;遞歸增加復雜度、break增加復雜度。
靜態代碼審查
靜態代碼檢測一般需要借助靜態檢測工具例如:SourceMonitor、 CCCC(代碼復雜度檢查工具)、Embold、SonarQube、cppcheck等等。
通過這些工具可以靜態檢測代碼中的:代碼行數、語句數目、函數數目、函數深度、類的梳理、注釋語句比例、繼承樹深度等等。
靜態代碼檢測的主要作用:代碼規范檢查、代碼bug檢查、代碼性能檢測、代碼壞味道檢測(過長的參數列表,過長的函數)。
靜態檢查雖然能夠幫助檢測出一些代碼的缺陷(代碼bug),但是對于檢查規則覆蓋的代碼、能夠工作更好;對于檢查規則沒有覆蓋的代碼,那么就無能為力,并且會存在一定概率誤報的情況。
動態代碼審查
動態的代碼檢測同樣也是需要借鑒工具進行對代碼動態分析,動態代碼檢測工具例如:Valgrind、GCC、Clang等等,通過運行軟件進行動態檢測代碼,可以讓內存問題、線程死鎖、線程競爭、未定義的行為更容易的暴露出來,動態檢測和單元測試、功能測試、系統測試相結合,可以提高檢測的覆蓋率,可以挖掘出更多代碼中的bug。
動態檢測代碼作用
1、能夠準確定位問題,誤報率相對比較低;
2、動態檢測和測試用例綁定在一起,查找缺陷比例與測試用例的覆蓋率有關;
3、對于沒有覆蓋到的錯誤,動態分析也無能為力;
4、嵌入式系統會存在內存資源的限制;
5、應該要動靜結合,多種檢測手段結合,能夠更有效提升代碼質量。
總結
提高軟件質量是作為開發人員的一個很重要的指標,通過多維度的論述軟件質量問題,并且從軟件開發者視角看討論如何寫出高質量的軟件。最后再從代碼審計的代碼度量分析、靜態代碼檢查和動態代碼檢查相結合,去分析如何挖掘出軟件的的種種問題,從而提高軟件質量。
文章來源:安全脈搏
本文作者:小道安全
文本鏈接:https://www.secpulse.com/archives/178005.html
了解更多資訊:http://www.tamaki-nami.com/news1/