轉(zhuǎn)帖|實(shí)施案例|編輯:鄭恭琳|2020-07-21 14:48:51.083|閱讀 122 次
概述:編碼規(guī)則幫助您提高代碼質(zhì)量,生成一致代碼,防止易錯(cuò)編碼風(fēng)格。為克服嚴(yán)峻的軟件開發(fā)挑戰(zhàn)并同時(shí)減少開發(fā)成本,軟件工程領(lǐng)域已經(jīng)形成了自己的規(guī)則慣例,如需求工程分析、設(shè)計(jì)技術(shù)、制程開發(fā),等等。許多規(guī)則慣例都應(yīng)用于開發(fā)的實(shí)際執(zhí)行階段,如編碼規(guī)則、代碼重構(gòu)、代碼檢查、靜態(tài)分析。其中,編碼規(guī)則是基礎(chǔ),它能夠很好地提高代碼可靠性,幫助不同的開發(fā)人員都生成一致的代碼,并防止易出錯(cuò)編碼方式的出現(xiàn)。 三星電子重點(diǎn)著眼于通過定義并強(qiáng)制執(zhí)行內(nèi)部編碼規(guī)則來提高代碼質(zhì)量。
# 界面/圖表報(bào)表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關(guān)鏈接:
編碼規(guī)則幫助您提高代碼質(zhì)量,生成一致代碼,防止易錯(cuò)編碼風(fēng)格。Robert Buckley對MISRA-C和編碼規(guī)則添加了一個(gè)注釋。本文作者JunHo和YoonKyu是三星電子軟件實(shí)驗(yàn)室的工程師。
為克服嚴(yán)峻的軟件開發(fā)挑戰(zhàn)并同時(shí)減少開發(fā)成本,軟件工程領(lǐng)域已經(jīng)形成了自己的規(guī)則慣例,如需求工程分析、設(shè)計(jì)技術(shù)、制程開發(fā),等等。許多規(guī)則慣例都應(yīng)用于開發(fā)的實(shí)際執(zhí)行階段,如編碼規(guī)則、代碼重構(gòu)、代碼檢查、靜態(tài)分析。其中,編碼規(guī)則是基礎(chǔ),它能夠很好地提高代碼可靠性,幫助不同的開發(fā)人員都生成一致的代碼,并防止易出錯(cuò)編碼方式的出現(xiàn)。
三星電子重點(diǎn)著眼于通過定義并強(qiáng)制執(zhí)行內(nèi)部編碼規(guī)則來提高代碼質(zhì)量。我們QA部門使用了一個(gè)編碼標(biāo)準(zhǔn)一致性檢查器來實(shí)現(xiàn)這個(gè)目的,但我們并沒有規(guī)范全部地將這個(gè)初始檢查工具應(yīng)用到我們的軟件開發(fā)過程中去。因?yàn)檫@個(gè)工具功能不強(qiáng),所以我們只是在最后的審核階段才偶爾用一下它。因此我們只看到了它對代碼質(zhì)量的提高起到了一丁點(diǎn)兒的作用。
最近,我們評估了Parasoft的C++TEST,并應(yīng)用它到我們正在進(jìn)行的開發(fā)項(xiàng)目“MOBILE”中。在本文中,我們將從中學(xué)習(xí)到的經(jīng)驗(yàn)和大家一起分享。在本文中,一個(gè)“編碼規(guī)則條目”是指一個(gè)在公司編碼規(guī)則和一致性文檔中描述的總的描述條,一個(gè)“編碼規(guī)則”(或“規(guī)則”)是指一個(gè)在自動(dòng)化編碼規(guī)則工具中制訂的具體的編碼規(guī)則。
三星電子是一個(gè)主要的消費(fèi)電子公司。盡管三星以主營硬件起家,軟件也迅速成為了我們一個(gè)主要的關(guān)注中心,正如大多數(shù)其他的消費(fèi)電子廠商一樣。這個(gè)“MOBILE”項(xiàng)目是三星的一個(gè)電子C/C++開發(fā)項(xiàng)目,它是要開發(fā)出一個(gè)用于移動(dòng)設(shè)備的可重用、可擴(kuò)展的面向?qū)ο蟮能浖蚣堋N覀兊?/span>QA部門是一個(gè)獨(dú)立出來專門測試三星電子開發(fā)出來的軟件的。我們投入了相當(dāng)多的時(shí)間來評估自動(dòng)化工具,以求能最大地減少重復(fù)的工作量。
這個(gè)MOBILE項(xiàng)目使用一套源于總的三星編碼規(guī)則并針對這個(gè)項(xiàng)目特別指定的編碼規(guī)則。這套MOBILE項(xiàng)目規(guī)則可以通過改變語言變量和其他開發(fā)約束條件來進(jìn)行改寫。比如,在MOBILE項(xiàng)目中的一些編譯器不支持對異常情況的處理。因此,當(dāng)一個(gè)對象的構(gòu)造器被調(diào)用的時(shí)候,不可能偵測到資源分配失敗。為解決這個(gè)問題,我們在 MOBILE 項(xiàng)目中采用了大家熟知的 two-phase object construction(二階段對象構(gòu)造)技術(shù)(在 MOBILE 項(xiàng)目編碼規(guī)則中有描述):將一個(gè)對象的初始化分為對象分配階段和資源分配階段,以通過一個(gè)值的方式返回異常情況(見代碼清單 1)。
class ResourceManager { ResourceManager(); // allocate only object result Construct(); // allocate resources // 'result' contains error code }; int main() { // Two phase construction ResourceManager aObject; if (aObject.Construct() == FAIL) printf("Resource allocation is failed"); }
代碼清單 1
另外,這個(gè)MOBILE項(xiàng)目需要對編碼規(guī)則進(jìn)行嚴(yán)格恪守。這個(gè)項(xiàng)目主要目標(biāo)是建成一個(gè)軟件框架給其他開發(fā)人員使用;它必須是一致的、組織良好的,以使得軟件開發(fā)能夠很好地在這個(gè)框架上進(jìn)行。越多的項(xiàng)目涉及進(jìn)來,就越需要一個(gè)自動(dòng)化的工具。這就是為什么MOBILE項(xiàng)目要采用一個(gè)編碼規(guī)則檢察器。
Parasoft的C++TEST(www.parasoft.com)提供了自動(dòng)的C/C++單元測試,和自動(dòng)化的編碼規(guī)則檢查。我們選擇 C++TEST作為我們的編碼規(guī)則檢查器,是因?yàn)樗鼘τ谖覀兊拇蠖鄶?shù)考慮來說是最有效的解決方案。
C++TEST 的一個(gè)明顯的特點(diǎn)就是它的基于圖形化界面的規(guī)則。如圖 1 顯示了對規(guī)則“每個(gè)全程變量必須進(jìn)行初始化”的圖形化界面規(guī)則描述,在分析源代碼時(shí),每當(dāng)發(fā)現(xiàn)一個(gè)“全程變量”,這條規(guī)則便會(huì)評估邏輯組件。如果以下條件中的任何不相符合,程序就會(huì)報(bào)告有一個(gè)代碼違規(guī):
圖 1: Parasoft C++test中基于圖形化界面的編碼規(guī)則
圖形化界面簡化了規(guī)則創(chuàng)建。大多數(shù)的C++代碼檢查器在創(chuàng)建規(guī)則時(shí)需要編寫腳本;這有一定的難度,并要求更多的C++編程知識。
因?yàn)楝F(xiàn)有的條件是圖形化顯示的,所以基本圖形化界面的規(guī)則能被容易地理解和執(zhí)行。通過基于圖形化界面的規(guī)則可以有更好的可擴(kuò)展性,因?yàn)橥ㄟ^圖形化界面只有預(yù)定義的節(jié)點(diǎn)和條件可以選擇。
我們的選擇標(biāo)準(zhǔn)包括產(chǎn)品使用特點(diǎn),但不是特點(diǎn)的細(xì)節(jié)(規(guī)則選擇、規(guī)則執(zhí)行、可量測性)。我們通過以下途徑來建立這些標(biāo)準(zhǔn):以前的使用編碼規(guī)則檢查器的經(jīng)驗(yàn),項(xiàng)目開發(fā)部門的反饋,產(chǎn)品評估報(bào)告。
能很靈活地修改規(guī)則:大多數(shù)編碼規(guī)則檢查器包括預(yù)執(zhí)行的規(guī)格。擁有內(nèi)含的規(guī)則可以減少規(guī)則執(zhí)行的工作量。但是這些規(guī)則通常并不完全符合我們的編碼風(fēng)格。而且,因?yàn)榇蠖嘁?guī)則中是簡單地執(zhí)行,不實(shí)的報(bào)錯(cuò)是常見的事,因而使得結(jié)果不具可靠性。我們需要一個(gè)簡單的方法來自定義規(guī)則以排除異常情況,添加新的規(guī)則或者修改已存在的規(guī)則。類似于LINT的工具可以檢查一些編碼規(guī)則項(xiàng),但缺少規(guī)則自定義的特點(diǎn)。盡管有些檢查器也能為規(guī)則自定義提供參數(shù)修改,但我需要更多的靈活性來修改詳細(xì)規(guī)則。
能在不同的級別上報(bào)告編碼規(guī)則的遵守程度:許多編碼規(guī)則檢查器支持文件級別的報(bào)告。然而,出于管理目的,文件包級和項(xiàng)目級的報(bào)告成為管理者們所希望有的。比如,要項(xiàng)目經(jīng)理經(jīng)常希望按文件包或項(xiàng)目來瀏覽編碼規(guī)則違規(guī)以編碼規(guī)則違規(guī)的趨勢和對編碼規(guī)則違規(guī)校正的優(yōu)先級別,特別是在項(xiàng)目工期快要到了的時(shí)候。
能與開發(fā)環(huán)境相集成:許多規(guī)則違規(guī)能被很容易地校正。比如,像“使用 TAB 而不是空格進(jìn)行縮進(jìn)”之類的違規(guī)可以通過簡單地用TAB替換空格就可以校正。在這樣的情形中,有一個(gè)可以直接訪問違規(guī)源代碼(通過與開發(fā)環(huán)境緊密集成)的編碼規(guī)則檢查器,就可以非常有效地減少校正所需要的時(shí)間。
另外,當(dāng)一個(gè)工程向前推進(jìn)的時(shí)候,它將所含更多的文件和更的"include/directive"設(shè)定。如果檢查器不在IDE內(nèi)運(yùn)行,那么檢查器就要通過導(dǎo)入或同步IDE項(xiàng)目文件(如MAKEFILES,DSP/DSW文件等)來創(chuàng)建工程文件。
能為 C/C++創(chuàng)建統(tǒng)一的規(guī)則:我們的主要的編程語言,C和C++,有一個(gè)相似的結(jié)構(gòu)(除了C++具有更多的基于對象的和類屬性編程)。在兩種語言上為相同的項(xiàng)維護(hù)兩種不同的規(guī)則將需要額外的資源。
能夠識別語言變量:相比C,C++的歷史比較短。編譯器提供商們在ISO C/C++發(fā)布以前產(chǎn)出了他們自己人的 C++編譯器,并且研究顯示,許多 C++的實(shí)際應(yīng)用并不能很好地支持 C++ ISO 標(biāo)準(zhǔn)(//www.ddj.com/184405483)。因?yàn)榫幋a規(guī)則檢查器經(jīng)常分析源代碼,所以能識別語言變量就顯得非常重要了。
能檢查未經(jīng)預(yù)編譯的頭文件:一些編碼規(guī)則檢查器缺少對頭文件的直接檢查,取而代之的是,在頭文件中的代碼違規(guī),是通過檢查在預(yù)編譯執(zhí)行的文件中的頭文件進(jìn)行間接地報(bào)告。在這種情況下,一些代碼違規(guī)被忽略了,如在頭文件中與預(yù)處理程序指令和注釋相關(guān)代碼違規(guī),這里通常包含一些被其他開發(fā)人員使用的重要信息。所以,直接對頭文件的檢查是一個(gè)我們所希望的功能。
應(yīng)用一個(gè)編碼規(guī)則檢查器可以減少在應(yīng)用中的編碼標(biāo)準(zhǔn)違規(guī)。然而,偵測和消除的違規(guī)數(shù)量取決于目標(biāo)工程的特點(diǎn)和編碼規(guī)則的質(zhì)量。我們發(fā)現(xiàn)每個(gè)工程都有其相似的整體傾向,但同時(shí)又有影響編碼規(guī)則檢查的不同細(xì)節(jié)。因些,得出來的結(jié)果應(yīng)該被看成是一個(gè)趨勢而不是一個(gè)確定的樣式。
直接的利益是指減少違規(guī)數(shù)量是如何提高代碼質(zhì)量的。
非直接利益是指其他不曾預(yù)料到的帶給開發(fā)人員的好處。
圖 2 顯示了編碼違規(guī)數(shù)量的總體趨勢。為消除規(guī)則不斷發(fā)展帶來的影響,我們使用最新的規(guī)則來進(jìn)行所有的檢查。在一個(gè)從10月4日到1月5日間相對穩(wěn)定的違規(guī)數(shù)量之后,在2月5日有一個(gè)大約1/8的違規(guī)減少。從2月5日到3月5日間,有一個(gè)不希望有的違規(guī)增加,但這是可以接受的,因?yàn)槟繕?biāo)項(xiàng)目仍在繼續(xù)向前推進(jìn)。
圖 2:總的違規(guī)數(shù)量/每千行代碼
圖 3 顯示了違規(guī)校正對只對當(dāng)前模塊有影響的違規(guī)數(shù)量。從采用檢查器之日起,違規(guī)數(shù)量減少了6.6個(gè)百分比。這個(gè)數(shù)量沒有包括注釋規(guī)則——這通常不會(huì)有大的變化影響但確實(shí)是需要重要的進(jìn)行變更的工作。
圖 3:小變化違規(guī)數(shù)量/每千行代碼
圖 4 顯示了校正不只影響當(dāng)前模塊的違規(guī)數(shù)量。從引入檢查器以來,違規(guī)減少了19.6個(gè)百分點(diǎn)。
圖 4:有大的改變影響的違規(guī)的數(shù)量/每千行代碼
代碼規(guī)則檢查給我們帶來的一個(gè)意外收獲,就是它對開發(fā)人員的教育和知識能力提升。新的開發(fā)人員,甚至是一些有經(jīng)驗(yàn)的開發(fā)人員,在開始的時(shí)候不大理解一些編碼規(guī)則項(xiàng)的意義和重要性。比如,編碼規(guī)則項(xiàng)“最好進(jìn)行初始化而不是分配”是被認(rèn)為是一個(gè)有效的方法來初始化一個(gè)構(gòu)造函數(shù)中的成員變量(可參考:《Effective C++》,作者:Scott Meyers,Addison-Wesley,1992)。一些開發(fā)人員不理解為什么在一個(gè)構(gòu)造函數(shù)的列表中對成員進(jìn)行初始化要比在構(gòu)造函數(shù)體中對成員分配初始化值要更好。他們在查看檢查器的檢查結(jié)果時(shí)討論這些問題。這就最終幫助開發(fā)人員完全理解了 C++的特點(diǎn),并且也展示了編碼規(guī)則檢查是如何幫助開發(fā)人員,使他們從犯錯(cuò)中進(jìn)行學(xué)習(xí)成長的。
另一個(gè)間接帶來的好處就是去除了那些不切實(shí)際的編碼規(guī)則項(xiàng)。當(dāng)我們應(yīng)用編碼規(guī)則一項(xiàng)目MOBILE中去的時(shí)候,我們發(fā)現(xiàn)大多數(shù)開發(fā)人員并不遵守這條規(guī)則即“每行不要80格”,這條規(guī)則的產(chǎn)生是因?yàn)橛行├系拈_發(fā)環(huán)境是80格顯示。我們檢查了我們的開發(fā)環(huán)境并得出結(jié)論:在我們的條件下,這種有限制的開發(fā)環(huán)境很少使用,我們建議一行使用更長的格。”所有我們將一行的格數(shù)限制從80格改到150格。這種編碼規(guī)則修改也可以提高開發(fā)人員對遵守編碼規(guī)則的接受程度。
直到最近以前,我們的檢查還只是QA部門在工程級別上檢查是否遵守編碼規(guī)則。這對于追蹤缺陷傾向和維護(hù)一套規(guī)則是有效果的。但是會(huì)有一些缺點(diǎn)。
首先,報(bào)告的違規(guī)來源并不總是開發(fā)環(huán)境中的那段代碼。開發(fā)人員通常并不在一個(gè)集中的源碼庫中操作,他們在自己的區(qū)域進(jìn)行書寫和修改代碼,然后復(fù)制或check-in源碼到集中的代碼庫中。如果開發(fā)源碼和QA測試的代碼不一樣,那么開發(fā)人員要識別和修改報(bào)告違規(guī)的來源就比較困難了。
再者,開發(fā)人員希望立即能夠驗(yàn)證到對于違規(guī)的校正已經(jīng)消除了存在的問題。
基于這些原因,我們決定要讓開發(fā)人員和QA一樣可以運(yùn)行編碼規(guī)則檢查工具。
那些不認(rèn)真遵守規(guī)則的開發(fā)人員會(huì)產(chǎn)生很多有違規(guī)的代碼,并且也通常不會(huì)去校正這些代碼違規(guī)。這是尤其會(huì)產(chǎn)生與識別或設(shè)計(jì)相關(guān)的違規(guī)問題,這樣會(huì)使得在以后的開發(fā)階段來校正這些錯(cuò)誤非常困難,因?yàn)槟菚r(shí)進(jìn)行這樣的校正會(huì)有一個(gè)較大的,整個(gè)工程范圍的影響。所以我們推薦將編碼規(guī)則檢查從早期的編碼階段就開始,這樣違規(guī)代碼就能在傳出模塊之前就得到校正。
為什么我們以前的工具沒能在編碼規(guī)則檢查上發(fā)揮效應(yīng)的也是因?yàn)樵谡麄€(gè)組織級別上缺乏對規(guī)則的維護(hù)。
在一套初始規(guī)則建立之后,規(guī)則應(yīng)該得到不斷的修改定義,因?yàn)槟承┮?guī)則也許不適用于特定的項(xiàng)目,開發(fā)風(fēng)格會(huì)根據(jù)開發(fā)的領(lǐng)域不同而會(huì)有改變。一套規(guī)則應(yīng)在項(xiàng)目不斷往前推進(jìn)的過程中根據(jù)項(xiàng)目的具體操作而進(jìn)行不斷的維護(hù)更新。
自動(dòng)的編碼規(guī)則檢查是對代碼走查的一個(gè)補(bǔ)充。在我們的開發(fā)過程中,代碼走查是強(qiáng)制的,因?yàn)檫@樣可以有效地找出開發(fā)人員的邏輯錯(cuò)誤和失誤。然而,開發(fā)人員也會(huì)因?yàn)楣て谔o的壓力跳過代碼走查。根據(jù)我們的經(jīng)驗(yàn)和研究顯示,一些開發(fā)人員很容易被一些編碼風(fēng)格問題弄得很頭痛,并在代碼走查的過程中花很多工夫到這個(gè)上面(參見:D. Kelly 和 T. Shepard 編寫的"Qualitative Observations from SoftwareCode Inspection Experiments"一書; CASCON, 2002),從而,一些開發(fā)人員將代碼走查看作是一件耗時(shí)卻收效甚微的工作,并不跳過這一步。這種情形可以通過在代碼走查之前使用自動(dòng)化的代碼規(guī)則檢查來消除代碼違規(guī)的方法來進(jìn)行避免。這樣的話,在代碼走查的時(shí)候我們就能將精力集中在發(fā)現(xiàn)邏輯錯(cuò)誤和嚴(yán)重錯(cuò)誤上來。而且,自動(dòng)化的檢查只能涉及到我們編碼規(guī)則項(xiàng)中的大約 50%(一些規(guī)則項(xiàng)用自動(dòng)化工具具體執(zhí)行起來非常復(fù)雜),所以代碼走查需要用來檢查剩余的規(guī)則項(xiàng)。
我們應(yīng)用 C++TEST 到了我們幾個(gè)項(xiàng)目中并在每個(gè)項(xiàng)目中都取得了很好代碼質(zhì)量提高效果。我們準(zhǔn)備將其應(yīng)用到更多的項(xiàng)目中去,用其分析代碼的質(zhì)量。
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請郵件反饋至chenjj@fc6vip.cn