• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            天行健 君子當(dāng)自強(qiáng)而不息

            程序設(shè)計(jì)風(fēng)格(1)


            人們看到最好的作家有時(shí)并不理會(huì)修辭學(xué)的規(guī)則。還好,當(dāng)他們這樣做雖然付
            出了違反常規(guī)的代價(jià),讀者還經(jīng)常能從句子中發(fā)現(xiàn)某些具有補(bǔ)償性的價(jià)值。除非作
            者自己也明確其做法的意思,否則最好還是按規(guī)矩做。
                                                                         William Strunk和E. B. White,《風(fēng)格的要素》


            下面這段代碼取自一個(gè)許多年前寫的大程序:

            i f ( (country == SING) I I (country == BRNI) I I
                   (country == POL) I I (country == ITALY) )
            {
            /*
            * I f the country is Singapore, Brunei or Poland
            * then the current time is the answer time
            * rather than the off hook time.
            * Reset answer time and s e t day of week.
            * /

            ...

            這段代碼寫得很仔細(xì),具有很好的格式。它所在的程序也工作得很好。寫這個(gè)系統(tǒng)的程序員會(huì)
            對(duì)他們的工作感到驕傲。但是這段摘錄卻會(huì)把細(xì)心的讀者搞糊涂:新加坡、文萊、波蘭和意大
            利之間有什么關(guān)系?為什么在注釋里沒有提到意大利?由于注釋與代碼不同,其中必然有一個(gè)
            有錯(cuò),也可能兩個(gè)都不對(duì)。這段代碼經(jīng)過了執(zhí)行和測(cè)試,所以它可能沒有問題。注釋中對(duì)提到
            的三個(gè)國(guó)家間的關(guān)系沒有講清楚,如果你要維護(hù)這些代碼,就必須知道更多的東西。


            上面這幾行實(shí)際代碼是非常典型的:大致上寫得不錯(cuò),但也還存在許多應(yīng)該改進(jìn)的地方。
            本書關(guān)心的是程序設(shè)計(jì)實(shí)踐,關(guān)心怎樣寫出實(shí)際的程序。我們的目的是幫助讀者寫出這
            樣的軟件,它至少像上面的代碼所在的程序那樣工作得非常好,而同時(shí)又能避免那些污點(diǎn)和
            弱點(diǎn)。我們將討論如何從一開始就寫出更好的代碼,以及如何在代碼的發(fā)展過程中進(jìn)一步改
            進(jìn)它。


            我們將從一個(gè)很平凡的地方入手,首先討論程序設(shè)計(jì)的風(fēng)格問題。風(fēng)格的作用主要就是
            使代碼容易讀,無論是對(duì)程序員本人,還是對(duì)其他人。好的風(fēng)格對(duì)于好的程序設(shè)計(jì)具有關(guān)鍵
            性作用。我們希望最先談?wù)擄L(fēng)格,也是為了使讀者在閱讀本書其余部分時(shí)能特別注意這個(gè)問
            題。


            寫好一個(gè)程序,當(dāng)然需要使它符合語法規(guī)則、修正其中的錯(cuò)誤和使它運(yùn)行得足夠快,但
            是實(shí)際應(yīng)該做的遠(yuǎn)比這多得多。程序不僅需要給計(jì)算機(jī)讀,也要給程序員讀。一個(gè)寫得好的
            程序比那些寫得差的程序更容易讀、更容易修改。經(jīng)過了如何寫好程序的訓(xùn)練,生產(chǎn)的代碼
            更可能是正確的。幸運(yùn)的是,這種訓(xùn)練并不太困難。


            程序設(shè)計(jì)風(fēng)格的原則根源于由實(shí)際經(jīng)驗(yàn)中得到的常識(shí),它不是隨意的規(guī)則或者處方。代
            碼應(yīng)該是清楚的和簡(jiǎn)單的—具有直截了當(dāng)?shù)倪壿?、自然的表達(dá)式、通行的語言使用方式、

            有意義的名字和有幫助作用的注釋等,應(yīng)該避免耍小聰明的花招,不使用非正規(guī)的結(jié)構(gòu)。一
            致性是非常重要的東西,如果大家都堅(jiān)持同樣的風(fēng)格,其他人就會(huì)發(fā)現(xiàn)你的代碼很容易讀,
            你也容易讀懂其他人的。風(fēng)格的細(xì)節(jié)可以通過一些局部規(guī)定,或管理性的公告,或者通過程
            序來處理。如果沒有這類東西,那么最好就是遵循大眾廣泛采納的規(guī)矩。我們?cè)谶@里將遵循
            《C程序設(shè)計(jì)語言》(The C Programming Language)一書中所使用的風(fēng)格,在處理J a v a和C++ 程
            序時(shí)做一些小的調(diào)整。


            我們一般將用一些好的和不好的小程序設(shè)計(jì)例子來說明與風(fēng)格有關(guān)的規(guī)則,因?yàn)閷?duì)處理
            同樣事物的兩種方式做比較常常很有啟發(fā)性。這些例子不是人為臆造的,不好的一個(gè)都來自
            實(shí)際代碼,由那些在太多工作負(fù)擔(dān)和太少時(shí)間的壓力下工作的普通程序員(偶然就是我們自己)
            寫出來。為了簡(jiǎn)單,這里對(duì)有些代碼做了些精練,但并沒有對(duì)它們做任何錯(cuò)誤的解釋。在看
            到這些代碼之后,我們將重寫它們,說明如何對(duì)它們做些改進(jìn)。由于這里使用的都是真實(shí)代
            碼,所以代碼中可能存在多方面問題。要指出代碼里的所有缺點(diǎn),有時(shí)可能會(huì)使我們遠(yuǎn)離討
            論的主題。因此,在有的好代碼例子里也會(huì)遺留下一些未加指明的缺陷。


            為了指明一段代碼是不好的,在本書中,我們將在有問題的代碼段的前面標(biāo)出一些問號(hào),
            就像下面這段:

            ? #define ONE 1
            ? #define TEN 10
            ? #define TWENTY 20

            為什么這些# d e f i n e有問題?請(qǐng)想一想,如果某個(gè)具有T W E N T Y個(gè)元素的數(shù)組需要修改得更大
            一點(diǎn),情況將會(huì)怎么樣。至少這里的每個(gè)名字都應(yīng)該換一下,改成能說明這些特殊值在程序
            中所起作用的東西。

            #def i ne INPUT-MODE 1
            #define INPUT-BUFSIZE 10
            #def i ne OUTPUT-BUFSIZE 20

             

            1.1 名字


            什么是名字?一個(gè)變量或函數(shù)的名字標(biāo)識(shí)這個(gè)對(duì)象,帶著說明其用途的一些信息。一個(gè)名
            字應(yīng)該是非形式的、簡(jiǎn)練的、容易記憶的,如果可能的話,最好是能夠拼讀的。許多信息來
            自上下文和作用范圍(作用域)。一個(gè)變量的作用域越大,它的名字所攜帶的信息就應(yīng)該越多。
            全局變量使用具有說明性的名字,局部變量用短名字。根據(jù)定義,全局變量可以出現(xiàn)在整個(gè)
            程序中的任何地方,因此它們的名字應(yīng)該足夠長(zhǎng),具有足夠的說明性,以便使讀者能夠記得
            它們是干什么用的。給每個(gè)全局變量聲明附一個(gè)簡(jiǎn)短注釋也非常有幫助:

            int npending = 0; // current length of input queue

            全局函數(shù)、類和結(jié)構(gòu)也都應(yīng)該有說明性的名字,以表明它們?cè)诔绦蚶锇缪莸慕巧?br> 相反,對(duì)局部變量使用短名字就夠了。在函數(shù)里, n可能就足夠了, n p o i n t s也還可以,
            用n u m b e r O f P o i n t s就太過分了。


            按常規(guī)方式使用的局部變量可以采用極短的名字。例如用i、j作為循環(huán)變量,p、q作為
            指針,s、t表示字符串等。這些東西使用得如此普遍,采用更長(zhǎng)的名字不會(huì)有什么益處或收
            獲,可能反而有害。比較:

            for (theElementIndex = 0; theElementIndex < number0fElements; theElementIndex++)
                     elementArray[theElementIndex] = theElementIndex;


            for (i = 0; i < nelems; i++)
                     elem[i] = i ;


            人們常常鼓勵(lì)程序員使用長(zhǎng)的變量名,而不管用在什么地方。這種認(rèn)識(shí)完全是錯(cuò)誤的,清晰
            性經(jīng)常是隨著簡(jiǎn)潔而來的。


            現(xiàn)實(shí)中存在許多命名約定或者本地習(xí)慣。常見的比如:指針采用以p結(jié)尾的變量名,例如
            n o d e p;全局變量用大寫開頭的變量名,例如G l o b a l;常量用完全由大寫字母拼寫的變量
            名,如C O N S T A N T S等。有些程序設(shè)計(jì)工場(chǎng)采用的規(guī)則更加徹底,他們要求把變量的類型和用
            途等都編排進(jìn)變量名字中。例如用p c h說明這是一個(gè)字符指針,用s t r T o和s t r F r o m表示它
            們分別是將要被讀或者被寫的字符串等。至于名字本身的拼寫形式,是使用n p e n d i n g或
            n u m P e n d i n g還是n u m _ p e n d i n g,這些不過是個(gè)人的喜好問題,與始終如一地堅(jiān)持一種切
            合實(shí)際的約定相比,這些特殊規(guī)矩并不那么重要。


            命名約定能使自己的代碼更容易理解,對(duì)別人寫的代碼也是一樣。這些約定也使人在寫
            代碼時(shí)更容易決定事物的命名。對(duì)于長(zhǎng)的程序,選擇那些好的、具有說明性的、系統(tǒng)化的名
            字就更加重要。


            C++ 的名字空間和J a v a的包為管理各種名字的作用域提供了方法,能幫助我們保持名字
            的意義清晰,又能避免過長(zhǎng)的名字。


            保持一致性。相關(guān)的東西應(yīng)給以相關(guān)的名字,以說明它們的關(guān)系和差異。
            除了太長(zhǎng)之外,下面這個(gè)J a v a類中各成員的名字一致性也很差:

            class UserQueue {
                    i n t noOfIternsInQ, frontOiTheQueue, queuecapacity;
                    public i n t noOfUsersInQueue() {... }

            這里同一個(gè)詞“隊(duì)列( q u e u e )”在名字里被分別寫為Q、Q u e u e或q u e u e。由于只能在類型
            U s e r Q u e u e里訪問,類成員的名字中完全不必提到隊(duì)列,因?yàn)榇嬖谏舷挛?。所以?/p>

            queue.queuecapacity

            完全是多余的。下面的寫法更好:

            class UserQueue {
               int ni terns, front, capacity;
               public i n t nusers() {. . .}

            }

            因?yàn)檫@時(shí)可以如此寫:

            quue.capacity++;

            n = queue.nusers();

            這樣做在清晰性方面沒有任何損失。在這里還有可做的事情。例如i t e m s和u s e r s實(shí)際是同一種
            東西,同樣?xùn)|西應(yīng)該使用一個(gè)概念。


            函數(shù)采用動(dòng)作性的名字。函數(shù)名應(yīng)當(dāng)用動(dòng)作性的動(dòng)詞,后面可以跟著名詞:

            now = date .getTirne() ;
            putchar('\nl) ;

            對(duì)返回布爾類型值(真或者假)的函數(shù)命名,應(yīng)該清楚地反映其返回值情況。下面這樣的語句

            if(checkoctal(c)) ...

            是不好的,因?yàn)樗鼪]有指明什么時(shí)候返回真,什么時(shí)候返回假。而:

            i f (i soctal (c)) . . .

            就把事情說清楚了:如果參數(shù)是八進(jìn)制數(shù)字則返回真,否則為假。
            要準(zhǔn)確。名字不僅是個(gè)標(biāo)記,它還攜帶著給讀程序人的信息。誤用的名字可能引起奇怪的程
            序錯(cuò)誤。


            本書作者之一寫過一個(gè)名為i s o c t a l的宏,并且發(fā)布使用多年,而實(shí)際上它的實(shí)現(xiàn)是錯(cuò)誤的:

            #define isoctal(c) ((c) >= '0' && (c) <= '8')

            正確的應(yīng)該是:

            #define isoctal(c) ((c) >= '0' && (c) <= '7')

            這是另外一種情況:名字具有正確的含義,而對(duì)應(yīng)的實(shí)現(xiàn)卻是錯(cuò)的,一個(gè)合情合理的名字掩
            蓋了一個(gè)害人的實(shí)現(xiàn)。


            下面是另一個(gè)例子,其中的名字和實(shí)現(xiàn)完全是矛盾的:

            public boolean inTable(0bject obj) {
              i n t j = t h i s .getIndex(obj) ;
             return (j == nTable);
            }

            函數(shù)g e t I n d e x如果找到了有關(guān)對(duì)象,就返回0到n T a b l e-1之間的一個(gè)值;否則返回
            n T a b l e值。而這里i n T a b l e返回的布爾值卻正好與它名字所說的相反。在寫這段代碼時(shí),
            這種寫法未必會(huì)引起什么問題。但如果后來修改這個(gè)程序,很可能是由別的程序員來做,這
            個(gè)名字肯定會(huì)把人弄糊涂。

             

            posted on 2007-11-02 02:45 lovedday 閱讀(573) 評(píng)論(0)  編輯 收藏 引用 所屬分類: ▲ Software Program

            公告

            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關(guān)鏈接

            搜索

            最新評(píng)論

            亚洲国产高清精品线久久| 99久久国产综合精品女同图片| 亚洲成av人片不卡无码久久| 久久99国产精品一区二区| 国产A三级久久精品| 久久亚洲国产最新网站| 伊人久久一区二区三区无码| 美女久久久久久| 亚洲精品tv久久久久| 中文字幕无码av激情不卡久久| 蜜桃麻豆www久久国产精品| 久久av高潮av无码av喷吹| 久久精品国产72国产精福利| 久久久WWW免费人成精品| 国内精品久久久久| 免费精品99久久国产综合精品| 日日躁夜夜躁狠狠久久AV| 狠狠88综合久久久久综合网| 久久99国产精品久久99| 国产精品女同一区二区久久| 午夜精品久久久久久久无码| 久久久久久久91精品免费观看| 狠狠色综合网站久久久久久久高清 | 精品午夜久久福利大片| 久久99精品国产麻豆宅宅| 99久久99久久精品国产| 久久久久久青草大香综合精品| 香蕉久久永久视频| 精品少妇人妻av无码久久| 91精品国产高清久久久久久国产嫩草| 久久精品人妻一区二区三区| 久久亚洲精品国产精品婷婷| 狠狠色丁香婷婷久久综合不卡| 久久93精品国产91久久综合| 77777亚洲午夜久久多人| 久久久精品免费国产四虎| 亚洲国产精品综合久久网络| 久久精品水蜜桃av综合天堂| 色综合久久久久综合99| 久久久噜噜噜www成人网| 久久99精品国产99久久6|