怎么能有效的預(yù)防軟件開(kāi)發(fā)中出現(xiàn)臭蟲(chóng)(Bug)
在軟件開(kāi)發(fā)中出現(xiàn)Bug似乎是再正常不過(guò)的事情了。作為軟件開(kāi)發(fā)工程師,誰(shuí)敢說(shuō)自己寫(xiě)的代碼沒(méi)有出現(xiàn)過(guò)Bug。甚至有的程序員自嘲自己的開(kāi)發(fā)工作是在寫(xiě)B(tài)ug。所以,在軟件開(kāi)發(fā)中出現(xiàn)Bug太正常了。但是,你有沒(méi)有考慮過(guò),如何在軟件開(kāi)發(fā)中預(yù)防出現(xiàn)Bug?
我們知道Bug發(fā)現(xiàn)的越早成本越低,發(fā)現(xiàn)的越晚,成本越高。估計(jì)很多人沒(méi)有這個(gè)體會(huì),也有很多人有這個(gè)體會(huì)。這對(duì)于小規(guī)模的代碼其實(shí)不太明顯,但大規(guī)模的,復(fù)雜的軟件就非常明顯。因?yàn)樵诖a量非常大的情況下,抓出一個(gè)Bug并非容易的事情。
示例
別說(shuō)大規(guī)模代碼了,大家看看這個(gè)下面代碼。這個(gè)代碼中print_gender用于根據(jù)參數(shù)打印性別字符串。但是在實(shí)際使用的時(shí)候發(fā)現(xiàn)打印的總是man,而無(wú)法打印woman,大家能看出問(wèn)題在哪嗎?

現(xiàn)在代碼比較少,估計(jì)很多人一下子就看出來(lái)了。但是如果在一個(gè)規(guī)模非常大的函數(shù)中找到類(lèi)似的錯(cuò)誤還是比較困難的。
看到?jīng)]?
是的,就是函數(shù)中if語(yǔ)句中的條件寫(xiě)錯(cuò)了。其實(shí)這個(gè)是一個(gè)非常低級(jí),而且很容易產(chǎn)生的錯(cuò)誤。我們?cè)诳焖俚那面I盤(pán)的時(shí)候,很有可能漏了一個(gè)等號(hào),就產(chǎn)生這個(gè)結(jié)果了。
- if ( is_male = true )
如何盡早發(fā)現(xiàn)問(wèn)題
盡早發(fā)現(xiàn)問(wèn)題當(dāng)然是最好的,但是能早到什么時(shí)候呢?如何盡早發(fā)現(xiàn)問(wèn)題呢?
最早的時(shí)間點(diǎn)應(yīng)該是編譯器編譯的時(shí)候。我們?cè)趯?xiě)代碼的時(shí)候經(jīng)常會(huì)出現(xiàn)編譯器無(wú)法通過(guò)的情況。如果我們能夠?qū)⒊绦虻腻e(cuò)誤能夠在該階段解決,那么自然是非常好的,但卻不可能全部在這個(gè)階段解決。我們可以做到盡量在這個(gè)階段來(lái)解決。
比如前面的錯(cuò)誤,我們是可以借助編譯器在編譯階段來(lái)搞定的。聰明的你知道如何做嗎?
我們可以將上面的if語(yǔ)句寫(xiě)成如下的樣子:
- if ( true = is_male )
也就是將常量寫(xiě)到前面,而變量寫(xiě)到后面。這樣,如果缺少等號(hào)的情況下就會(huì)出現(xiàn)編譯錯(cuò)誤。因?yàn)槲覀兪菬o(wú)法為一個(gè)常量賦值的。如果沒(méi)有缺少等號(hào)的情況下是可以編譯通過(guò)的。
這里只是一個(gè)例子,我們可以在很多地方借助編譯器來(lái)提高我們的代碼質(zhì)量,而避免在后期出現(xiàn)邏輯的錯(cuò)誤。我們?cè)倥e一個(gè)例子。
在C/C++中const是經(jīng)常用到的關(guān)鍵字,比如下面這個(gè)store_name函數(shù),我們本來(lái)是想將傳入的參數(shù)存儲(chǔ)在函數(shù)中的臨時(shí)變量,然后進(jìn)行后續(xù)的分析。但是由于馬虎,將strcpy的參數(shù)搞反了。如果在參數(shù)中使用了const關(guān)鍵字,則可以起到預(yù)防的作用,從而避免錯(cuò)誤。

可以看出,通過(guò)這種方式可以有效的避免開(kāi)發(fā)中由于低級(jí)錯(cuò)誤而產(chǎn)生的軟件Bug。而且由于問(wèn)題會(huì)比較早的發(fā)現(xiàn),整個(gè)修復(fù)的成本會(huì)低很多。