隨著科技的進步,顧客的期望也隨之提高。嵌入式裝置變得越來越聰明,相關系統和軟體也越來越複雜,即使開發時程縮短,開發高品質軟體仍是產品成功的關鍵。本篇文章將討論如何在日常開發中系統性地提升程式碼品質。
什麼是程式碼品質?
程式碼品質是衡量程式碼效能的一個標準,用來區分「優良」的程式碼(高品質)和「不良」的程式碼(低品質)。雖然對程式碼品質沒有單一的定義,但通常會透過幾個指標來評估:
- 可讀性:程式碼應該清晰且易於理解。
- 可靠性:程式碼應該盡可能少有缺陷(最好沒有)。
- 可測試性:程式碼應該易於測試。
- 可重用性:程式碼應該促進透過功能凝聚性進行重複使用。
- 可維護性:程式碼應該易於更新和維護。
- 可擴展性:程式碼應該促進彈性,便於增加新功能。
- 可攜性:程式碼應該能夠輕鬆移植到不同的硬體平台上。

如何提升程式碼品質?
提升程式碼品質是一個持續的過程,而非一次性任務。以下是幾項有效的策略:
- 遵循程式設計規範:這些規範包括公司特定的(例如程式風格和命名規則)和業界通用的(如MISRA、CERT和CWE)。
- 靜態程式碼分析:檢查並強制執行符合您選定的程式設計規範。
- 單元測試:通常稱為功能測試,單元測試用來檢查程式碼是否符合設計並確保程式碼功能的正確性。
- 程式碼審查:這有助於增進開發者之間的協作,並幫助檢查程式碼中的邏輯問題。
- 使用版本控制:利用版本控制管理程式碼變更歷史,並促進團隊合作,有助於維護建構的重複性。
- 採用CI/CD:CI/CD自動化構建、分析和單元測試,簡化開發過程,同時提高構建重複性。
為何需要在日常開發中提升程式碼品質?
在日常開發階段提升程式碼品質,有助於及早發現並修復錯誤,顯著降低修復成本。以下是來自Capers Jones的書籍《Applied Software Measurement: Global Analysis of Productivity and Quality》中,關於錯誤注入、檢測及修復成本的圖表。圖中有兩個非常重要的觀察:
- 大部分錯誤是在日常開發(程式設計)階段注入的。
- 錯誤發現的時間越早,修復越容易,修復成本也越低;反之,發現錯誤越晚,修復越困難且成本更高。
晚期發現的錯誤更昂貴,因為該缺陷會扭曲您的軟體發佈指標。您發現錯誤的越晚,為了達成發表指標,您需要投入更多測試工作。因此,在日常開發(程式設計)階段提升程式碼品質,不僅能減少初期注入的缺陷數量,還能幫助儘早發現其他錯誤。這種程式碼品質的雙重效應顯著降低了專案中的軟體錯誤成本。
如何提升日常開發中的程式碼品質?
提升程式碼品質可能一開始看起來令人畏懼,但當您使用品質工具時,這個過程會變得更加容易。以下是一些幫助您快速提升程式碼品質的建議:
建構:0錯誤,0警告
達到「0錯誤,0警告」在建構過程中至關重要。錯誤會使建構失敗,而警告雖不會使建構失敗,但可能表示潛在的隱藏錯誤。
下圖是一個經典的編譯器警告:比較運算子 == 應該用於代替賦值運算子 =:

修改後重建:0錯誤,0警告

靜態程式碼分析
在成功建構並且達到「0錯誤,0警告」後,強烈建議進行靜態程式碼分析。靜態程式碼分析檢查程式碼中常見的問題,這些問題通常會讓開發者在日常編碼過程中踩到陷阱。而且,使用品質工具進行靜態程式碼分析非常簡單。
在IAR Embedded Workbench中,您只需要先選擇對應的C-STAT檢查:

接著,您可以使用C-STAT對整個專案進行靜態程式碼分析:

您也可以對單一檔案使用C-STAT進行靜態程式碼分析:

分析完成後,相應的C-STAT訊息視窗會顯示對應的結果。雙擊相關訊息,即可查看其在程式碼中的位置:

IAR C-STAT工具的另一個實用功能是其上下文關聯協助。您可以在C-STAT訊息視窗中高亮顯示某一違規項,並按下F1來獲取更多關於該違規的資訊。這包含了違規的詳細描述、列出該違規的程式設計規範、嚴重性/確定性矩陣,以及最重要的—範例,展示了錯誤在程式碼中的樣貌,並如何修正這些錯誤。
這些範例可以幫助您更容易地定位並修正自己程式碼中的問題:

