您好,登錄后才能下訂單哦!
在第9章中,同學們完成了WC程序,經(jīng)過評比,九條的程序獲得了第一名。這時,阿超說,現(xiàn)代軟件產(chǎn)業(yè)經(jīng)過幾十年的發(fā)展,已經(jīng)不可能出現(xiàn)一個人單槍匹馬完成一個軟件的事情了,軟件都是在相互合作中完成的。阿超建議大家互相看看別人的代碼,在TFS中每個人都把各自項目的權(quán)限放寬,允許別人訪問,交流一下意見。
兩個小時后,小飛來抱怨說,九條的代碼都是一行到底,隨意縮進,跟他提了意見,他還說“編譯通過就行了”。
他們找到了九條。
九條:我打麻將的時候牌都是亂擺,贏的也不少呀。
阿超:為什么要亂擺?
九條:因為怕圍觀的人看清我的牌路,我自己清楚就行了。
上課了。阿超問大家,我們寫的代碼是給人看的,還是給機器看的?
雜曰:人也看,機器也看。
阿超:對,但是最終是人在看。而且和打麻將不同,我們的代碼要讓“旁觀者”看得清清楚楚。請看下一段代碼,如代碼清單10-1所示,如果你接手這樣的代碼,有什么感想?
代碼清單10-1 badly formatted code – big C[1]
#include "stdafx.h" #include "stdio.h" void test(); int _tmain (int argc, _TCHAR* argv[]) { test(); return 0; } char C[25][40];void d(int x,int y) {C[x][y]=C[x][y+1]=32;}int f(int x){return (int)x*x*.08;} void test(){int i,j; char s[5]="TEST"; for(i=0;i<25;i++) for(j=0;j<40;j++) C[i][j]=s[(i+j)%4]; for(i=1;i<=7;i++) {d(18-i,12); C[20-f(i)][i+19]= C[20-f(i)][20-i]=32; }d(10,13);d(9,13); d(8,14);d(7,15); d(6,16);d(5,18);d(5,20); d(5,22);d(5,26); d(6,23);d(6,25);d(7,25);for(i=0;i<25;i++,printf("\n")) for(j=0;j<40;printf("%c",C[i][j++]));}
同學們紛紛發(fā)言,基本上有如下的反應:
(1)Faint?。?/span>
(2)重寫程序?。?/span>
(3)找到原作者,暴打一頓?。?!
(4)讓此人從公司辭職!?。。?/span>
計算機只關心編譯后的機器碼,你的程序是什么樣的縮進風格,以及變量名是否有統(tǒng)一的規(guī)范等和機器碼的執(zhí)行無關。但是,做一個有商業(yè)價值的項目,或者在團隊里工作,代碼規(guī)范相當重要。
我們講的“代碼規(guī)范”可以分成兩個部分。
(1)代碼風格規(guī)范。主要是文字上的規(guī)定,看似表面文章,實際上非常重要。
(2)代碼設計規(guī)范。牽涉到程序設計、模塊之間的關系、設計模式等方方面面,這里有不少與具體程序設計語言息息相關的內(nèi)容(如C/C++/Java/C#),但是也有通用的原則,這里主要討論通用的原則。
10.1 代碼風格規(guī)范
代碼風格的原則是:簡明,易讀,無二義性。
提示:這是移山公司的一家之言,如果碰到爭執(zhí),關鍵是要本著“保持簡明,讓代碼更容易讀”的原則,看看如下爭執(zhí)中的代碼規(guī)范是否能夠讓程序員們更好地理解和維護程序。
10.1.1 縮進
是用Tab鍵好,還是2、4、8個空格?
結(jié)論:4個空格,在VS2005和其他的一些編輯工具中都可以定義Tab鍵擴展成為幾個空格鍵。不用 Tab鍵的理由是Tab鍵在不同的情況下會顯示不同的長度。4個空格的距離從可讀性來說正好。
10.1.2 行寬
行寬必須限制,但是以前有些文檔規(guī)定的80字符行寬太小了(以前的計算機/打字機顯示行寬為80字符),現(xiàn)在時代不同了,可為100字符。
10.1.3 括號
在復雜的條件表達式中,用括號清楚地表示邏輯優(yōu)先級。
10.1.4 斷行與空白的{ }行
程序的結(jié)構(gòu)是什么風格?下面有幾種格式,我們一一討論。
最精簡的格式A:
if (condition) DoSomething();
else DoSomethingElse();
有人喜歡這樣,因為可以節(jié)省幾行,但是不同的語句(Statement)放在一行中,會使程序調(diào)試(DeBug)非常不方便,如果要一步一步觀察condition(condition有可能是包含函數(shù)調(diào)用的復雜表達式)中各個變量的變化情況,單步執(zhí)行就很難了。
因此,我們還是要有斷行,這樣可以得到如下的結(jié)構(gòu)——格式B:
if (condition)
DoSomething();
else
DoSomethingElse();
這樣的結(jié)構(gòu),由于沒有明確的“{”和“}”來判斷程序的結(jié)構(gòu),在有多層控制嵌套的時候,就不容易看清結(jié)構(gòu)和對應關系。下面的改進(格式C)雖好,但是阿超認為還是不夠清晰:
if ( condition) {
DoSomething();
} else {
DoSomethingElse();
}
于是我們最后做了這個選擇,每個“{”和“}”都獨占一行。就是格式D:
if ( condition)
{
DoSomething();
}
else
{
DoSomethingElse();
}
10.1.5 分行
不要把多行語句放在一行上。
a = 1; b = 2; // bogus
if (fFoo) Bar(); // bogus
更嚴格地說,不要把不同的變量定義在一行上。
Foo foo1, foo2; // bogus
10.1.6 命名
阿超:我在某個同學的程序中看到有些變量叫“lili”,“yunyun”,不知道這些變量在現(xiàn)實生活中有沒有什么意義。
下面哄笑起來。
果凍:(紅著臉問)那有些變量的確想不出名字,簡單的變量像i、j、k都用完了,怎么辦?
阿超:當我們的程序比“Hello World”復雜10倍以上的時候,像給變量命名這樣簡單的事看起來也不那么簡單了。我們就來談談如何起名字這個問題。程序中的實體、變量是程序員晝思夜想的對象,要起一個好的名字才行。大家都知道用單個字母給有復雜語義的實體命名是不好的,目前最通用的,也是經(jīng)過了實踐檢驗的方法叫“匈牙利命名法”。例如:
fFileExist,表明是一個bool值,表示文件是否存在;
szPath,表明是一個以0結(jié)束的字符串,表示一個路徑。
如此命名的目的是讓程序員一眼就能看出變量的類型,避免在使用中出錯。早期的計算機語言(如BCPL)不作類型檢查,在C語言中,int、byte、char、bool大概都是一回事。下面這一句話:
if (i)
從語義來說,i可以是表示真/假的一個值,也可以表示長度是否為零,
還可以表示是否到了字符串的結(jié)束位置,或者可以表示兩個字符串比較的結(jié)果不相等(strcmp()返回-1,0,1)。從程序的文字上,很難看出確切的語義。
同樣是字符串類型,char *,BSTR的有些行為是很不一樣的。
HRESULT的值也可以用來表示真假,但是HR_TRUE == 0,HR_FALSE ==1,這和通常的true/false剛好相反。
大部分的程序,錯就錯在這些地方!在變量面前加上有意義的前綴,就可以讓程序員一眼看出變量的類型及相應的語義。這就是“匈牙利命名法”的用處。
匈牙利命名法的一些通用規(guī)定,見本書附錄B(第337頁)。
還有一些地方不適合用“匈牙利命名法”,比如,在一些強類型的語言(如C#)中,不同類型的值是不能做運算的,對類型有嚴格的要求,例如C# 中,if()語句只能接受bool值的表達式,這樣就大大地防止了以上問題的發(fā)生。在這樣的語言中,前綴就不是很必要的,匈牙利命名法則不適用了。Microsoft .Net Framework就不主張用這樣的法則。
10.1.7 下劃線問題
下劃線用來分隔變量名字中的作用域標注和變量的語義,如:一個類型的成員變量通常用m_來表示。移山公司規(guī)定下劃線一般不用在其他方面。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。