代碼審查技術(shù)_第1頁
代碼審查技術(shù)_第2頁
代碼審查技術(shù)_第3頁
代碼審查技術(shù)_第4頁
代碼審查技術(shù)_第5頁
已閱讀5頁,還剩145頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、代碼審查技術(shù)學(xué)習(xí)目標(biāo) 掌握代碼分析和評審技術(shù) 掌握自動(dòng)化代碼分析工具的使用建筑工程師的第一堂課-關(guān)注細(xì)節(jié)關(guān)注并弄清楚橋梁修建細(xì)節(jié),否則你建起來的橋就有可能坍塌。-安全編程 代碼靜態(tài)分析1940年Tacoma Narrows大橋600英尺的一段坍塌落入普吉特灣。代碼審查對成本的節(jié)省黑盒測試的缺陷 黑盒測試既不充分,而且效率也低。 在系統(tǒng)完成之前,測試就無法開始,測試人員只有軟件版本發(fā)布時(shí)才能拿到版本進(jìn)行測試。Static white-box testing Find bugs early Find bugs that would be difficult to uncover or isolat

2、e with dynamic black-box testing Cost effective Side benefit:give black-box tester ideas for test cases to apply when they receive the software for testing不懂開發(fā)怎么做代碼審查?霍元甲霍元甲因?yàn)樗救松眢w虛弱,所以父親從小不讓練武功,而生長在那樣的環(huán)境中,他天天可以看到兄弟們在練功,招式已經(jīng)記憶在心里,但是苦在沒有練功的機(jī)會,他利用體力勞動(dòng)的過程中,改變勞動(dòng)方式,趁機(jī)練功,后來發(fā)展到獨(dú)創(chuàng)“迷蹤拳”。代碼靜態(tài)分析 靜態(tài)分析是指在不執(zhí)行的情況下

3、對代碼進(jìn)行評估的過程。包括:- 類型檢查- 風(fēng)格檢查- 程序理解- BUG查找- 安全審查靜態(tài)分析 - 類型檢查在Java中,下面的語句雖然符合類型檢查規(guī)則,但是會在運(yùn)行時(shí)失敗,拋出一個(gè)ArrayStoreException異常:Object objs = new String1;objs0 = new Object();/lint -w2/lint +e734#include stdafx.hint main()char ch = 0;int n = 0;/.ch = n;return 0;VC6編譯通過,但是PCLint可以通過靜態(tài)代碼檢查找出類型轉(zhuǎn)換造成的精度丟失問題靜態(tài)分析 - 風(fēng)格檢

4、查 常見工具C/C+:PC-LintJAVA:PMD.NET:StyleCop風(fēng)格檢查更加挑剔,也更加注重空格、縮進(jìn)、命名、注釋、程序結(jié)構(gòu)這些表面的東西。風(fēng)格檢查程序所展示的錯(cuò)誤往往都是影響代碼的可讀性和可維護(hù)性的問題。typedef enum red, green, blue Color;char *getColorString( Color c)char *ret = NULL;switch( c )case red:printf( red );return ret;gcc的“-Wall”選項(xiàng)將檢查出其中的問題。typedef const char *CSTRING;CSTRING rev

5、ere( int lights )CSTRING manner = by land;if( lights 0 )if( lights = 2 ) manner = by sea;else manner = ;return manner;int main()printf( The British are coming %sn, revere( 1 ) );return 0;靜態(tài)分析 - 程序理解 程序理解工具能幫助我們搞懂代碼庫中的大量代碼,洞察程序運(yùn)轉(zhuǎn)之道。 集成開發(fā)環(huán)境(IDE)一般至少都包含某些程序理解功能,例如:“查找本方法的所有應(yīng)用”。 常用工具:- 代碼流程圖:Code Visual

6、 to Flowchart- UML與源代碼雙向工程,例如FujabaFujiaba 能在UML視圖和源代碼之間來回轉(zhuǎn)換靜態(tài)分析 - Bug查找 BUG查找的目的不像風(fēng)格檢查那樣抱怨格式方面的問題,而是根據(jù)“BUG慣用法”(規(guī)則)來描述代碼中潛在的缺陷。 常用工具:PMD、FindBugs、Coverity、KlocworkEmptyCatchBlock:Empty Catch Block finds instances where an exception is caught, but nothing is done. In most circumstances, this swallows

