溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

現(xiàn)代軟件工程講義 3 代碼規(guī)范與代碼復審

發(fā)布時間:2020-04-01 12:03:08 來源:網(wǎng)絡 閱讀:248 作者:鄒欣 欄目:軟件技術(shù)


現(xiàn)代軟件工程講義 3 代碼規(guī)范與代碼復審


在第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ā)言,基本上有如下的反應:

1Faint?。?/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鍵好,還是24、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)非常不方便,如果要一步一步觀察conditioncondition有可能是包含函數(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)實生活中有沒有什么意義。

下面哄笑起來。

果凍:(紅著臉問)那有些變量的確想不出名字,簡單的變量像ij、k都用完了,怎么辦?

阿超:當我們的程序比“Hello World”復雜10倍以上的時候,像給變量命名這樣簡單的事看起來也不那么簡單了。我們就來談談如何起名字這個問題。程序中的實體、變量是程序員晝思夜想的對象,要起一個好的名字才行。大家都知道用單個字母給有復雜語義的實體命名是不好的,目前最通用的,也是經(jīng)過了實踐檢驗的方法叫“匈牙利命名法”。例如:

fFileExist,表明是一個bool值,表示文件是否存在;

szPath,表明是一個以0結(jié)束的字符串,表示一個路徑。

如此命名的目的是讓程序員一眼就能看出變量的類型,避免在使用中出錯。早期的計算機語言(如BCPL)不作類型檢查,在C語言中,int、bytechar、bool大概都是一回事。下面這一句話:

if (i)

從語義來說,i可以是表示真/假的一個值,也可以表示長度是否為零,

還可以表示是否到了字符串的結(jié)束位置,或者可以表示兩個字符串比較的結(jié)果不相等(strcmp()返回-10,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ī)定下劃線一般不用在其他方面。


向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI