Code Style(代碼的風格)
2019-09-06 23:33:49
供稿:網(wǎng)友
1./t簡介
2./t什么是風格?
3./t代碼的風格為什么如此重要?
4./t更少的工作,更多的文檔?
5./t推薦的代碼風格
6./t簡單的文檔
7./t輸出風格
8./t結(jié)論
簡介
讓我們面對一下吧…如果您是一個資深的程序員,那么您總是在最后期限下工作并且您的最終目標是完成您設(shè)計的軟件。如果您是個新手,您的努力是更多的研究、試驗、當然還有錯誤和一心希望您的程序可以象打算的那樣運行。不管怎樣,當您的程序真的如愿以償?shù)倪\行時那種成功的感覺令人十分振奮,但更多的程序員發(fā)現(xiàn)能夠用良好的風格生成程序內(nèi)部代碼時的那種自豪的感覺更棒。
如果您是程序設(shè)計小組的成員或者如果您還在書寫學校分配的任務(wù),那么您會有機會被要求遵守某些必須遵守的風格規(guī)則。 絕大多數(shù)的程序員考慮風格這件事就象一個10歲大的孩子看待就寢時間一樣。但資深程序員和我所見過的小組領(lǐng)導(dǎo)及多年來使用許多風格的程序員都會試圖向您傳達良好的代碼風格與您所得意的一些書寫代碼的技巧同樣重要。在這篇文章中我將嘗試包括一些輸出風格的觀點,這也許有助您的編程旅程。
更少的工作,更多的文檔?
因此風格意味著要在代碼的每一行加上注解,對嗎?錯。如果沒有做對的話,注解也會變成一場災(zāi)難。 我仍然希望一個程序員學會喜歡輸入注解或真正對注解有足夠的重視。為了未來的可維護性必須強制自己正確的放置注解。所以怎么能夠不使用注解?
顯然對一個新手最困難的事是懂得什么是好的變量命名。讓我們看看以下的代碼。您能告訴我下面的代碼是做什么的嗎?
/t/t float __fastcall TExampleForm::CalcAverageGrade(void)
/t {
/t int y=0;
/t int i=0;
/t for (i; i<x; i++) {
/t/t y=y+g;/t
/t }
/t return float(y/x);
/t/t }
在上面的例子中,您能很輕易的告訴我y代表什么呢?x又是什么呢?這段代碼也許需要一些注釋來解釋這些變量的代表意義及代碼中發(fā)生了什么?應(yīng)用以上的代碼風格,看不出什么邏輯關(guān)系。現(xiàn)在讓我們看看應(yīng)用更好的代碼風格以后,代碼是何等模樣?
/t/t float __fastcall TExampleForm::CalcAverageGrade(void)
/t {
/t int total=0;
/t for (int i=0; i<maxGrades; i++)
/t/t {
/t/t total+=Grades;
/t } //求所有成績的和
/t return float(total/maxGrades);
/t } //計算平均成績
在您除錯時以上兩段代碼孰優(yōu)孰劣,已不必多說。現(xiàn)在就讓我們討論一些能夠讓您的代碼更具有可維護性的推薦風格吧。
推薦的代碼風格
1. 使用有描述意義的變量名。
2. 使用i, j, k, l, m作為循環(huán)計數(shù)變量。這起源于Fortran,自始自終這都是事實上的工業(yè)標準。
3. 在閉合括號處為所有的聲明和方法注釋。這樣在嘗試找到與此配對的上一個初始括號時更容易做決定,尤其在聲明很長時。
4. 考慮將if后面或循環(huán)定義體的初始括號放在一個單獨的行上。這真的有助于您找到與其對應(yīng)的閉合括號。
5. 使用適當?shù)慕M合運算符 (+=, *=, 等等)。對自增(自減)變量使用++ 和 -?C運算符。正確使用這些運算符會使您的代碼更可讀和更一致。這也減少了輸入的字符數(shù)量。組合運算符也會幫助編譯器生成更快的代碼。舉例來說,i++產(chǎn)生的asm(匯編)代碼是inc ,而i=i+1將會產(chǎn)生如下的asm(匯編)代碼mov eax, inc eax mov ,eax。
6. 注解代碼時,要明智些!如果一段代碼的邏輯關(guān)系很復(fù)雜,注解將有助于別人理解代碼的意圖。但如果邏輯關(guān)系直線向前,避免加上并非必須的注解。要象維護您的代碼一樣維護您的注解!
7. 命名變量時,使用有描述意義的大寫。簡單變量(例如,int, long, String)應(yīng)該以小寫字符開始。復(fù)雜變量(例如,對象、結(jié)構(gòu)、數(shù)組)應(yīng)該以大寫開始。變量名稱中包含的所有單詞都應(yīng)該大寫開頭。這會讓讀(寫)代碼的人對所訪問的數(shù)據(jù)類型有一個清晰的第一印象。
8. 避免在變量名中使用下劃線。絕大多數(shù)的編譯器中,它都有特殊的意義。
9. 盡可能(而不是瘋狂的)將代碼模塊化。合理的話,將代碼放入函數(shù)中去。這允許更好的代碼重用性和可讀性。
10. 使用正確的循環(huán)。如果代碼最少要執(zhí)行一次,使用do-while循環(huán),否則使用while-do循環(huán)。如果確切的循環(huán)執(zhí)行次數(shù)已知,使用for循環(huán)。
11. 在事件發(fā)生的數(shù)量超過兩種時,只要可能就使用switch聲明。同時,無論何時只要可能就包含一個switch default(缺省開關(guān)),這樣總會有一個選項被觸發(fā)。Switch聲明很容易除錯,而且比組合的多重if聲明執(zhí)行速度更快。
12. 在您代碼中的邏輯步驟之間加上一個空行(例如,定義變量、循環(huán)、等等)。
13. 聲明變量的位置非常重要。變量應(yīng)該聲明的位置幾乎沒有隨意性。當變量用于整個(類)對象或者必須在對象外可見的時候,變量應(yīng)放在頭文件中。臨時變量如果不需要在if聲明或循環(huán)體外被訪問的話,就應(yīng)在它們內(nèi)部聲明。不正確的放置變量聲明會導(dǎo)致執(zhí)行速度減慢、錯誤、或者引起誤導(dǎo)的代碼。
14. 初始化所有的變量。
15. 如果您有非空返回(帶返回值)的函數(shù),確保所有的退出點都使用了return。對編譯器產(chǎn)生的警告"function should return a value"(函數(shù)應(yīng)該返回一個值)要引起足夠重視。這是嚴重警告并且可能導(dǎo)致您的軟件發(fā)生隨機錯誤。
16. 在兩個不同類型的變量間賦值時,應(yīng)對變量進行強制轉(zhuǎn)換計算來避免編譯器的警告(例如:int x; float y; … y=float x;)。這么做可以防止"Conversion may loose significant digits"的警告。作為一個程序員您的目標應(yīng)該盡可能的減少警告的數(shù)量。而強制類型轉(zhuǎn)換將消除其中的大多數(shù)。
17. 永遠在刪除后將指針設(shè)為NULL。
18. 盡量仔細的調(diào)查以避免“閉門造舊車”。經(jīng)過證明的函數(shù)與程序使用時優(yōu)先于新寫的代碼。這會讓您有更多的時間去寫真實的邏輯代碼并且非常有助于維護。盡管盡管動態(tài)鏈表的書寫非常有趣,它早已被完成了!
19. 正確的拼寫很重要。如果拼寫有錯的話,將來的搜索會很困難。
20. 永遠不要使用兩個只有大小寫不同的變量名字。
21. 在您創(chuàng)建代碼時就輸入注解,而不是以后。在您修改代碼的時候,保持對注解的維護。
22. 如果您在調(diào)試或除錯時注解(rem)了一段代碼的話,確保您最后將被注解的代碼刪除。
23. 最后最重要的是…保持風格的一致。
簡單的文檔
平凡的文檔在創(chuàng)建一個可維護的系統(tǒng)是卻十分有效。您應(yīng)該設(shè)置一個標準來為您的文檔注解模板規(guī)定文件的開始處應(yīng)該放置的內(nèi)容。這里是某些應(yīng)該在您的模板中完成的東西:
1./t 原創(chuàng)作者名字
2./t 原始創(chuàng)建日期
3./t 文件的用途
4./t 包括使用指導(dǎo)在內(nèi)的主要內(nèi)容列表
5./t 包括修訂日期的修訂歷史記錄。同時應(yīng)該說明修訂時發(fā)現(xiàn)并修復(fù)的bug。
文件注解應(yīng)該放在文檔頭部,并盡量簡明。下面是我們現(xiàn)在的應(yīng)用程序的一個例子。這個例子比較復(fù)雜。
/*
Written by(作者): Scott Cross/t/t
Date originally Completed(原始完成日期): 9/18/99
Purpose(用途): Main routine for NY Billing. This logic calculates the installments and provides all data necessary to print, display, and report billing status. The form will display the billing information. The main structure, InvoiceInfo, has all information including detail of Installments and Payment activities. Although the main object is a form, the form need not be shown in order to get billing information. This is the only billing logic for this version of the system. All billing inquiries should go through this routine.
Usage(用法): Nothing will be performed during the OnCreate event with the exception of setting some reference variables. All calculations are done by calling the main routine LoadAcctInfo. This routine can be called many times for different policies since it is fully initialized on each call. There are 5 parameters for the main functions and their usage is as follows:
bool LoadAcctInfo(
String policyNo - Supplies the logic with the targeted PolicyNo./t
bool printInvoice - Set to true if you want to print the invoice./t
bool nightRunning - If being called from the night, set to true./t
bool payableRunning - If being called by accounting rpt, set to true.
String masterPrintDate - This is a date. For more info on usage, see cpp.
);
No preliminary logic needs to be performed and the function will return true in most cases. No structures are passed since the main structure is public. It is imperative that the LoadAcctInfo be called prior to displaying the screen or unexpected results can occur since the main structures will not be initialized.
struct InvoiceInfoStruct{
PaymentHistoryStruct Payments[30]; - Payment History
int paymentCount; - Count of Payments
InstallmentStruct Installments[30]; - Installment Information
int installmentCount; - Count of Installments
int currInstall; - The current due installment
float totalPaid; - The total paid on file *
float totalDue; - Total due on file
float pastDue; - Total amount past due
float totalBilled; - Total amount billed on file
float totalApplied; - Amount applied to installments **
String equityDate; - The date the premium is paid to
String dateDue; - Date the file is due a payment
float annualizedPremium; - the annualized premium ***
};
* Restricted to masterPrintDate
** Should equal total paid
*** What the annualized premium is for the policy as stored in the tables if rated for one year.
Update History(更新歷史):
09/18/1999 - Scott - Completed
02/01/2000 ?C Scott - Fixed totalPaid error on cancelled file
*/
輸出風格
輸出風格沒有標準。在我的觀念中,編程最精彩的部分是程序的設(shè)計。您可以有自己的選擇,從什么是好的或壞的直到系統(tǒng)的外觀和感覺。盡管如此,仍有些有助于您的設(shè)計的建議。
1. 選擇統(tǒng)一的字體。
2. 把界面設(shè)計成可以在不同分辨率和不同設(shè)置下正常工作。啟用/不用大字體,然后測試您的軟件。并假定用戶仍在windows的VGA設(shè)定下運行(640X480 16色)。
3. 在多種顏色方案下測試軟件。
4. 嘗試維護逼真的3D效果。大多數(shù)情況下,初始的form(頁面)應(yīng)該是凸起的并帶有一種附加的下凹效果。盡管這看起來有點小兒科,但這使得程序有了深度并非常有助于分割頁面。
5. 牢記輸出效果的性能。在處理器集中的循環(huán)中,更新越簡單,執(zhí)行就越快。
6. 盡量避免在界面中使用太多的噱頭組件和效果。這會給人不專業(yè)的感覺,也可能傷害用戶的信心,除非工程要求浮華的設(shè)計。
7. 設(shè)計登錄屏幕,讓用戶無須鼠標動作就可以獲得更多。
8. 您的用戶也許欣賞毫不雜亂的環(huán)境,但也要牢記這依靠用戶的配置,多屏可能會使系統(tǒng)太慢。嘗試在速度和可用性之間找到平衡吧。
9. 在任何時候使用彈出提示和提示條都是合適的。從一開始就就記住要將頁面設(shè)置成這樣的。
10. 向?qū)ь愋偷慕缑鎸?fù)雜的多步驟過程時十分合適。這使得軟件可以指導(dǎo)用戶一步步的走過這些步驟。找一個好的NoteBook(筆記本)組件吧。
11. 在進行長時間的操作時,應(yīng)該總是調(diào)用Application->ProcessMessages();保持界面更新并讓windows知道您的應(yīng)用程序仍然處于活動狀態(tài)且能夠響應(yīng)消息。
12. 最后最重要的是…保持系統(tǒng)風格的一致。
結(jié)論
編程的風格要比許多程序員想像的更重要的多。您想讓別的程序員看見您現(xiàn)在的工程中的代碼嗎?您是不是對您的代碼和您的系統(tǒng)一樣自豪呢?現(xiàn)在花點時間來決定想在您的代碼中采用何種風格并開始每天使用這種風格。記住,用6個星期來發(fā)展一個習慣,不管它是好的還是壞的。
祝 好運!
原著: Scott Cross
翻譯: cker
版權(quán)說明:
國內(nèi)的網(wǎng)站上,有許多關(guān)于C++Builder的內(nèi)容,但多以軟件、組件為主。論壇里也大都不能令人滿意,很空虛的感覺。書籍又都昂貴,內(nèi)容卻有搶錢之嫌。對銀子不足的初學者、自學者關(guān)愛不夠,因而想盡自己的綿薄之力。
文中的所有資料都是從國外網(wǎng)站上收集而來。因為E文不方便,所以翻成中文。又因為English和計算機都不是非常好,文中的錯誤在所難免。若大家覺得有用的話,我計劃不斷搜集翻譯一些有用的東西。
有任何意見和建議請mailto:cker@sina.com
您可以隨意復(fù)制、分發(fā)、下載此文檔。但未經(jīng)本人同意,您不可以截取、改動本文片斷,或用本文謀取任何形式的利益.