7、 an exception which should either be acted on or reported. Example: public void doSomething() try FileInputStream fis = new FileInputStream(/tmp/bugger); catch (IOException ioe) string str = ; for (int i = 0; i h_name , tHost , sizeof(tHost ) ) )trusted = true;elsetrusted = false;黑名單 vs. 白名單 黑名單法(bl

8、ack listing):嘗試枚舉所有不能接受的輸入值。 白名單法(white listing):通過已知正確值清單來進(jìn)行檢查。下面是摘自Tomcat5-1.31版本中的一段程序,采用了一個(gè)黑名單,假定在Web頁面中只有4個(gè)特殊的字符輸入才會導(dǎo)致程序的安全問題:for( int i=0; i content.length; i+ )switch ( contenti )case :resule.append(>);break;case &:resule.append(&);break;case :resule.append(");brea

9、k;default:result.append(contenti); 黑名單法只拒絕已知惡意的數(shù)據(jù),而在給定環(huán)境中,惡意值的集合通常是難于枚舉的(或者可能是無限的),所以黑名單法一般是不完善的。 即使可能列出一個(gè)危險(xiǎn)輸入值的完整清單,也很可能隨著時(shí)間的變遷而過時(shí)。黑名單法是不利于應(yīng)用程序安全的。審查緩沖區(qū)溢出錯(cuò)誤 緩沖區(qū)溢出(buffer overflow):將大量數(shù)據(jù)塞入一個(gè)較小的緩沖區(qū)中所導(dǎo)致的程序漏洞 緩沖區(qū)溢出通常被攻擊者用于重寫內(nèi)存中的數(shù)據(jù)。 近10年來,緩沖區(qū)溢出漏洞的數(shù)量沒有明顯下降的趨勢。void trouble()int a =32;char line128;gets(lin

10、e); 緩沖區(qū)溢出就是將長度超過緩沖區(qū)大小的數(shù)據(jù)寫入程序的緩沖區(qū),造成緩沖區(qū)的溢出,從而破壞程序的堆棧,使程序轉(zhuǎn)而執(zhí)行其他指令。 當(dāng)一個(gè)超長的數(shù)據(jù)進(jìn)入到緩沖區(qū)時(shí),超出部分就會被寫入其他緩沖區(qū),其他緩沖區(qū)存放的可能是數(shù)據(jù)、下一條指令的指針,或者是其他程序的輸出內(nèi)容,這些內(nèi)容都被覆蓋或者破壞掉??梢娨恍〔糠?jǐn)?shù)據(jù)或者一套指令的溢出就可能導(dǎo)致一個(gè)程序或者操作系統(tǒng)崩潰。天生危險(xiǎn)的函數(shù) gets、cin、scanf、 strcpy、wcscpy、lstrcpy sprintf、fprintf、swprintf禁用函數(shù)列表Linux和Windows平臺上替換C類庫的字符串解決方案GNU/Linux Bstr

11、lib: http:/ FireString: /wordpress/projects/firestring GLib: /doc/API/2.0/glib/index.html Libmib: http:/ Vstr: /vstr Safe CRT: http:/ SafeStr: /safestr審查整數(shù)溢出錯(cuò)誤 當(dāng)一個(gè)整數(shù)值大于或者小于其范圍時(shí),就會產(chǎn)生整數(shù)溢出錯(cuò)誤(integer overflow)?!盎乩@”unsigned lo

12、ng readamt;readamt = getstringsize();if( readamt 1024 )return -1;readamt-;buf = malloc( readamt );如果getstringsize返回0,則readamt-1將等于4294967295(無符號32位整數(shù)的最大值),這個(gè)操作可能會因?yàn)閮?nèi)存不足而失敗。檢測整數(shù)溢出IntSafe數(shù)學(xué)函數(shù) 對于C語言,微軟開發(fā)了IntSafe類庫,它可以幫助檢測和防止整數(shù)操作中的漏洞 IntSafe函數(shù)庫包含200多個(gè)轉(zhuǎn)換函數(shù)審查異常處理錯(cuò)誤char buf10,cp_buf10;fgets(buf,10,stdin);s

13、trcpy(cp_buf,buf); 如果發(fā)生I/O錯(cuò)誤,fgets將不給buf添加NULL終止符。在buf中缺少NULL終止符將可能會導(dǎo)致在后續(xù)的strcpy調(diào)用時(shí)發(fā)生緩沖區(qū)溢出。Try catch finally C+和Java都支持try/finally的語法。不論異常是否拋出,finally模塊總是在try模塊后執(zhí)行。 但是,如果finally模塊包含一個(gè)return語句,將抑制異常拋出。審查資源泄漏問題 未能及時(shí)釋放資源(包括數(shù)據(jù)庫對象、文件句柄和套接字)可能會導(dǎo)致嚴(yán)重的性能問題。 在C程序中,在單個(gè)函數(shù)體中查找多個(gè)return語句,通常是分布式錯(cuò)誤處理代碼的標(biāo)志,也是資源泄漏的滋生

