• <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>

            第一桶 從C到C++ 第六碗 陳老C演迭代開發(fā) 潘小P學(xué)漸進(jìn)編程(之一)

                 “今天早上陽光明媚啊,”老C在教研室門口深呼吸。

                 “嗯,東花園顯得很漂亮啊……”小P應(yīng)聲道,兩人走過東花園,來到教研室,準(zhǔn)備妥當(dāng)后,坐在小P桌前。

                 “好,我們今天先不評論你的代碼內(nèi)容,而是重新來寫這個代碼。”老C不好意思說小P的代碼太爛以至于無法評審,所以決定另起爐灶,“然后我們拿新寫的這個版本與原來的版本做比較。”

                 “也好。”小P同意。

                 “這樣,我們兩個來一起寫這個代碼,這樣更快一些。”老C道。

                 “好啊好啊。”

                 兩人新建了一個名叫AppleGame的工程,然后老C添加了一個main.c的文件,“本來在這里應(yīng)當(dāng)使用配置管理工具的,但是因為簡單起見,我們就土 法煉鋼,采用拷貝的方法記錄版本吧。”老C一邊說一邊在硬盤上建立了一個新目錄,起名為AppleGame_V0.01,“名字也隨便起了,不用使用 VBD等等復(fù)雜的規(guī)范,但是你千萬注意這只是例子,以后千萬不要隨便學(xué)啊。”老C解釋道,“至于什么配置管理和版本命名規(guī)范,我們以后再說。”

                 “槑……”小P有些暈,下意識的回答道。

                 “我們的做法在一般面試、筆試的時候可千萬不要用,完全是大炮打蚊子……在這里出現(xiàn)只是為了演示,然而如果你熟悉了這樣的開發(fā)過程,再反過來使用更直接的方法應(yīng)付面試和筆試還是比較容易的,”老C又補(bǔ)充道,“大炮一響,黃金萬兩……有時打打大炮也是有價值的,起碼熟悉了開炮過程,這樣以后用大炮打黃金就駕輕就熟了……”

                 “……”小P決定無視老C的自言自語,心想人上了年紀(jì)就是有些羅嗦。

                 “好,第一個任務(wù),寫一個main函數(shù)。”

                 “這個簡單。”小P應(yīng)道。在文件上敲下幾行代碼。


            void main()
            {
            }

                 “唉,這樣是有問題滴……”老C說到。

                 “什么問題?”

                 “規(guī)范……”老C回答,“我們應(yīng)當(dāng)這樣寫。”老C開始更改小P的代碼。


            int main()

            {

                return 0;

            }

            int main(int argc, char* argv[])

            {

                return 0;

            }


                 “我們兩個中間選一個,因為這個程序沒有命令支持,所以就第一個吧。”老C說到,“這個是C99的新標(biāo)準(zhǔn),我們還是按照標(biāo)準(zhǔn)來吧。”老C補(bǔ)充道,“你可以 在學(xué)校圖書館查查《ISO/IEC 9899 : 1999》這個文檔,里面說的很清楚。如果我們還使用原來的格式,可能在代碼兼容性上會出問題,我們寫出的代碼就不能在所有編譯器上編譯通過……”

                 “是么?這么復(fù)雜……”小P有些疑惑,“好吧,那么就這樣吧。”

                 “那么現(xiàn)在說說你解決這道題的思路吧。”老C問。

                 “嗯,先設(shè)計一個循環(huán)隊列,每個隊列中的元素表示一個小朋友,1表示在對列中,0表示他不在對列中,然后開始按照規(guī)則玩游戲,直到剩下最后一個小朋友,然后在隊列中找出這個剩下的元素,打印它的下標(biāo)……就是座位號碼啦……”

                 “嗯,思路還算清晰,”老C評論,“我們姑且不論選擇循環(huán)隊列是否合適,就先按照這個思路來做,等到后面再評審更改吧。”然后他在文件中添加如下的語句。


            int main()
            {
                /* Initialize the queue. */

                /* Play the game, until the last one is found. */

                /* Search the last one's seat number.  */

                return 0;
            }

                 “好了,我們的第一版程序完成了。”老C拍拍手。
                 “完了?”小P有些不敢相信。
                 “是啊,”老C確定的說,“編程不只是寫代碼,代碼 != 程序!當(dāng)你開始進(jìn)行思考的時候,就開始進(jìn)行程序設(shè)計了,代碼不過是程序的表達(dá)方式。如果人類的語言可以在計算機(jī)上執(zhí)行,你剛才說的話,就是代碼。是不是這樣?”
                 “嗯,有些道理……”
                 “編譯!好了,我們的第一版程序沒有什么問題!”老C說完,將main.c文件拷貝到AppleGame_V0.01文件夾下面,然后又新建了一個AppleGame_V0.02的文件夾。
                 “下來我們需要一個調(diào)試宏,”老P說到,“本來可以使用IDE為我們準(zhǔn)備的debug和release編譯選項,但是這里我們先不用,為了明白背后的道理,我們完全自己打造一個先。關(guān)于debug和release,我們以后再說。”
                 “哦……”小P點(diǎn)點(diǎn)頭。
                 老C在main.c的開頭寫下如下代碼。

            #include <stdio.h>

            #define PRINT_DEBUG_INFO


            #if defined(PRINT_DEBUG_INFO)
            #define MY_DEBUG(str)            printf(str)
            #define MY_DEBUG_1(str, par)    printf(str, par)
            #else
            #define MY_DEBUG(str)
            #define MY_DEBUG_1(str, par)
            #endif // PRINT_DEBUG_INFO

                 “這幾個宏用于在調(diào)試的時候輸出一些中間信息,”老C解釋道,“如果我們想輸出調(diào)試信息,只需要#define PRINT_DEBUG_INFO就可以了,否則就注釋掉這個宏。這只是一些小技巧而已,沒有什么神秘的。”
                 “是嗎?嗯,我看看……”小P琢磨著代碼。
                 “下來進(jìn)行一些實質(zhì)性的,”老C接著說,“但是之前我們要了解一個規(guī)則,用問題域的詞匯去編程,而不是解決域。”
                 “槑,什么叫問題域?解決域?”小P不解。
                 “我寫你看好了。”老C說道,然后在main.c文件中接下來的部分寫下如下內(nèi)容。

            //////////////////////////////////////////////////////////////////////////
            //
            #define CHILDREN_NUM    20U

            typedef int SEAT_NUM;
            typedef enum tagEXIST_STATE { ABSENT, EXISTED } EXIST_STATE;
            typedef struct tagCHILD
            {
                SEAT_NUM       seatNum_;
                EXIST_STATE    existState_;
            }CHILD;

            #define QUEUE_LENGTH    CHILDREN_NUM
            typedef CHILD QUEUE_CONTENT;
            typedef struct tagQUEUE
            {
                int size_;
                int index_;
                QUEUE_CONTENT queue_[QUEUE_LENGTH];
            }QUEUE;

            typedef struct tagAPPLE_GAME
            {
                int currCountNum_;
                int childrenRemained_;
                QUEUE childrenQueue_;
            }APPLE_GAME;

            void InitAppleGame (APPLE_GAME* game);
            int IsGameOver (APPLE_GAME* game);
            void PlayGame (APPLE_GAME*  game);
            int LastChildSeatNum (APPLE_GAME* game);



            //////////////////////////////////////////////////////////////////////////
            //
            int main()
            {
                APPLE_GAME theGame;
                int num;
                
                /* Initialize the game. */
                InitAppleGame(&theGame);

                /* Play the game, until the last child is found. */
                while (!IsGameOver(&theGame))
                {
                    PlayGame(&theGame);
                }

                /* Search the last child's seat number.  */
                num = LastChildSeatNum(&theGame);

                printf("The last child's seat number is %d.\n", num);

                return 0;
            }



            //////////////////////////////////////////////////////////////////////////
            //
            void InitAppleGame(APPLE_GAME* game)
            {
                MY_DEBUG("Init the apple game.\n");
            }

            int IsGameOver(APPLE_GAME* game)
            {
                static int n = -1;
                
                MY_DEBUG("Only one child?\n");
                ++n;

                return n;
            }

            void PlayGame(APPLE_GAME* game)
            {
                MY_DEBUG("Play game...\n");
            }

            int LastChildSeatNum(APPLE_GAME* game)
            {
                int n = 1;
                MY_DEBUG("Searching last child's seat number\n");

                return n;
            }

                 “喏,就是這個意思,盡量用現(xiàn)實生活的語言對需要解決的問題進(jìn)行描述,并將關(guān)系相近的變量用結(jié)構(gòu)體放在一起。”老C說,“然后將對這些名詞的操作寫成可以 用現(xiàn)實生活語言表達(dá)的函數(shù),并將結(jié)構(gòu)體作為函數(shù)的入口參數(shù)傳入函數(shù)中。”老C咽了一口唾沫,“咳咳,你再比較比較我們這兩版的注釋有什么變化?”
                 “叫我看看……”小P開始比較代碼,“哦,在這個版本你用 game 代替了 queue,用 child 代替了 one, 但是有什么實質(zhì)區(qū)別?”小P有些不解。
                 “嗯,這個是一個用問題域詞匯編程而不是解決域詞匯編程的例子,最大的優(yōu)點(diǎn)是意圖明確,容易理解,代碼可讀性強(qiáng);另外一個好處是相對穩(wěn)定——比如用 game 代替 queue——其一,評審代碼的人可能會不明白這個queue是做什么的,為什么和下面的初始化函數(shù)格格不入,從而造成你頻繁的回答大量的溝通性的問題, 這將大大影響你生活的穩(wěn)定性和質(zhì)量;其二,如果我們將來——我是說如果——使用list數(shù)據(jù)結(jié)構(gòu)來替換queue,避免了還要更改注釋的風(fēng)險——代碼更新 而注釋陳舊,正是我們在進(jìn)行項目開發(fā)時一個特別特別特別的n次冪嚴(yán)重的問題……而使用問題域的詞匯,只要需求不發(fā)生變更,則我們就不需要修改什么而導(dǎo)致一 些……代碼人格上的分裂……”
                 “哦,我再消化消化……”小P開始看代碼,“下面這些函數(shù)的實現(xiàn)是什么意思?”
                 “嗯,是測試,”老C說,“我們先不看具體函數(shù),先看看main()函數(shù)的主要結(jié)構(gòu)。”

            int main()
            {
                APPLE_GAME theGame;
                int num;
                
                /* Initialize the game. */
                InitAppleGame(&theGame);

                /* Play the game, until the last child is found. */
                while (!IsGameOver(&theGame))
                {
                    PlayGame(&theGame);
                }

                /* Search the last child's seat number.  */
                num = LastChildSeatNum(&theGame);

                printf("The last child's seat number is %d.\n", num);

                return 0;
            }

                 “我們用實際的代碼完善剛才的注釋——剛才的注釋其實就是偽代碼的一部分——然后在框架函數(shù)中加入測試代碼,檢驗我們的算法是否可行。”老C解釋道,“現(xiàn)在我們的算法一目了然,你看看是否是用問題域的詞匯表達(dá)算法更清晰一些呢?比一些a,b,c之類,或者其類似的解決域內(nèi)的名字更好理解吧?”
                 “哦,我再看看……”小P答道,“我要消化一下……”
                 “嗯,”等小P抬起頭,老C補(bǔ)充道,“接下來一個重要的規(guī)則是先構(gòu)思如何測試,更先于編碼!”
                 “稍等,”可能被新的信息灌輸?shù)挠行╊^暈,“這個是什么意思?”小P有些反應(yīng)不過來。
                 “就是說,在編碼之前,我們要先想好如何測試我們即將要編寫出來的代碼。我們的代碼是否易于被測試,關(guān)系到我們代碼質(zhì)量的生命!”老C解釋道,“如果你一 開始就考慮到這些問題,并留有充分的余地,那么在做代碼自測和測試人員測試時,會節(jié)省組織內(nèi)部大量的精力……算了,這些也是要靠編寫代碼的規(guī)模積累起來的 經(jīng)驗,你以后會慢慢的明白的。但是,無論如何你在編寫代碼的時候要保持足夠的意識,要不斷提醒自己,我所寫的代碼易于測試嗎?”
                 “好,我記住了。”小P說。
                 “呵呵,其實經(jīng)歷了一些挫折你才會真正明白——不過就算建立了概念也不錯。”老C笑道,“現(xiàn)在你編譯并運(yùn)行一下代碼吧,觀察一下屏幕輸出的信息……”
                 “好,”小P看了看文件底部的函數(shù)實現(xiàn),然后又看了看屏幕輸出信息,“哦,算法的脈絡(luò)這樣看就比較清楚了,果然我腦海中就是這么想的,不過現(xiàn)在更具體,也好追蹤了。”
                 “O.K.!我們第二版的程序又有了!”
                 “這么快?為什么?”小P不解道。
                 “我們驗證了算法,證實算法框架運(yùn)行與設(shè)計——就是你腦海中的步驟——是一致的,這樣當(dāng)然ok了!”老C一邊說一邊將main.c拷貝到AppleGame_V0.02,并且又新建了一個AppleGame_V0.03目錄。

            (請等待V0.03版本)

            posted on 2009-01-23 03:36 Anderson 閱讀(1768) 評論(6)  編輯 收藏 引用

            評論

            # re: 第一桶 從C到C++ 第六碗 陳老C演迭代開發(fā) 潘小P學(xué)漸進(jìn)編程(之一)[未登錄] 2009-01-23 12:40 Len

            看來更新的速度很快呀,又要結(jié)冊出版了  回復(fù)  更多評論   

            # re: 第一桶 從C到C++ 第六碗 陳老C演迭代開發(fā) 潘小P學(xué)漸進(jìn)編程(之一)[未登錄] 2009-01-23 16:45 ypp

            非常不錯,原創(chuàng)作品,極力支持  回復(fù)  更多評論   

            # re: 第一桶 從C到C++ 第六碗 陳老C演迭代開發(fā) 潘小P學(xué)漸進(jìn)編程(之一) 2009-01-23 17:22 winsty

            現(xiàn)在用純C開發(fā)的機(jī)會太少了吧
            個人覺得某些規(guī)范在OOP下并不合適  回復(fù)  更多評論   

            # re: 第一桶 從C到C++ 第六碗 陳老C演迭代開發(fā) 潘小P學(xué)漸進(jìn)編程(之一) 2009-01-23 23:55 imnobody

            真的很棒,i like  回復(fù)  更多評論   

            # re: 第一桶 從C到C++ 第六碗 陳老C演迭代開發(fā) 潘小P學(xué)漸進(jìn)編程(之一) 2009-02-04 00:24 zoujer

            此章學(xué)到很多東西,期待更精彩的~~~~~  回復(fù)  更多評論   

            # re: 第一桶 從C到C++ 第六碗 陳老C演迭代開發(fā) 潘小P學(xué)漸進(jìn)編程(之一) 2009-02-04 09:03 tmhlcwp

            之前在"C++博客"上有看到過同風(fēng)格的博文,但現(xiàn)在找不到了,有誰知道的告訴下哈,謝謝了  回復(fù)  更多評論   


            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            <2009年9月>
            303112345
            6789101112
            13141516171819
            20212223242526
            27282930123
            45678910

            導(dǎo)航

            統(tǒng)計

            常用鏈接

            留言簿(6)

            隨筆檔案(21)

            文章檔案(1)

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            亚洲AV日韩精品久久久久久 | 欧美与黑人午夜性猛交久久久 | 久久99精品久久久久久齐齐| 久久99久久99小草精品免视看 | 国产精品久久久久…| 成人久久综合网| 久久综合九色综合久99| 亚洲国产精品无码成人片久久| 91久久精品91久久性色| 四虎国产精品成人免费久久| 波多野结衣中文字幕久久| 日韩电影久久久被窝网| 波多野结衣中文字幕久久| 日本欧美国产精品第一页久久| 国产精品无码久久综合 | 久久精品国产免费一区| 久久天天躁狠狠躁夜夜不卡| 激情综合色综合久久综合| 天天躁日日躁狠狠久久| 亚洲国产日韩欧美久久| a级毛片无码兔费真人久久| 久久夜色精品国产噜噜麻豆| 亚洲国产精品综合久久网络| 91精品国产色综久久| 久久WWW免费人成一看片| 久久久久免费精品国产| 国内精品久久久久久中文字幕| 要久久爱在线免费观看| 伊人久久大香线焦综合四虎| 99久久国产亚洲综合精品| 香蕉久久一区二区不卡无毒影院| 精品蜜臀久久久久99网站| 久久强奷乱码老熟女网站| 狠狠色丁香婷婷久久综合五月| 精品久久久久久久久久中文字幕 | 久久精品国产第一区二区三区| 深夜久久AAAAA级毛片免费看| 欧美精品九九99久久在观看| 久久精品国产黑森林| 久久精品国产亚洲7777| 蜜桃麻豆www久久国产精品|