天天看點

從配置檔案的格式扯到GUI和CLI

看一下windows的ini格式配置檔案:

[startup]

cmd=a.bat

para=...

...

windows的配置都是諸如上述的ini檔案,格式如下:

[section]

name=value

這種配置檔案雖然沒有二進制檔案那般無恥可畢竟也是“格式化”的,比如上面的"[","]","="等都是格式,這種“格式”定義得越多,處理它的程式就越複雜和專業,最終随着配置檔案的複雜化,處理程式也最終變成了諸如word之類的龐然大物,是以說,盡可能不要定義格式太複雜的配置檔案,程式不應該将大量邏輯用于處理檔案IO,是以盡可能保持配置檔案的簡單性,正如unix的文本配置檔案那樣,沒有section,以行為機關,每次處理一行。處理程式可以十分簡單,以一個while循環為大架構,裡面就是一個狀态機,每一行就是狀态機的一個狀态,同時每一行也是一個子狀态機,解析程式控制這兩個狀态機向前推進,直到檔案被處理完畢,下面是一個經典的配置檔案處理架構:

static void read_config_file (...)

{

    int line_num;

    char line[OPTION_LINE_SIZE];  //配置檔案的一行

    char *p[MAX_PARMS];    //配置檔案一行轉化而成的有意義的數組

    fp = fopen (file, "r");

    line_num = 0;

    while (fgets(line, sizeof (line), fp)) {  //讀取一行

        ++line_num; //下面的parse_line的實作是個狀态機,本質上就是将沒有意義的一行資料line轉化為有意義的一個字元串數組p

        if (parse_line (line, p, SIZE (p), file, line_num, msglevel, &options->gc)) {

            bypass_doubledash (&p[0]); //越過"--"。下面的add_option将parse_line的結果--有意義的數組p填充到結構體option中,進而完成對配置檔案一行的解析

            add_option (options, p, file, line_num, level, msglevel, permission_mask, option_types_found, es);

        }

    }

    fclose (fp);

}

