軟件開發編碼管理規范_第1頁
軟件開發編碼管理規范_第2頁
軟件開發編碼管理規范_第3頁
軟件開發編碼管理規范_第4頁
軟件開發編碼管理規范_第5頁
已閱讀5頁,還剩38頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

XXXX有限公司

軟件開發編碼管理規范

V。.1(討論稿)

二o二一年十二月

項目研發室

目錄

1.排版........................................................................3

2.注釋........................................................................8

3.標識符命名.................................................................16

4.可讀性......................................................................18

5.變量、結構.................................................................20

6.函數.......................................................................26

7.可測性.....................................................................33

8.程序效率...................................................................36

9.質量保證...................................................................37

10.代碼編輯、編譯、審查.......................................................41

11.代碼測試、維護.............................................................43

1.排版

1-1:程序塊要采用縮進風格編寫,縮進的空格數為4個。

說明:對于由開發工具自動生成的代碼可以有不一致。

1-2:相對獨立的程序塊之間、變量說明之后必須加空行。

示例:如下例子不符合規范。

if(!valid_ni(ni))

(

...//programcode

}

repssn_ind=ssn_data[index].repssn_index;

repssn_ni=ssn_data[index].ni;

應如下書寫

if(!valid_ni(ni))

(

...//programcode

)

repssn_ind=ssn_data[index].repssn_index;

repssn_ni=ssn_data[index].ni;

1-3:較長的語句(>80字符)要分成多行書寫,長表達式要在低優先級操作符處劃分新行,

操作符放在新行之首,劃分出的新行要進行適當的縮進,使排版整齊,語句可讀6

示例;

perm_count_msg.head.len=NO7_TO_STAT_PERM_COUNT_LEN

+STAT_SIZE_PER_FRAM*sizeof(_UL);

act_task_table[frame_id*STAT_TASK_CHECK_NUMBER+index].occupied

=stat_poi[index].occupied;

act_task_table[taskno].duration_true_or_false

=SYS_get_s2cp_statistic_state(stat_item);