14、地。 函數(shù)有多個(gè)出口時(shí),沒有在每個(gè)出口處對動(dòng)態(tài)申請的內(nèi)存進(jìn)行釋放。一般在異常處理時(shí)容易出現(xiàn)這種錯(cuò)誤。下面的代碼段就是這樣的例子:.pRecord = new charpTable-GetRecordLength();assert(pRecord != NULL);if (pTable-GoTop(FALSE) != DBIERR_NONE)return; / 如果從這里返回,pRecord將得不到釋放.pTable-Close();delete pRecord;char * getBlock( int fd ) char * buf = (char *)malloc( BLOCK_SIZE )

15、;if ( !buf )return NULL;if ( read (fd,buf ,BLOCK_SIZE ) != BLOCK_SIZE )return NULL;return buf;如果read調(diào)用失敗,將導(dǎo)致已經(jīng)分配的buf內(nèi)存泄漏!tryStatement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery(CXN_SQL);harvestResult( rs );stmt.close();catch( SQLException e)logger.log( Level.ERROR ,” error execut

16、ing sql query” , e ); 如果在執(zhí)行SQL或處理結(jié)果時(shí)出現(xiàn)了異常,那么stmt對象將不能被關(guān)閉。假如這種情況經(jīng)常發(fā)生,數(shù)據(jù)庫將耗盡可用的指針,不能執(zhí)行任何其他的查詢。C/C+代碼審查 C/C+語言編碼規(guī)范 C/C+常見代碼問題檢測循環(huán)語句的效率for (row=0; row100; row+) for ( col=0; col5; col+ ) sum = sum + arowcol; 在多重循環(huán)中,如果有可能,應(yīng)當(dāng)將最長的循環(huán)放在最內(nèi)層,最短的循環(huán)放在最外層,以減少CPU 跨切循環(huán)層的次數(shù):for (col=0; col5; col+ )for (row=0; row100

17、; row+)sum = sum + arowcol;指針的使用 _UC *puc_card_config_tab; . . Get_Config_Table( AMP_CPM_CARD_CONFIG_TABLE, &ul_card_config_num, &puc_card_config_tab, use_which_data_area );. . b_middle_data_ok = generate_trans_middle_data_from_original_data( puc_card_config_tab, Ul_card_config_num). .分配資源是否