上面的處理程式結構很緊湊,基本就是三件事情,1.讀取一行;2.将一行無意義字元串轉化為有意義的字元串數組;3.将有意義的字元串數組轉化為程式内部結構體。除了諸如注釋"#"需要處理之外(很簡單,直接跳過),很少需要處理複雜的額外格式。如果說希望像處理指令行參數那樣使用getopt_long處理參數,那麼配置檔案格式更簡單,直接寫成一行或者分行的情況在處理時删除換行符,然後将檔案讀入一個緩沖區,用awk處理該緩沖區,使之格式化成main參數argv[]的格式,最終傳入getopt_long即可(man 3 getopt),非常靈活。正式因為配置檔案寫成--XXX yyy之類的格式可讀性受到影響,是以才使用XXX yyy的格式,對于指令行,'-'或者'--'是可了解的最佳方式,但是對于配置檔案,它們都不需要了,對比windows的ini檔案,處理程式少了對[,],=等的解析。

     windows為何采用ini“如此複雜”的文本格式,不得而知,但是unix的簡單配置檔案先入為主倒是不争的事實,即使windows中也有unix的影子,$WIN/system32/drivers/etc目錄下面的檔案hosts,networks,protocol等就是執行個體,即使是windows,在涉及網絡配置的時候也還是使用unix的方式,這恰恰證明了網絡從unix而來的事實(BSD和Sun的貢獻很大)。既然很多網絡配置業已成型,windows索性也要拿來主義了,這個隻是猜測...windows其實也不是傻到了故意将配置檔案複雜化,windows之是以采用基于section的配置檔案可能是為了迎合其GUI,基于GUI的配置往往是具有結構的,最終的一個程式的配置就是一個樹形的結構,比如“開始”菜單就是一個樹形結構,而CLI程式的配置幾乎都是線形結構,如果一個程式的配置是樹形結構的話,采用線形的配置檔案顯然難于和GUI界面相對應,是以隻能采用具有一定結構的配置檔案,在這些結構化配置檔案中,最簡單的就是ini檔案了,可見windows并不是不追求簡單,而是它的GUI本身就将“簡單”這個詞的意義給異化了,在GUI的層次上,最簡單的配置檔案就是ini格式了,雖然并不是所有使用ini檔案的程式都有GUI。這裡說的GUI是一種思想而不僅僅指一個界面。

     之是以說GUI臃腫是因為它沒有做到單一的抽象,一個“按鈕”除了具體的邏輯意義之外還有“視覺感官”意義,一個多級的菜單需要我們首先将它找出來才能使用,是以如何組織GUI結構就顯得尤為重要,一個好的GUI程式必然需要組織良好的控件,反觀CLI,隻需要設計出配置參數即可,這些參數選項在指令行或者配置檔案中的順序并沒有要求,設計上消除了“感官”需求,将所有的配置選項集中與單一的邏輯意義,是以才能使用最簡單最高效的配置檔案。CLI是外向的,GUI是内向的,其間的差別和字母文字之于漢字的差別一緻。如果想在CLI程式中增加一個新的選項,隻需兩步即可,1.在程式内部結構體中增加一個字段;2.在解析參數時增加一個else if或者case,這種工作可以無限擴充,也就是說參數可以随意增加,最終隻要完善一下手冊,使用者就不會誤用或者為不知參數何意而抓狂,另外CLI的使用者沒有“尋找”參數位置的問題,使用一個選項參數之前,使用者必知道其意義(查閱手冊),然後直接用鍵盤敲入即可。但是對于GUI程式來講,增加一個選項必然牽扯到界面的變動,首先要考慮新的選項加在什麼位置,那個菜單的哪個菜單項之下,随着選項的持續增多,菜單平鋪則太長,子集過多則太深,使用控件之前必先找到該控件,總之查找的過程就是不便,最終控件的數量趨于可查找意義上的飽和,GUI在控件可查找性上已經不堪重負,再也不能增加控件了,GUI可擴充性受到“感官”限制,此謂内向。

     GUI浪費了鍵盤上絕大多數按鍵,很多時候僅用滑鼠即可,這在選項參數少的時候特别有用,比如回答“是”與“否”的案例,在GUI的情況下,使用者一眼就可以看到寫着“是”和“否”的控件,然後下滑鼠點選即可,可是使用CLI的話,使用者必須首先查閱手冊,了解如果想選擇“是”,因該輸入什麼...,面對着鍵盤上如此多的按鍵,真的不知道該按下哪些,但是如果隻有兩個按鍵,胡亂一按就可能成功,如果隻有一個按鍵,那麼就隻有按它了,随着選項的增加,鍵盤被有效利用了,CLI的優勢就展現出來了,最起碼它使你不再覺得設計這麼多按鍵是浪費了。選項越多,程式功能越複雜,越強大,而由于GUI有着天生的選項個數的限制,根本承擔不了大任,除非放棄GUI,在windows上也寫指令行程式。配置過IIS和Apache的應該對GUI和CLI的差別有所感受。

      正是由于CLI程式使用鍵盤來配置而不是兩擊或者三擊的滑鼠,是以在CLI環境中才不提倡長檔案名而幾乎總用縮寫,這是為了最少化輸入(或許早期還起到了節省記憶體的作用),反觀GUI,不管多長的檔案名,點選即可,沒有圖示的情況下,檔案名短了手一抖還不容易擊中呢!最後GUI程式可以說沒有真正配置的概念,它們幾乎一開始就沒有可擴充性,如果說CLI環境的程式是一台通用計算機,那麼GUI程式則是一台已定制的帶有固定按鈕的電視機或者任意帶有固定面闆的機器。

 本文轉自 dog250 51CTO部落格,原文連結:http://blog.51cto.com/dog250/1271827

繼續閱讀