代碼質量是在軟件滿足了設計功能的前提下,對軟件代碼執行的可靠性、穩定性和高性能的一種更高的要求。如何能夠有效提高代碼質量,又節約程序員查找和修復bug的時間,成了一個難題。白盒測試工具的引入,恰好解決了這一難題。本文將通過多個專題,闡述程序員如何有效利用白盒測試工具,提高代碼質量和開發效率。
提高代碼質量的巨大經濟收益
從提高軟件投資回報的角度出發,企業應在降低開發成本的同時,提高軟件的可用性,這就意味著盡量減少應用程序中的bug和性能缺陷。而由于代碼編寫過程的人為因素,代碼中的bug是不可避免的。據統計,每千行軟件代碼中,就可能存在20到30個bug。在無法避免bug產生的情況下,如何發現并及時消除這些bug,就成了提高軟件投資回報的唯一可行辦法。
首先,我們來看看修復一個bug所需要的成本。在軟件交付周期的不同階段,修復一個bug所需的成本差別非常之大。越是到了軟件交付的后期,修復bug越困難,成本也就越高。從圖1可以看出,在測試階段修復bug的代價是開發階段的幾倍,而一旦產品上線,進入維護期后,所需的代價更是達到幾十倍。
根據國際上的經驗,在測試階段修復一個bug的時間往往要比在代碼編寫階段要多出15到75倍。
因此,越早發現bug,越早解決,企業所付出的代價就越小。我們建議在軟件進入測試階段之前就解決掉大部分的bug,即交付高質量代碼的意義所在。
提高代碼質量的幾個關注點
代碼質量是在程序滿足了設計功能的前提下,對軟件代碼執行的可靠性、穩定性和高性能的一種更高的要求。為了保證交付給測試人員的代碼能夠滿足上述質量方面的要求,在開發階段應該對代碼進行如下方面的測試:
1.靜態代碼分析
為保正團隊內各程序員之間編寫習慣的一致性和規范性,消除容易導致錯誤的語法隱患,通常會制定一系列的編程規范。靜態代碼分析,即要求程序員對所有代碼行進行規范性檢查,消滅潛在隱患,提高代碼的可靠性。
靜態代碼分析的好處在于能發現大量潛在的軟件缺陷。比如下面一段VB .NET代碼中,使用Asc()函數返回ASCII碼。
If (Asc(mChar) <> 13) And (Asc(mChar) <> 10) Then
從語法上分析,這段代碼是完全正確的。但若mChar為空,Asc()就會拋出ArgumentException錯誤,導致程序異?;蛑袛?。因此,從代碼可靠性的角度出發,在使用Asc()之前,應對引用的字符串作判斷,如下:
If Len(strchars) > 0 And strchars <> nothing Then Ascii = Asc(strchars)
這樣,就可以避免潛在的異常錯誤。而類似的這樣問題,IDE的語法檢查通常沒有辦法,只有通過手工或自動化的代碼檢查來發現和解決。
沒有經過靜態分析的程序可能跑起來不錯,而實際上可能像一塊奶酪一樣,滿身是漏洞,問題一出現就很嚴重而且直接面對問題的是可能是最終用戶。
2、代碼覆蓋率分析
只有經過充分測試的代碼,質量才是有保障的。而程序員在做單元測試時,往往很難遍歷所有的分支情況,尤其是程序對錯誤輸入的反應往往被忽略。因此,對代碼的測試覆蓋率分析是保證交付高質量代碼的關鍵。利用一些代碼覆蓋率檢查工具,不僅可以了解代碼的整體測試水平,也能夠指出未經過測試的代碼,給程序員以方向上的指引。
3、運行時內存分析
內存往往是導致嚴重性能故障的根本原因,而一些不良的編程習慣經常會導致運行時的內存泄露。這類問題幾乎無法通過單元測試或功能驗證來發現,而又經常被程序員忽視,直到軟件投入生產后才逐漸暴露出來,這時再查找和修復內存問題就非常困難了。因此,應盡量在代碼交付之前消滅內存問題。運行時內存分析,即在代碼調試階段,對所有對象的內存占用狀態的運行時分析,查找內存泄露的隱患。
運行時內存分析的第一步就是內存使用的監控,以便了解在運行期間,程序對內存的使用和釋放情況,查找程序對內存的不當使用。
如下圖所示,在A點位置,程序穩定運行,對內存的使用也基本穩定。在B點,我們打開程序的某個窗口時,程序使用了更多的內存來儲存新的對象。當窗口關閉時,這些對象被釋放,內存也應隨之釋放。而從圖上B點之后的內存使用情況來看,這些內存并沒有被釋放。因而,可能存在著內存泄露。在C點和D點再次打開前面的窗口,內存還是不斷增加而沒有回收??梢詳喽?,該窗口對應的代碼存在內存泄露的問題。
雖然無論是Java還是.Net,都提供了自動的內存回收機制,但內存泄露仍是引起應用系統性能劣化的一個主要原因。除此之外,運行時的內存分析還應深入的對每個對象、方法的內存占用進行分析,以便為內存使用的優化提供方向。
4、性能分析和優化
代碼的執行效率,直接影響著應用程序的可用性和可靠性。因此,軟件的性能問題應該在開發階段就充分加以考慮,提高代碼的執行效率,而不是把性能問題全部留到壓力測試階段去解決。
性能分析和優化,即要求在代碼提交之間,對每一個功能實現的響應時間以及每個方法的效率進行分析,并對運行效率較低的代碼進行優化,從而提高代碼的整體性能,保證交付高質量的代碼。
程序員總是被要求優化某段代碼,縮短執行時間,但這并不是一件容易的事情。困難就在于,代碼執行是一個非常復雜的過程,包含了太多的分支和無數的方法、代碼行,往往讓程序員無從著手。這就需要借助一些動態的代碼分析工具,幫助程序員了解每個方法及代碼行的執行效率,從而有針對性地對那些執行時間最長的方法或代碼行進行性能改進。動態代碼分析工具應能夠提供諸如運行期間調用了哪些文件、方法、代碼行,每個文件、方法和代碼行的執行時間、對總體運行時間的影響程度等等。有了這些信息,程序員就能夠找出影響執行時間的關鍵路徑,有效改進代碼性能。