18、正確釋放void WarnSvr:SaveWarnData() .for( int m = 0;m Csn = BufferEVENT_ALARMm.Csn; item-Position = m + ( RecordsInHistoryFile - RecordsInBufferEVENT_ALARM );/If a warn with a certain Csn is not in EventFilterIndex,it is not necessary to be added to HistoryFilterIndexint item_total = EventFilterIndex.Ge

19、tItemsInContainer();BOOL find_flag = false;for (int k = 0; k Csn = item-Csn ) find_flag = true; break;if( find_flag ) HistoryFilterIndex.Add( item );if( HistoryFilterIndex.IsFull() ) ClearIndexEntry(); PC-Lint LINT工具是一種軟件質(zhì)量保證工具,許多國外的大型專業(yè)軟件公司,如微軟公司,都把它作為程序檢查工具,在程序合入正試版本或交付測試之前一定要保證通過了LINT檢查,他們要求軟件工程師

20、在使用LINT時(shí)要打開所有的編譯開關(guān),如果一定要關(guān)閉某些開關(guān),那么要給出關(guān)閉這些開關(guān)的正當(dāng)理由。 PC-LINT是GIMPEL SOFTWARE公司的產(chǎn)品,其中的內(nèi)容是非常廣泛的,光是選項(xiàng)就有30 0多個(gè),涉及到程序編譯及語法使用中的方方面面。練習(xí):PC-Lint的安裝和使用1:2: char *report( short m, short n, char *p )3: 4: int result;5: char *temp;6: long nm;7: int i, k, kk;8: char name11 = Joe Jakeson;9:10: nm = n * m;11: temp = p

21、 = ? null : p;12: for( i = 0; i 0 ) result = 1;16: else if( kk 0 ) result = -1;17: if( m = result ) return temp;18: else return name;19: /* Off-By-One Example */#include int main() int i; int a = 1,2,3; int n = sizeof(a)/sizeof(int); for(i=0;i=n;i+) printf(a%d=%dn,i,ai); return 0;#define NStu 3000#d

22、efine NCrs 400extern int const StuCourseNStuNCrs;extern double const CostBookNCrs;double total_cost() int i, j; double cost = 0; for( i = 0; i NStu; i+ ) for( j = 0; j NCrs; i+ ) cost += StuCourseij * CostBookj; return cost;JAVA代碼審查代碼審查和語法錯(cuò)誤檢查是兩個(gè)不同層次的概念。語法錯(cuò)誤是低層次、強(qiáng)制性的檢查,任何違反語法的程序都是無法通過編譯的,也就是說可運(yùn)行的程序必

23、須是語法正確的。而代碼審查是高級別,非強(qiáng)制性的檢查,它對語法正確的程序施加了更高更嚴(yán)格的要求,從而提升程序的可讀性、降低因變量命名、方法定義、程序邏輯的不完整性等問題而導(dǎo)致程序的潛在出錯(cuò)機(jī)率,增加程序的可維護(hù)性和健壯性。 switch Statement Should Include a Default Case 1. switch (formatType)2. 3. case 1:4. formatStr = yyyyMMddHHmmss;5. break;6. case 2:7. formatStr = yyyy-MM-dd HH:mm:ss;8. break;9. case 3:10.f

24、ormatStr = yyyy.MM.dd HH:mm:ss;11.break;12.case 4:13.formatStr = yyyy年MM月dd HH:mm:ss;14.break;15. 根據(jù)Sun的編碼規(guī)范,每個(gè)switch流程控制語句都必須帶一個(gè)default分支,以保證邏輯分支的完整性。 如果沒有第1516行的default代碼,代碼審查將給出警告。 1. switch (formatType)2. 3. case 1:4. formatStr = yyyyMMddHHmmss;5. break;6. case 2:7. formatStr = yyyy-MM-dd HH:mm:

25、ss;8. break;9. case 3:10.formatStr = yyyy.MM.dd HH:mm:ss;11.break;12.case 4:13.formatStr = yyyy年MM月dd HH:mm:ss;14.break;15.default:16.formatStr = yyyy-MM-dd HH:mm:ss;17. Accessing Static Members by the Descendant Class Name1. public class ASMO12. 3. void func()4. 5. ASMO1 obj1 = new ASMO1();6. ASMO2

26、 obj2 = new ASMO2();7. obj1.attr = 10; 8. obj2.attr = 20; 9. obj1.oper(); 10. obj2.oper(); 11.this.attr+;12.this.oper();13.14. 15.static int attr;16.static void oper()17.18. 19. 20. class ASMO221. 22. static int attr;23. static void oper()24. 25. 類中所有的靜態(tài)方法或變量都應(yīng)該通過類名來引用,如果通過類的實(shí)例來引用這些靜態(tài)的成員將影響到程序的可讀性可讀

27、性。如果通過類名來引用靜態(tài)變量,將容易分辨出這些成員的靜態(tài)屬性。因?yàn)轭愳o態(tài)成員變量在JVM中僅存在一份,而非每個(gè)對象實(shí)例各自一份,因此靜態(tài)成員變量可以看成類的成員。Complex Assignment 1. int i = 0;2. int j = 0;3. int k = 0;4. int l = 0;5. i *= +j;6. 7. k = j = 10;8. 9. l = j += 15;10.11. i = j+ +20;12. 13. i = (j = 25) + 30;14. 15. i = j+ + 20;16. 17. i = (j = 25) + 30;往往有些程序員熱衷于將

28、Java的語法發(fā)揮到極致,以資其對Java語法精通的憑據(jù)。如果是為了練習(xí)語法、理解語法,無可厚非。但如果在需要充分協(xié)作溝通的軟件項(xiàng)目中,簡潔明了,清晰易懂將會受到推崇,晦澀難懂的語句將會受到奚落。故此,大部分的軟件公司的規(guī)范都對語句的精簡明了精簡明了提出了要求。Complex Initialization or Update Clauses in for Loops1.for (i = 0, j = 0, k = 10, l = -1; i 10; i+, j+, k-, l += 2)2. 3./do something4. 由于for循環(huán)控制語句的高度靈活性,所以for()中的代碼往往是復(fù)

29、雜晦澀代碼的樂園,在for語句中以逗號分隔的賦值語句最多不應(yīng)超過3個(gè):1. for (i = 0, j = 0, k = 10, l = -1; i 10; i+, j+, k-, l += 2)2. 3. /do something4. 5. /應(yīng)改寫成下面的樣式6. /l = -1;7. /for (i = 0, j = 0, k = 10; i cnt; i+, j+, k-)8. /9. / /do something10. / l += 2;11. /Use Abbreviated Assignment Operator 1. void oper () 2. int i = 0;3.