利用上下文關聯協助中的資訊,您推測需要將程式碼中的4u更改為(int32_t) 4。一旦完成更改,當再次進行靜態程式碼分析時,您會發現先前的違規已經修正:

一項由Google進行並由ACM發表的案例研究顯示,,獲得程式碼回饋與實際回饋本身一樣重要。當回饋是即時的(或接近即時時),開發者會將這些回饋視為需要處理的問題,並且74%的時間會用於處理。如果回饋是延遲的(例如,由於它是夜間建構的一部分),那麼這個比例降到21%。
作者認為,這是由於程式碼的「倖存者效應」,意味著承認這個問題確實是一個錯誤,會對他們的發表指標產生不利影響。IAR C-STAT使開發者能在桌面檢查程式碼時(也就是在程式碼進入建構過程之前),找到並修正這些錯誤,從發佈指標的角度看,這些錯誤仿佛從未發生過。
單元測試
靜態程式碼分析後,強烈建議進行單元測試,因為靜態程式碼分析只能檢查程式碼是否遵循相關的程式設計規範,而單元測試則是用來測試程式碼功能是否正確。
IAR本身並未提供單元測試工具,但IAR有多個合作夥伴提供這類單元測試工具。有時候,缺陷只會在執行時顯現,並且在模組之間進行相互呼叫時出現。為了協助測試這些情況,IAR C-RUN執行時檢查有助於在單元測試過程中發現潛在問題。
在IAR Embedded Workbench中,您只需要選擇對應的C-RUN執行時檢查規則:

重建後,編譯器會在潛在錯誤發生的地方自動插入對應的測試程式碼。
執行時,C-RUN會檢測程式碼是否未通過插入的檢查。例如,以下C-RUN訊息提示存在越界存取違規:

對應的陣列大小為4,但[4]代表的是第5個元素,這導致了越界存取違規。修改程式碼後,我們可以再次運行測試,查看程式碼似乎運行正常,沒有違規發生:

程式碼審查
在單元測試後,強烈建議邀請同事進行程式碼審查。建議在進行程式碼審查前,完成「0錯誤,0警告」的建構、靜態程式碼分析和單元測試,以提高程式碼審查的效率。人工審查是最昂貴的程式碼測試類型,因此您應該僅對已經通過所有先前測試的程式碼進行這種測試。
CI/CD


程式碼審查後,建議將程式碼上傳至伺服器,讓CI/CD進行自動化建構、靜態程式碼分析和單元測試。
IAR提供對應的自動化工具IAR Build Tools,透過命令列執行自動化建構、靜態程式碼分析和下載與除錯(針對單元測試):
結論
隨著程式碼品質越來越受顧客重視,最早採用程式碼品質最佳實踐的公司已證明它們能夠在提高開發者生產力的同時,按時、按預算交付專案。然而,並非每家公司都發現這些最佳實踐:
- 有些公司完全依賴最終產品測試,並未意識到靜態程式碼分析、單元測試和程式碼審查的價值。
- 有些公司雖然購買了很好的靜態程式碼分析和單元測試工具,但這些工具未能在日常開發中得到充分使用,反而將測試工作交給軟體QA團隊(在那裡所有的缺陷會計入發表指標),或是僅在軟體發表後才對整個專案進行靜態程式碼分析和單元測試。
- 有些公司尚未部署CI/CD,認為這會造成不必要的複雜性。然而,開發者的時間非常寶貴,公司應該盡力自動化建構、靜態程式碼分析和單元測試,以便讓開發者能夠儘早收到反饋。
本文以IAR Embedded Workbench和IAR Build Tools(包括C-STAT靜態程式碼分析和C-RUN執行時檢查)為例,介紹開發者如何在日常開發中提升程式碼品質。值得注意的是,本文中提到的IAR Embedded Workbench和IAR Build Tools(包括C-STAT靜態程式碼分析和執行時檢查)僅為工具範例,本文中的方法也適用於其他工具。
選擇適當的工具至關重要,但更重要的是,開發人員需要在日常開發中充分利用選定的工具來提升程式碼品質。由於大多數錯誤都會在日常開發(程式設計)階段導入,錯誤發現越早,修復越容易,修復成本越低;反之,錯誤發現越晚,修復就越困難且成本更高。
邁向下一步
使用先進的開發解決方案提升您的嵌入式專案,探索IAR Embedded Workbench for Arm、IAR Build Tools,並利用C-STAT靜態程式碼分析和C-RUN執行時檢查確保程式碼品質。
本文由 iar 提供