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