30、 i = i + 20; 4. i = 30 * i; 5. 在可能的情況下使用縮減賦值運(yùn)行符(*=, /=, %=, +=, -=, =, &=, =, 和|=),因?yàn)檫@些語句能夠提高編碼錄入的速度,增強(qiáng)代碼的簡潔性簡潔性,同時(shí)縮減賦值運(yùn)行符使某些編輯器運(yùn)行得更快。 1. void oper () 2. int i = 0;3. i = i + 20; 4. i = 30 * i; 5. 6. /應(yīng)改寫成應(yīng)改寫成7. /void oper ()8. /9. / int i = 0;10. / i += 20; 11. / i *= 30; 12. /Coding Style:- Mu

31、ltiple Statements on One Line - Place Statement in Block - Use L instead of l at the End of Integer Constants 1. i+; j+;2 3. if (val = 10)6.val /= 10;7. 8. void func () 9. long var = 0 x0001111l;10. 不應(yīng)將多行語句寫在同一行代碼中。 代碼塊應(yīng)以“”框起來,雖然增長了代碼,但代碼結(jié)構(gòu)性結(jié)構(gòu)性更強(qiáng)。 聲明長整型使用大寫的“L”類型指定符,而非小寫的“l(fā)”,因?yàn)楹笳吆蛿?shù)字1相似。Hiding Names

32、1. public class HideName2. 3. int index;4. void func()5. 6. int index;7. / do something8. 9. void setIndex(int index)10. 11. this.index = index; 12. index+; 13. 14. 類成員變量被局部變量隱藏:因類方法體中的局部變量和類成員變量具有相同的名字,而使成員變量被屏蔽 1. public class HideName2. 3. int index;4. void func()5. 6. int index;/隱藏了成員變量隱藏了成員變量in

33、dex,應(yīng)改成另一個(gè)名字,應(yīng)改成另一個(gè)名字,如如int newIndex;7. / do something8. 9. void setIndex(int index)10. 11. this.index = index; /該語句行中帶this顯式引用成員變量進(jìn)行賦值,審查規(guī)則將不報(bào)警 12. index+;/該語句行沒有該語句行沒有this顯式引用,審查規(guī)則將報(bào)警顯式引用,審查規(guī)則將報(bào)警13. 14. Hiding Inherited Field 1. class Window2. 3. protected int style;4. 5. 6. class Button extends W

34、indow7. 8. protected int style;9. 子類成員變量隱藏父類成員變量:子類成員變量和可繼承的父類成員變量名字相同。 1. class Window2. 3. protected int style;4. 5. 6. class Button extends Window7. 8. protected int style;/具有和父類相同的成員變量,應(yīng)改具有和父類相同的成員變量,應(yīng)改為另一個(gè)名字,如為另一個(gè)名字,如anStyle9. Hiding Inherited Static Methods 1. class Animal2. 3. static void ope

35、r1()4. static void oper2()5. 6. 7. class Elephant extends Animal8. 9. static void oper1() 10. static void oper2() 11. 子類覆蓋父類靜態(tài)方法:和非靜態(tài)的方法覆蓋不一樣,靜態(tài)的父類方法不應(yīng)被子類覆蓋。成員變量和局部變量的隱藏,常常會使開發(fā)人員張冠李戴,犯一些不經(jīng)意的錯(cuò)誤,而子類隱藏父類的成員和靜態(tài)變量常常是由于沒有注意到父類中已經(jīng)具有相同的名字而引起的,由此而生產(chǎn)的程序Bug由于其隱身性強(qiáng),是很難被發(fā)現(xiàn)。1. class Animal2. 3. static void oper1(

36、)4. static void oper2()5. 6. 7. class Elephant extends Animal8. 9. static void oper1() /隱藏了父類中的靜態(tài)方法,應(yīng)取另一個(gè)名字,如隱藏了父類中的靜態(tài)方法,應(yīng)取另一個(gè)名字,如anOper1()10. static void oper2() /隱藏了父類中的靜態(tài)方法,應(yīng)取另一個(gè)名字,如隱藏了父類中的靜態(tài)方法,應(yīng)取另一個(gè)名字,如anOper2()11. Use Conventional Variable Names 1. void method(double d) 2. 3. int i;4. Exception