report_or_not_flag=((taskno<MAX_ACT_TASK_NUMBER)

&&(n7stat_stat_item_valid(stat_item))

&&(act_cask_table[taskno]jesuk_da(a!=0));

1-4:循環、判斷等語句中若有較長的表達式或語句,則要進行適應的劃分,長表達式要

在低優先級操作符處劃分新行,操作符放在新行之首。

示例:

if((taskno<max_act_task_number)

&&(n7stat_stat_item_valid))

(

...//programcode

)

for(i=0,j=0;(i<BufferKeyword[word_index].word_length)

&&(j<NewKeyword.word_length);i++xj++)

(

...//programcode

}

for(i=0,j=0;

(i<first_word_length)&&(j<second_word_length);

(

...IIprogramcode

)

1-5:若函數或過程中的參數較長,則要進行適當的劃分。

示例:

n7stat_str_pare((BYTE*)&stat_objectr

(BYTE*)&(act_task_table[taskno].stat_object),

sizeof(_STAT_OBJECT));

n7stat_flash_act_duration(stat_item,frame_id*STAT_TASK_CHECK_NUMBER

+index,stat_object);

1-6:不允許把多個短語句寫在一行中,即一行只寫一條語句。

示例:如下例子不符合規范。

rect.length=0;rect.width=0;

應如下書寫

rect.length=0;

rect.width=0;

1-7:if>for>do>while%case、switch^default等語句自占一行,且if、for>

d。、while等語句的執行語句部分無論多少都要加括號{}。

示例:如下例子不符合規范。

if(pUserCR==NULL)return;

應如下書寫:

if(pUserCR==NULL)

(

return;

)

1-8:對齊只使用空格鍵,不使用TAB鍵。

說明:以免用不同的編輯器閱讀程序時,因TAB鍵所設置的空格數目不同而造成程序布

局不整齊,不要使用BC作為編輯器合版本,因為BC會自動將8個空格變為一個TAB

鍵,因此使用BC合入的版本大多會將縮進變亂。

1-9:函數或過程的開始、結構的定義及循環、判斷等語句中的代碼都要采用縮進風格,

case語句下的情況處理語句也要遵從語句縮進要求。

1-10:程序塊的分界符(如C/C++語言的大括號'{,和'>)應各獨占一行并且位于同一

列,同時與引用它們的語句左對齊。在函數體的開始、類的定義、結構的定義、枚舉的定義

以及if、do>whilesswitch、case語句中的程序都要采用如上的縮進方式。

示例:如下例子不符合規范。

for(...){

...//programcode

)

if(...)

…//programcode

voidexample_fun(void)

...〃programcode

}

應如下書寫。

for(,,.)

(

...//programcode

)

if(...)

(

...//programcode

}

voidexample_fun(void)

(

???//programcode

}

1-11;在兩個以上的關鍵字、變量、常量進行對等操作時,它們之間的操作符之前、之后或

者前后要加空格;進行非對等操作時,如果是關系密切的立即操作符(如一>),后不應加空

格。

說明:采用這種松散方式編寫代碼的日的是使代碼更加清晰。

由于留空格所產生的清晰性是相對的,所以,在已經非常清晰的語句中沒有必要再留空

格,如果語句已足夠清晰則括號內側(即左括號后面和右括號前面:不需要加空格,多重

括號間不必加空格,因為在C/C++語言中括號已經是最清晰的標志了。

在長語句中,如果需要加的空格非常多,那么應該保持整體清晰,而在局部不加空格。

給操作符留空格時不要連續留兩個以上空格,

示例:

(1)逗號、分號只在后面加空格。

inta,b,c;

(2)比較操作符,賦值操作符”="、"+=”,算術操作符”+”、”解,邏輯操作符“&&“、

”&“,位域操作符"”等雙目操作符的前后加空格。

if(current_timeMAX_TIME_VALUE)

a=b+c;

a*=2;

a=bA2;

(3)“!”、、“十十“(地址運算符)等單目操作符前后不加空格。

*p=//內容操作"*”與內容之間

flag=JisEmpty;//非操作“!”與內容之間

p=&mem;//地址操作與內容之間

i++;//”+與內容之間

(4)“-”、前后不加空格6

p->id=pid;//”->”指針前后不加空格

(5)if、for、while%switch等與后面的括號間應加空格,使if等關健字更為突

出、明顯。

if(a>=b&&c>d)

2.注釋

2-1:一般情況下,源程序有效注釋量必須在20%以上。

說明:注釋的原則是有助于對程序的閱讀理解,在該加的地方都加了,注釋不宜太多也

不能太少,注釋語言必須準確、易懂、簡潔。

2-2:說明性文件(如頭文件.h文件、.hem文件、.de£文件等)頭部應進行注釋,注釋必須

列出:版權說明、版本號、生成日期、作者、內容、功能、與其它文件的關系、修改日志

等,頭文件的注釋中還應有函數功能簡要說明。

示例:下面這段頭文件的頭注釋比較標準,當然,并不局限于此格式,但上述信息建議

要包含在內。

Copyright(C),1988-1999,laucentTech.Co.,Ltd.

Filename://文件名

Author;Version:Date;//作者、版本及完成日期

Description://用于詳細說明此程序文件完成的主要功能,與其他模塊

//或函數的接口,輸出值、取值范圍、含義及參數間的控

//制、順序、獨立或依賴等關系

Others://其它內容的說明

FunctionList://主要函數列表,每條記錄應包括函數名及功能簡要說明

History://修改歷史記錄列表,每條修改記錄應包括修改日期、修改

//者及修改內容簡述

1.Date:

Author:

Modification:

2.

2-3:源文件頭部應進行注釋,列出;版權說明、版本號、生成日期、作者、模塊目的/功

能、主要函數及其功能、修改日志等Q

示例:下面這段源文件的頭注釋比較標準,當然,并不局限于此格式,但上述信息建議

要包含在內。

Copyright(C),1988-1999,HuaweiTech.Co.,Ltd.

FileName;test.cpp

Author:Version:Date:

Description://模塊描述

Version://版本信息

FunctionList;//主要函數及其功能

1.------

History://歷史修改記錄

<author><version><desc>

David96/10/121.0buildthismoudle

說明;Description一項描述本文件的內容、功能、內部各部分之間的關系及本文件

與其它文件關系等。History是修改歷史記錄列表,每條修改記錄應包括修改口期、修

改者及修改內容簡述。

2-4:函數頭部應進行注釋,列出:函數的目的/功能、輸入參數、輸出參數、返回值、調用

關系(函數、表)等。

示例;下面這段函數的注釋比較標準,當然,并不局限于此格式,但上述信息建議要包

含在內。

Function://函數名稱

Description://函數功能、性能等的描述

Calls://被本函數調用的函數清單

CalledBy;//調用本函數的函數清單

TableAccessed://被訪問的表(此項僅對于牽扯到數據庫操作的程序)

TableUpdated://被修改的表(此項僅對于牽扯到數據庫操作的程序)

Input://輸入參數說明,包括每個參數的作

//用、取值說明及參數間關系。

Output://對輸出參數的說明。

Return://函數返回值的說明

Others://其它說明

2-5:邊寫代碼邊注釋,修改代碼同時修改相應的注釋,以保證注釋與代碼的一致性。不再有

用的注釋要刪除。

2-6:注釋的內容要清楚、明了,含義準確,防止注釋二義性。

說明:錯誤的注釋不但無益反而有害。

規則2-7:避免在注釋中使用縮寫,特別是非常用縮寫。

說明:在使用縮寫時或之前,應對縮寫進行必要的說明。

2-8;注釋應與其描述的代碼相近,對代碼的注釋應放在其上方或右方(對單條語句的注釋)

相鄰位置,不可放在下面,如放于上方則需與其上面的代碼用空行隔開。

示例:如下例子不符合規范。

例1:

/*getreplicatesubsystemindexandnetindicator*/

repssn_ind=ssn_data[index].repssn_index;

repssn_ni-ssn_data[index].ni;

例2:

repssn_ind=ssn_data[index].repssn_index;

repssn_ni=ssn_data[index].ni;

/*getreplicatesubsystemindexandnetindicator*/

應如下書寫

/*getreplicatesubsystemindexandnetindicator*/

repssn_ind=ssn_data[index],repssn_index;

repssn^ni=ssn_data[index].ni;

2-9:對于所有有物理含義的變量、常量,如果其命名不是充分自注釋的,在聲明時都必須加

以注釋,說明其物理含義。變量、常量、宏的注釋應放在其上方相鄰位置或右方。

示例:

/*activestatistictask,number*/

#defineMAX_ACT_TASK_NUMBER1000

#defineMAXACTTASKNUMBER1000/*activestatistictasknumber

*/

2-10:數據結構聲明(包括數組、結構、類、枚舉等),如果其命名不是充分自注釋的,必須

加以注釋。對數據結構的注釋應放在其上方相鄰位置,不可放在下面;對結構中的每個域的

注釋放在此域的右方。

示例:可按如下形式說明枚舉/數據/聯合結構。

/*seepinterfacewithseepuserprimitivemessagename*/

enumSCCP_USER_PRIMITIVE

(

N_UNITDATA_IND,/*seepnotifyseepuserunitdatae*/

NNOTICEIND,/*seepnotifyusertheNo.7networkcannot

*/

/*transmissionthismessage*/

N_UNITDATA_REQ,/*seepuser1sunitdatatransmission

request*/

};

2-11:全局變量要有較詳細的注釋,包括對其功能、取值范圍、哪些函數或過程存取它以及

存取時注意事項等的說明。

示例:

/*TheErrorcodewhenSCCPtranslate*/

/*GlobalTitlefailure,asfollows*///變量作用、含義

/*0-SUCCESS1-GTTableerror*/

/*2—GTerrorOthers-nouse*///變量取值范圍

/*onlyfunctionSCCPTranslate()in*/

/*thismodualcanmodifyit,andother*/

/*modulecanvisititthroughcall*/

/*thefunctionGetGTTransErrorCode()*///使用方法

BYTEg_GTTranErrorCode;

2-12;注釋與所描述內容進行同樣的縮排.

說明:可使程序排版整齊,并方便注釋的閱讀與理解。

示例:如下例子,排版不整齊,閱讀稍感不方便。

voidexamplefun(void)

/*codeonements*/

CodeBlockOne

/*codetwomerits*/

CodeBlockTwo

}

應改為如下布局。

voidexample_fun(void)

(

/*codeonements*/

CodeBlockOne

/*codetwoments*/

CodeBlockTwo

}

2-13:將注釋與其上面的代碼用空行隔開。

示例:如下例子,顯得代碼過于緊湊。

/*codeonements*/

programcodeone

/*codetwoments*/

programcodetwo

應如下書寫

/*codeonements*/

programcodeone

/*codetwoments*/

programcodetwo

2-14:對變量的定義和分支語句(條件分支、循環語句等)必須編寫注釋。

說明:這些語句往往是程序實現某一特定功能的關鍵,對于維護人員來說,良好的注釋

幫助更好的理解程序,有時甚至優于看設計文檔。

2-15;對于switch語句下的case語句,如果因為特殊情況需要處理完一個case后進入下一

個case處理,必須在該case語句處理完、下一個case語句前加上明確的注釋。

說明;這樣比較清楚程序編寫者的意圖,有效防止無故遺漏break語句。

示例(注意斜體加粗部分):

caseCMDJJP:

ProcessUp();

break;

caseCMD_DOWN:

ProcessDown();

break;

caseCMD_FWD:

ProcessFwd();

if(...)

(

break;

)

else

(

ProcessCFW_B();//nowjumpintocaseCMD_A

}

caseCMD_A:

ProcessAO;

break;

caseCMD_B:

ProcessB();

break;

caseCMD_C:

ProcessC();

break;

caseCMD_D;

ProcessD();

break;

2-1:避免在一行代碼或表達式的中間插入注釋。

說明:除非必要,不應在代碼或表達中間插入注釋,否則容易使代碼可理解性變差。

22通過對函數或過程、變量、結構等正確的命名以及合理地組織代碼的結構,使代碼成為

自注釋的Q

說明:清晰準確的函數、變量等的命名,可增加代碼可讀性,并減少不必要的注釋。

23在代碼的功能、意圖層次上進行注釋,提供有用、額外的信息。

說明;注釋的目的是解釋代碼的目的、功能和采用的方法,提供代碼以外的信息,幫助

讀者理解代碼,防止沒必要的重復注釋信息。

示例:如下注釋意義不大。

/*ifreceive_flagisTRUE*/

if(receive_flag)

而如下的注釋則給出了額外有用的信息。

/*ifmtpreceiveamessagefromlinks*/

if(recGive_flag)

24在程序塊的結束行右方加注釋標記,以表明某程序塊的結束。

說明:當代碼段較長,特別是多重嵌套時,這樣做可以使代碼更清晰,更便于閱讀。

示例:參見如下例子。

if(...)

(

//programcode

while(index<MAX_INDEX)

(

//programcode

}/*endofwhile(index<MAX_INDEX)*///指明該條while語句

結束

}/*endofif(...)*/II指明是哪條if語句結束

25注釋格式盡量統一,建議使用V*……*/〃。

2-6:注釋應考慮程序易讀及外觀排版的因素,使用的語言若是中、英兼有的,建議多使用中

文,除非能用非常流利準確的英文表達。

說明:注釋語言不統一,影響程序易讀性和外觀排版,出于對維護人員的考慮,建議使

用中文。

3.標識符命名

3-1:標識符的命名要清晰、明了,有明確含義,同時使用完整的單詞或大家基本可以理解的

縮寫,避免使人產生誤解。

說明:較短的單詞可通過去掉“元音”形成縮寫;較長的單詞可取單詞的頭幾個字母形

成縮寫;一些單詞有大家公認的縮寫0

示例;如下單詞的縮寫能夠被大家基木認可。

temp可縮寫為tmp;

flag可縮寫為fig;

statistic可縮寫為stat;

increment可縮寫為inc;

message可縮寫為msg;

3-2;命名中若使用特殊約定或縮寫,則要有注釋說明。

說明:應該在源文件的開始之處,對文件中所使用的縮寫或約定,特別是特殊的縮寫,

進行必要的注釋說明。

3-3:自己特有的命名風格,要自始至終保持一致,不可來回變化°

說明;個人的命名風格,在符合所在項目組或產品組的命名規則的前提下,才可使用。

(即命名規則中沒有規定到的地方才可有個人命名風格)。

3-4:對于變量命名,禁止取單個字符(如i、j、k...),建議除了要有具體含義外,還能

表明其變量類型、數據類型等,但,j、k作局部循環變量是允許的,

說明:變量,尤其是局部變量,如果用單個字符表示,很容易敲錯(如i寫成j),而

編譯時又檢查不出來,有可能為了這個小小的錯誤而花費大量的查錯時間。

示例;下面所示的局部變量名的定義方法可以借鑒。

ifitlivWidth

其變量名解釋如下:

指針型變量:“p_”+變量名:

結構變量:+變量名;

局部變量:“V,+變量名;

全局變量;“gv_”+變量名;

這樣可以防止局部變量與全局變量重名。

3-1:除非必要,不要用數字或較奇怪的字符來定義標識符。

示例;如下命名,使人產生疑惑。

#define_EXAMPLE_O_TEST_

#define_EXAMPLE_1_TEST_

voidset_sls00(BYTEsis);

應改為有意義的單詞命名

#define_EXAMPLE_UNIT_TEST_

#define_EXAMPLE_ASSERT_TEST_

voidsetudtmsgsis(BYTEsis);

32在同一軟件產品內,應規劃好接口部分標識符(變量、結構、函數及常量〉的命名,防

止編譯、鏈接時產生沖突。

說明:對接口部分的標識符應該有更嚴格限制,防止沖突。如可規定接口部分的變量與

常量之前加上“模塊”標識等。

33用正確的反義詞組命名具有互斥意義的變量或相反動作的函數等。

說明;下面是一些在軟件中常用的反義詞組。

add/removebegin/endcreate/destroy

insert/deletefirst/lastget/release

increment/decrementput/get

add/deletelock/unlockopen/close

min/maxold/newstart/stop

next/previoussource/targetshow/hide

send/receivesource/destination

cut/pasteup/down

示例;

intminsum;

intmax_sum;

intadd_user(BYTE*user_name);

intdelete_user(BYTE*user_name);

34除了編譯開關/頭文件等特殊應用,應避免使用_EXAMPLE_TEST_之類以下劃線開始和

結尾的定義。

4.可讀性

4-1:注意運算符的優先級,并用括號明確表達式的操作順序,避免使用默認優先級。

說明:防止閱讀程序時產生誤解,防止因默認的優先級與設計思想不符而導致程序出

錯6

示例:下列語句中的表達式

word=(high<<8)|low(1)

if((aIb)&&(a&c))(2)

if((a|b)<(c&dH(3)

如果書寫為

high?8|low

a|b&&aic

a|b<c&d

由于

high<<8|low=(high<<8)Ilow,

aIb&&a&c=(aIb)&&(a&c),

(1)(2)不會出錯,但語句不易理解:

a|b<c&d=aI(b<c)&d,(3)造成了判斷條件出錯。

4-2:避免使用不易理解的數字,用有意義的標識來替代。涉及物理狀態或者含有物理意義的

常量,不應直接使用數字,必須用有意義的枚舉或宏來代替。

示例:如下的程序可讀性差。

if(Trunk[index].trunk_state==0)

(

Trunk[index].trunk_state=1;

...//programcode

應改為如下形式。

#defineTRUNK_IDLE0

#defineTRUNK_BU$Y1

if(Trunk[index].trunkstate==TRUNKIDLE)

Trunk[index],trunk_state=TRUNK_BUSY;

...//programcode

}

4-1:源程序中關系較為緊密的代碼應盡可能相鄰6

說明:便于程序閱讀和查找。

示例;以下代碼布局不太合理。

rect.length=10;

char_poi=str;

rect.width=5;

若按如下形式書寫,可能更清晰一些。

rect.length=10;

rect.width=5;//矩形的長與寬關系較密切,放在一起。

char_poi=str;

42不要使用難懂的技巧性很高的語句,除非很有必要時。

說明:高技巧語句不等于高效率的程序,實際.上程序的效率關鍵在于算法6

示例;如下表達式,考慮不周就可能出問題,也較難理解。

*stat_poi+++=1;

*++stat_poi+=1;

應分別改為如下。

*stat_poi+=1;

stat__poi++;//此二語句功能相當于"*stat_poi+++=1;

++stat_poi;

*statpoi+=1;//此二語句功能相當于"*++statpoi+=1;

5.變量、結構

5-1:去掉沒必要的公共變量。

說明:公共變量是增大模塊間耦合的原因之一,故應減少沒必要的公共變量以降低模

塊間的耦合度。

5-2:仔細定義并明確公共變量的含義、作用、取值范圍及公共變量旬的關系。

說明:在對變量聲明的同時,應對其含義、作用及取值范圍進行注釋說明,同時若有

必要還應說明與其它變量的關系。

5-3:明確公共變量與操作此公共變量的函數或過程的關系,如訪問、修改及創建等。

說明:明確過程操作變量的關系后,將有利于程序的進一步優化、單元測試、系統聯

調以及代碼維護等。這種關系的說明可在注釋或文檔中描述。

示例:在源文件中,可按如下注釋形式說明。

RELATIONSystem_InitInput_Rec_RecStat_Score

StudentCreateModifyAccessAccess

ScoreCreateModifyAccessAccess,

Modify

注:RELATION為操作關系:System_InitNInput_Rec%_Rec、Stat_Score

為四個不同的函數;StudentsScore為兩個全局變量;Create表示創建,

Modify表示修改,Access表示訪問。

其中,函數[nput_Rec、Stat_Score都可修改變量Score,故此變量將引起函數

間較大的耦合,并可能增加代碼測試、維護的難度。

5-4:當向公共變量傳遞數據時,要十分小心,防止賦與不合理的值或越界等現象發生。

說明:對公共變量賦值時,若有必要應進行合法性檢杳,以提高代碼的可靠性、穩定

性。

5-5:防止局部變量與公共變量同名。

說明:若使用了較好的命名規則,那么此問題可自動消除。

5-6:嚴禁使用未經初始化的變量作為右值。

說明:特別是在C/C++中引用未經賦值的指針,經常會引起系統崩潰。

5-1:構造僅有一個模塊或函數可以修改、創建,而其余有關模塊或函數只訪問的公共變

量,防止多個不同模塊或函數都可以修改、創建同一公共變量的現象。

說明:降低公共變量耦合度。

5-2:使用嚴格形式定義的、可移植的數據類型,盡量不要使用與具體硬件或軟件環境關

系密切的變量。

說明:使用標準的數據類型,有利于程序的移植。

示例:如下例子(在DOS下BC3.1環境中),在移植時可能產生問題。

voidmain()

registerintindex;//寄存器變量

_AX=0x4000;//_AX是BC3.1提供的寄存器“偽變量”

.,?//programcode

typedefstructTEACHER_STRU

unsignedcharnane[8];/*teachername*/

unisgnedcharsex;/*teachersex,asfollows*/

/*0-FEMALE;1-MALE*/

}TEACHER;

typedefstructSTUDENT_STRU

unsignedcharnane[8];/*student's:name*/

unsignedcharage;/*student*s:age*/

unsignedcharsex;/*student*s:sex,asfollows*/

/*0-FEMALE;1-MALE*/

unsignedintteacherind;/*histeacherindex

}STUDENT;

54不要設計面面俱到、非常靈活的數據結構。

說明:面面俱到、靈活的數據結構反而容易引起誤解和操作困難。

55不同結構間的關系不要過于復雜。

說明:若兩個結構間關系較復雜、密切,那么應合為一個結構。

示例:如下兩個結構的構造不合理。

typedefstructPERSON_ONE_STRU

unsignedcharname[8];

unsignedcharaddr[40];

unsignedcharsex;

unsignedcharcity[15];

}PERSON_ONE;

typedefstructPERSON_TWO_STRU

(

unsignedcharname[8];

unsignedcharage;

unsignedchartel;

}PERSON_TWO;

由于兩個結構都是描述同一事物的,那么不如合成一個結構。

typedefstructPERSON_STRU

(

unsignedcharname[8];

unsignedcharage;

unsignedcharsex;

unsignedcharaddr[40];

unsignedcharcity[15];

unsignedcharte";

}PERSON;

56結構中元素的個數應適中。若結構中元素個數過多可考慮依據某種原則把元素組成

不同的子結構,以減少原結構中元素的個數。

說明:增加結構的可理解性、可操作性和可維護性。

示例:假如認為如上的.PERSON結構元素過多,那么可如下對之劃分。

typedefStructPERSON_BASE_INFO_STRU

(

unsignedcharname[8];

unsignedcharage;

unsignedcharsex;

}PERSON_BASE_INFO;

typedefStructPERSON_ADDRESS_STRU

(

unsignedcharaddr[40];

unsignedcharcity[15];

unsignedchartel;

}PERSON_ADDRESS;

typedefstructPERSON_STRU

(

PERSON_BASE_INFOperson_base;

PERSON_ADDRESSperson_addr;

}PERSON;

5-7:仔細設計結構中元素的布局與排列順序,使結構容易理解、節省占用空間,并減少

引起誤用現象。

說明:合理排列結構中元素順序,可節省空間并增加可理解性。

示例:如下結構中的位域排列,將占較大空間,可讀性也稍差。

typedefStructEXAMPLF._STRU

(

unsignedintvalid:1;

PERSONperson;

unsignedintset_f1g:1;

}EXAMPLE;

若改成如下形式,不僅可節省1字節空間,可讀性也變好了。

typedefstructEXAMPLE_STRU

(

unsignedintvalid:1;

unsignedintset_f1g:1;

PERSONperson;

}EXAMPLE;

58結構的設計要盡量考慮向前兼容和以后的版本升級,并為某些未來可能的應用保留

余地(如預留一些空間等)。

說明:軟件向前兼容的特性,是軟件產品是否成功的重要標志之一。如果要想使產品

具有較好的前向兼容,那么在產品設計之初就應為以后版本升級保留一定余地,并且

在產品升級時必須考慮前一版本的各種特性。

5-9:留心具體語言及編譯器處理不同數據類型的原則及有關細節。

說明:如在C語言中,static局部變量將在內存“數據區”中生成,而非static

局部變量將在“堆棧”中生成。這些細節對程序質量的保證非常重要。

5-10:編程時,要注意數據類型的強制轉換。

說明:當進行數據類型強制轉換時,其數據的意義、轉換后的取值等都有可能發生變

化,而這些細節若考慮不周,就很有可能留下隱患。

5-11:對編譯系統默認的數據類型轉換,也要有充分的認識。

示例:如下賦值,多數編譯器不產生告警,但值的含義還是稍有變化。

charchr;

unsignedshortintexam;

chr=-1;

exam=chr;//編譯器不產生告警,此時exam為OxFFFFo

5-12:盡量減少沒有必要的數據類型默認轉換與強制轉換。

5-13:合理地設計數據并使用自定義數據類型,避免數據間進行不必要的類型轉換。

5-14:對自定義數據類型進行恰當命名,使它成為自描述性的,以提高代碼可讀性。注意

其命名方式在同一產品中的統一。

說明:使用自定義類型,可以彌補編程語言提供類型少、信息量不足的缺點,并能使

程序清晰、簡潔。

示例:可參考如下方式聲明自定義數據類型。

下面的聲明可使數據類型的使用簡潔、明了。

typedefunsignedcharBYTE;

typedefunsignedshortWORD;

typedefunsignedintDWORD;

下面的聲明可使數據類型具有更豐富的含義。

typedeffloatDISTANCE;

typedeffloatSCORE;

6-5:在同一項目組應明確規定對接口函數參數的合法性檢查應由函數的調用者負責還是

由接口函數本身負責,缺省是由函數調用者負責。

說明:對于模塊間接口函數(I勺參數的合法性檢查這一問題,往往有兩個極端現象,

即:要么是調用者和被調用者對參數均不作合法性檢查,結果就遺漏了合法性檢查這

一必要的處理過程,造成問題隱患;要么就是調用者和被調用者均對參數進行合法性

檢查,這種情況雖不會造成問題,但產生了冗余代碼,降低了效率。

6.函數

6-1:防止將函數的參數作為工作變量。

說明:將函數的參數作為工作變量,有可能錯誤地改變參數內容,所以很危險。對必

須改變的參數,最好先用局部變量代之,最后再將該局部變量的內容賦給該參數。

示例:下函數的實現不太好。

voidsum_data(unsignedintnum,int*data,int*sum)

(

unsignedintcount;

*?jum=0;

for(count=0;count<num;count++)

(

*sum+=data[count];//sum成了工作變量,不太好。

}

)

若改為如下,則更好些。

voidsum_data(unsignedintnum,int*data,int*sum)

(

unsignedintcount;

intsum_temp;

sum_temp=0;

for(count=0;count<num;count++)

sum_temp+=data[count];

)

*sum=sum_temp;

}

62函數的規模盡量限制在200行以內。

說明:不包括注釋和空格行。

6-3:一個函數僅完成一件功能。

6-4:為簡單功能編寫函數。

說明:雖然為僅用一兩行就可完成的功能去編函數好象沒有必要,但用函數可使功能

明確化,增加程序可■讀性,亦可方便維護、測試。

示例:如下語句的功能不很明顯。

value=(a>b)?a:b;

改為如下就很清晰了。

intmax(inta,intb)

(

return((a>b)?a:b);

)

value=max(a,b);

或改為如下。

#defineMAX(a,b)(((a)>(b))?(a):(b))

value=MAX(a,b);

65不要設計多用途面面俱到的函數。

說明:多功能集于一身的函數,很可能使函數的理解、測試、維護等變得困難。

6-6:函數的功能應該是可以預測的,也就是只要輸入數據相同就應產生同樣的輸出。

說明:帶有內部“存儲器”H勺函數的功能可能是不可預測的,因為它的輸出可能取決

于內部存儲器(如某標記)的狀態。這樣的函數既不易于理解又不利于測試和維護。

在C/C++語言中,函數的s二atic局部變量是函數的內部存儲器,有可能使函數的

功能不可預測,然而,當某函數的返回值為指針類型時,則必須是STAT工C的局部變

量的地址作為返回值,若為AUTO類,則返回為錯針。

示例:如下函數,其返回值(即功能)是不可預測的。

unsignedintinteger_sum(unsignedintbase)

(

unsignedintindex;

staticunsignedmtsum=0;//注意,是static類型的。

//若改為aut。類型,則函數即變為

可預測。

for(index=1;index<=base;index++)

(

sum+=index;

}

returnsum;

)

67盡量不要編寫依賴于其他函數內部實現的函數。

說明:此條為函數獨立性的基本要求。由于目前大部分高級語言都是結構化的,所以

通過具體語言的語法要求與編譯器功能,基本就可以防止這種情況發生。但在匯編語

言中,由于其靈活性,很可能使函數出現這種情況。

示例:如下是在DOS下TASM的匯編程序例子。過程_Msg的實現依賴于

工nput_Msg的具體實現,這種程序是非結構化的,難以維護、修改。

...//程序代碼

proc_Msg//過程(函數)_Msg

...//程序代碼

jmpLABEL

//程序代碼

endp

procInput_Msg//過程(函數)Input_Msg

...//程序代碼

LABEL:

...//程序代碼

endp

6-8:避免設計多參數函數,不使用的參數從接口中去掉。

說明:目的減少函數間接口H勺復雜度。

6-9:非調度函數應減少或防止控制參數,盡量只使用數據參數。

說明:本建議目的是防止函數間的控制耦合。調度函數是指根據輸入的消息類型或控

制命令,來啟動相應的功能實體(即函數或過程),而本身并不完成具體功能。控制

參數是指改變函數功能行為的參數,即函數要根據此參數來決定具體怎樣工作。非調

度函數的控制參數增加了函數間的控制耦合,很可能使函數間的耦合度增大,并使函

數的功能不唯一。

示例:如下函數構造不太合理。

intadd_sub(inta,mtb,unsignedcharadd_sub_f1g)

(

if(add_sub_flg==INTEGER_ADD)

{

return(a+b);

}

else

(

return(a29b);

)

不如分為如下兩個函數清晰。

intadd(inta,intb)

return(a+b);

)

intsub(inta,intb)

(

return(a30b);

)

6-10:檢查函數所有參數輸入的有效性。

6-11:檢查函數所有非參數輸入的有效性,如數據文件、公共變量等。

說明:函數的輸入主要有兩種:一種是參數輸入;另一種是全局變量、數據文件的輸

入,即非參數輸入。函數在使用輸入之前,應進行必要的檢查。

6-12:函數名應準確描述函數的功能。

6-13:使用動賓詞組為執行某操作的函數命名。如果是OOR方法,可以只有動詞(名詞是

對象本身)。

示例:參照如下方式命名函數。

void_record(unsignedintrec_ind);

intinput_record(void);

unsignedcharget_current_color(void);

建議6-14:避免使用無意義或含義不清的動詞為函數命名。

說明:避免用含義不清的動詞如process、handle等為函數命名,因為這些動詞

并沒有說明要具體做什么。

建議6-15:函數的返回值要清楚、明了,讓使用者不容易忽視錯誤情況。

說明:函數的每種出錯返回值的意義要清晰、明了、準確,防止使用者誤用、理解錯

誤或忽視錯誤返回碼。

6-16:除非必要,最好不要把與函數返回值類型不同的變量,以編譯系統默認的轉換方式

或強制的轉換方式作為返回值返回。

6-17:讓函數在調用點顯得易懂、容易理解。

6-18:在調用函數填寫參數時,應盡量減少沒有必要的默認數據類型轉換或強制數據類型

轉換。

說明:因為數據類型轉換或多或少存在危險。

6-19:避免函數中不必要語句,防止程序中的垃圾代碼。

說明:程序中的垃圾代碼不僅占用額外的空間,而且還常常影響程序的功能與性能,

很可能給程序的測試、維護等造成不必要的麻煩。

62h減少函數本身或函數間的遞歸調用。

說明:遞歸調用特別是函數間的遞歸調用(如,影響程序的可理解

性;遞歸調用一般都占用較多的系統資源(如棧空間);遞歸調用對程序的測試有一

定影響。故除非為某些算法或功能的實現方便,應減少沒必要的遞歸調用。

6-25:仔細分析模塊的功能及性能需求,并進一步細分,同時若有必要畫出有關數據流

圖,據此來進行模塊的函數劃分與組織。

說明:函數的劃分與組織是模塊的實現過程中很關鍵的步驟,如何劃分出合理的函數

結構,關系到模塊的最終效率和可維護性、可測性等。根據模塊的功能圖或/及數據

流圖映射出函數結構是常用方法之一。

6-26:改進模塊中函數的結構,降低函數間的耦合度,并提高函數的獨立性以及代碼可讀

性、效率和可維護性。優化函數結構時,要遵守以下原則:

(1)不能影響模塊功能的實現。

(2)仔細考查模塊或函數出錯處理及模塊的性能要求并進行完善。

(3)通過分解或合并函數來改進軟件結構。

(4)考查函數的規模,過大的要進行分解。

(5)降低函數間接口的復雜度。

(6)不同層次的函數調用要有較合理的扇入、扇出。

(7)函數功能應可預測。

(8)提高函數內聚。(單一功能的函數內聚最高)

說明:對初步劃分后的函數結構應進行改進、優化,使之更為合理。

6-28:避免使用BOOL參數。

說明:原因有二,其一是BOOL

溫馨提示

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

評論

0/150

提交評論