37、 e;5. char s;6. Object f;7. String k;8. Object UK;9. Object COM;10. 避免用過于簡單的變量名避免用過于簡單的變量名除了循環(huán)體中的臨時(shí)變量,及一些沒有特殊意義的常見數(shù)據(jù)類型,應(yīng)該盡量避免使用一個(gè)字符作為變量。那些無特殊意義且常見的數(shù)據(jù)類型,所選取的單字符變量名必須按表1進(jìn)行命名。為了減少潛在的沖突,避免不必要的混淆,不允許以大寫域名或國家代碼作變量名。1. void method(double d) 2. 3. int i;4. Exception e;5. char s;/應(yīng)該改為應(yīng)該改為c6. Object f;/應(yīng)該改為應(yīng)該

38、改為o7. String k;/應(yīng)該改為應(yīng)該改為s8. Object UK;/和英國國家代碼相同,應(yīng)改為其他的名字,如和英國國家代碼相同,應(yīng)改為其他的名字,如ukObj9. Object COM;/和域名相同,應(yīng)改為其他的名字,如和域名相同,應(yīng)改為其他的名字,如obj_110. Break Statement is Missing before Case clause 1. switch (c) 2. case +:3. .4. break;5. case -:6. .7. case n:8. .9. case : case t:10. .11. break;12. 根據(jù)Sun編碼慣例,程序入

39、口點(diǎn)從一個(gè)case進(jìn)入,直接到達(dá)下一個(gè)case代碼段。前一個(gè)case沒有對應(yīng)的break語句時(shí),在跨過的地方必須給出一個(gè)顯示的注釋,表示是特定流程控制的要求,而非無意遺漏。 Non-Case Label in Switch statement 1. public class CaseLabel2. 3. /*點(diǎn)*/4. public static final int POINT = 1;5. /*線*/6. public static final int LINE = 2;7. /*多邊形*/8. public static final int POLYGON = 3;9. 10.public

40、 String getFigureType (int kind)11. 12. String tempName = null;13. switch (kind)14. 15. case POINT:16. LINE:17. tempName = POINT and LINE;18. break;19. case POLYGON:20. tempName = POLYGON;21. break;22. default:23. tempName = UNDEFINE;24. 25. return tempName;26. 27. 在switch中出現(xiàn)非case的標(biāo)簽:在Java語句中有兩個(gè)標(biāo)簽,即

41、case分支標(biāo)簽,另一個(gè)則是語句標(biāo)簽,如果case分支標(biāo)簽語句誤刪或遺漏了case關(guān)鍵字,則case分支標(biāo)簽將變成語句標(biāo)簽,而編譯器無法識別這個(gè)錯(cuò)誤。 Suspicious Break/Continue 1. void scan(char arr)2. 3. loop:4. for (int i = 0; i arr.length; i+)5. 6. switch (arri)7. 8. case 0:case 1:case 2:case 3:case 4:9. /56的數(shù)字10. case 5:case 6:case 7:case 8:case 9:11. 12. if (processDi

42、git(arri)13. 14. continue loop; 15. 16. else17. 18. break; 19. 20. 21. case :case t:22. 23. processWhitespace(arri);24. continue; 25. 26. default:27. processLetter(arri);28. break;29. 30. 有錯(cuò)誤嫌疑的break和continue:break和continue用于switch和循環(huán)中的跳轉(zhuǎn)控制,break用于提前結(jié)束循環(huán)以及從switch中退出,break的這種“多態(tài)性”使得在循環(huán)體中內(nèi)嵌switch語句時(shí),常

43、會帶來一些隱患。即開發(fā)者本希望退出外層循環(huán),結(jié)果卻只退出內(nèi)層的switch語句而已。Comparing Floating-Point Values1. void calc(double limit)2. 3. if (limit = 0.0)4. 5. System.out.println( the float-point number is exactly 0);6. 7. 避免對浮點(diǎn)值進(jìn)行等值邏輯判斷避免對浮點(diǎn)值進(jìn)行等值邏輯判斷浮點(diǎn)數(shù)都是一定精度的數(shù)據(jù),由于內(nèi)部表示的誤差,往往字面上相同的兩個(gè)浮點(diǎn)數(shù),其內(nèi)部表示也不完全相同。故此應(yīng)避免對浮點(diǎn)值數(shù)進(jìn)行等值邏輯判斷,而應(yīng)采用邏輯比較判斷。 1.

44、 void calc(double limit)2. 3. if (limit = 0.0)/應(yīng)改為通過和較小值比較來判斷,如應(yīng)改為通過和較小值比較來判斷,如if(Math.abs(limit) 0.0000001)4. 5. System.out.println( the float-point number is exactly 0);6. 7. Mixing Logical Operators Without Parentheses 1. boolean a, b, c;2. .3. if (a | b & c) 4. 5. .6. 添加添加()清晰化復(fù)雜的表達(dá)式清晰化復(fù)雜的表達(dá)

45、式寫復(fù)雜的表達(dá)式時(shí)不應(yīng)過度依賴運(yùn)算操作符的計(jì)算優(yōu)先順序,而應(yīng)養(yǎng)成使用“()”的好習(xí)慣,當(dāng)一個(gè)邏輯表達(dá)式由多個(gè)邏輯運(yùn)算組成時(shí),應(yīng)該用“()”劃分不同的部分。1. boolean a, b, c;2. .3. if (a | b & c) /應(yīng)該替換成應(yīng)該替換成if (a | b) & c)4. 5. .6. Member is Not Used 1. public class Unuse2. 3. private String name;4. public Object value;5. 6. private Object getValue()7. 8. return value

46、;9. 10. 11.private void print()12. 13. System.out.println(getValue() + = + value);14. 15. 類中private的成員方法和成員變量不可能在外部類中調(diào)用,如果發(fā)現(xiàn)private的成員變量或方法并沒有在內(nèi)部的protect或public方法中使用,即這個(gè)成員永遠(yuǎn)不會在運(yùn)行期得到引用,而成為一個(gè)無用的成員變量和方法。代碼清單中name變量,getValue()及print()方法都是無用的方法,因?yàn)椴豢赡芡ㄟ^外面的類訪問到這些成員,Unuse也沒有提供調(diào)用這些成員的接口,所以這些成員都可以從類中清除。 Compa

47、rison always produces the Same Result 1. void handleEvent(Event e) 2. if (e != null) 3. .4. if (e = = null) 5. .6. 7. 8. 9. 10. void putChar(char c, boolean isLetter, boolean isDigit) 11. if (isDigit) 12. boolean isLetterOrDigit = isLetter | isDigit;13. .14. 15. 無作為的表達(dá)式無作為的表達(dá)式比較表達(dá)式總是返回相同的值。1. void h

48、andleEvent(Event e) 2. if (e != null) 3. .4. if (e = = null) / 該表達(dá)式的值永遠(yuǎn)都是該表達(dá)式的值永遠(yuǎn)都是false,因?yàn)檫M(jìn)入這個(gè)代碼段,因?yàn)檫M(jìn)入這個(gè)代碼段的的e恒為非空恒為非空5. .6. 7. 8. 9. 10. void putChar(char c, boolean isLetter, boolean isDigit) 11. if (isDigit) 12. boolean isLetterOrDigit = isLetter | isDigit;/該表達(dá)式的值永遠(yuǎn)都是該表達(dá)式的值永遠(yuǎn)都是true13. .14. 15. O

49、peration has No Effect 1. public class NoEffect2. 3. private String name;4. private int index;5. 6. NoEffect(String n, int index)7. 8. = name; 9. this.index = index;10. 11. 12.int getPosition()13. 14. int base = 0;15. return index + base; 16. 17. 18. int getModule()19. 20. int x = 1, y = 2

50、;21. return x % y;22. 23. 無效的算術(shù)運(yùn)算無效的算術(shù)運(yùn)算,例如: 當(dāng)進(jìn)行加法和減法運(yùn)算時(shí),有一個(gè)操作數(shù)是0。當(dāng)進(jìn)行乘法運(yùn)算時(shí),乘法或被被乘數(shù)為1。當(dāng)進(jìn)行除法運(yùn)算時(shí),除數(shù)為1。當(dāng)進(jìn)行取模運(yùn)算時(shí),左邊的操作數(shù)的絕對值比右邊操作數(shù)的絕對值小,此時(shí)xy=x。屬性賦值時(shí),將本身的值賦給自己。Statement is Unreachable 1. int arr = new intsize;2. if (arr = null) 3. 4. return null;5. 流程控制中存在不可到達(dá)的語句流程控制中存在不可到達(dá)的語句有些流程控制由于測試條件恒為false,則流程中的程序無法

51、到達(dá)。1. int arr = new intsize;2. if (arr = null) /由于由于arr不為空,則該測試邏輯不可能通不為空,則該測試邏輯不可能通過,程序無法進(jìn)入該程序塊中過,程序無法進(jìn)入該程序塊中3. 4. return null;5. JBuilder的Code Audits功能的使用JBuilder根據(jù)Sun的編碼規(guī)范及軟件開發(fā)界總結(jié)出的一套行之有效的編碼習(xí)慣,對Java開發(fā)中的編碼風(fēng)格、聲明風(fēng)格、Javadoc文檔注釋、EJB規(guī)范、命名風(fēng)格、潛在錯(cuò)誤、編碼中的畫蛇添足等諸多方面進(jìn)行代碼審查并給出警示,以便開發(fā)人員發(fā)現(xiàn)這些不足和隱患予以及時(shí)更正。C#代碼審查 C#編碼

52、規(guī)范 C#常見代碼問題檢測避免不必要的強(qiáng)制轉(zhuǎn)換public static void UnderPerforming(ArrayList list) foreach(object obj in list) if(obj is Control) Control aControl = obj as Control; / Use aControl. 使用字符串長度屬性測試是否為空字符串string s1 = test; public void EqualsTest() if (s1 = ) Console.WriteLine(s1 equals empty string.); 優(yōu)先使用交錯(cuò)數(shù)組而非多維

53、數(shù)組 int, multiDimArray = 1,2,3,4, 5,6,7,0, 8,0,0,0, 9,0,0,0 ;屬性不應(yīng)返回?cái)?shù)組 public class Test string nameValues; public Test() nameValues = new string100; for (int i = 0; i 100; i+) nameValuesi = Sample; public string Names get return (string) nameValues.Clone(); public static void Main() Test t = new Test

54、(); for (int i = 0; i t.Names.Length ; i+) if (t.Namesi = (SomeName) / Perform some operation. public class PhotoLibraryprivate Photo photos = null;public Photo PhotosgetPhoto copyOfPhotos = new Photophotos.Length;for (int i = 0;i photos.Length; i+)copyOfPhotosi = photosi.Clone();return copyOfPhotos

55、;/ 使用Photos屬性:for (int i=0; i library.Photosi.Height)Console.WriteLine(Landscape);else if (library.Photosi.Width library.Photosi.Height)Console.WriteLine(Portrait);elseConsole.WriteLine(Square);避免過多的繼承 class BaseClass class FirstDerivedClass : BaseClass class SecondDerivedClass : FirstDerivedClass c

56、lass ThirdDerivedClass : SecondDerivedClass class FourthDerivedClass : ThirdDerivedClass class FifthDerivedClass : FourthDerivedClass 避免異常的發(fā)生private void DrawBox(Rectangle rect , Brush brush)Graphics g = this.CreateGraphics();tryg.FillRectangle(brush , rect);catch (ArgumentNullException) g.FillRecta

57、ngle(SystemBrushes.Desktop, rect);finallyg.Dispose();控制異常foreach (string exp in expressions)tryint num = int.Parse(exp);s += num;catch (FormatException)Console.WriteLine(exp + 包含無效的Int32數(shù)值。);catch (OverflowException)Console.WriteLine(exp + 溢出。);注意多個(gè)catch子句的排列順序tryif (path != null)FileStream fstream

58、= File.Open(path , FileMode.Open);/ .catch (ArgumentException)MessageBox.Show(文件名格式不正確或包含非法字符);catch (ArgumentOutOfRangeException)MessageBox.Show(無效的打開文件模式);/ .異常信息的隱藏public AccountInfo SignIn(string userName , byte key)byte savedKey = GetSavedKeyByUserName(userName);tryfor (int i = 0; i savedKey.Le

59、ngth; i+)if (savedKeyi != keyi)throw new InvalidPasswordException(密碼無效。);return GetAccountInfo(userName);catch (IndexOutOfRangeException ex)throw new InvalidPasswordException(密碼無效。, ex);異常提示信息throw new ArgumentOutOfRangeException( age, 年齡不能為負(fù)數(shù)!);訪問控制public struct Personpublic int Age;public class Pr

60、ogrampublic static void main()Person person;person.Age = -3;字段其實(shí)就是結(jié)構(gòu)或類中的普通變量成員。這將意味著,一旦字段被公開,對其的訪問便處于完全失控的狀態(tài)。FxCop FxCop是一款專門用于分析.NET托管代碼程序集的工具。它能檢查.NET代碼是否滿足Microsoft.NET Framework 設(shè)計(jì)規(guī)范。它使用反射、MSIL解析等技術(shù)來分析程序集,可以檢查超過200個(gè)缺陷,包括庫設(shè)計(jì)、本地化、命名規(guī)范、性能、安全等方面的內(nèi)容。 FxCop的使用FxCop命令行運(yùn)行方式 FxCopCmd /f:” F:CNJC6CodeAnalysisTest1CodeAnalysisTest1binDebug C

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論