<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 297,  comments - 1618,  trackbacks - 0

    原文出處:http://www.cnblogs.com/loverP/archive/2006/05/02/390787.aspx
    摘要:代碼也分種類?哪種代碼能夠自動生成?自動生成代碼會不會讓程序員沒有飯吃?或者會顛覆現有的編程模式?

    寫在前面

      學習編程,再加上實際開發,寫代碼也有7個年頭了。雖然不敢說有多少多少經驗,但思考總是有一些的。這兩年慢慢發現,原來代碼和代碼也是不同的。

      編程越來越趨于自動化,尤其在微軟的產品里,程序員總是可以很懶惰。但懶惰之余也有顧慮,35歲的年限讓很多人從25歲就開始焦慮,就開始“尋求出路”。而我卻越來越戀上編程,也曾想過將來做管理。但德魯克告訴我們,每個人都是自己的管理者,無論從事什么工作。

      現在的工作離編程好像越來越遠了,但從事教育,在給別人澄清問題的時候也讓自己對很多知識產生了更深入的理解,更重要的是,產生了更深入的思考。

      本文就是很長一段日子以來思考的結果,主要是對代碼的一些認識。今后也還將就這些問題繼續思考,但決不會停止編程的步伐。

    聲明性代碼和行為性代碼

      我認為自己最有價值的思考就是將代碼分成了這兩種類別——聲明性代碼和行為性代碼。聲明性代碼這個名詞忘了在哪里看到過的(Declarative Codes),而行為性代碼這個名詞則是我根據這個詞的對立面自編出來的。

      聲明性代碼指的是本身不完成任何實際工作,只是為編譯器和運行環境提供與程序相關信息的代碼。

      行為性代碼指的是真正用來完成實際工作中某一步驟任務的代碼。

      就以Hello World為例。

    01: using System;
    02:
    03: namespace AndersLiu.Samples
    04: {
    05:??? public class Hello
    06:??? {
    07:??????? static void Main()
    08:??????? {
    09:??????????? Console.WriteLine("Hello, world!");
    10:??????? }
    11:??? }
    12: }

      除了第09行屬于行為性代碼以外,其他代碼都是聲明性代碼。例如第01行,其作用僅僅是告訴編譯器,對于System命名空間中的類型,程序中可能僅會提到類型的名字,而不會給出完全限定的名字,需要編譯器自己進行解析。又如第03、05、07行,分別告訴編譯器,這里有個名為AndersLiu.Samples的命名空間、當前命名空間中有個名為Hello的公共類型、當前類型中有一個名為Main靜態私有方法,當然最終這些信息會保留在程序集中,指導CLR的運作。

      而第09行,才真正完成程序的功能,向屏幕上寫一個字符串。

      現在就可以明確一個問題了。眾所周知,一個C#源文件被編譯后將生成一個程序集,而程序集中存放的是IL代碼和元數據。那么,究竟哪些代碼經過編譯后會生成IL代碼,哪些代碼經過編譯后會生成元數據呢?答案不言而喻,聲明性代碼經過編譯后要么被丟棄,要么形成元數據;而行為性代碼經過編譯后,會變成IL代碼。聲明性代碼中,用來指導編譯器進行編譯的代碼將會被丟棄,而用來指導CLR運作的代碼,被保留在程序集中形成元數據。

      這是在.NET世界中,那么對于其他編程技術或語言呢?不難發現,任何編程語言的構成結構中都會有這樣兩種代碼存在。而在編程語言之外,有很多純聲明性的語言存在,比如各種標記語言(HTML、XML、VRML等)。不過純行為性語言的存在值得質疑,目前沒有那種語言中僅存在行為性代碼,這是因為任何時候編譯器都要從代碼中獲取一些信息,而這些信息幾乎總是通過聲明性代碼來傳達的。

      在編程語言之中,聲明性語言的最大特征就是沒有明顯的先后順序性。例如下面兩個變量(或域)的聲明:

    int i;
    int j;

      交換上面這兩條語句的順序,不會對程序產生任何影響。

      而行為性代碼就具有很強烈的順序性,如果兩條代碼引用了相關的實體,那么調換其順序必然會導致程序行為的異常。像i++; j++;這樣的語句交換順序沒問題,這僅僅是因為兩條語句沒有什么相關性而已。

      另外,聲明性代碼和行為性代碼并不是以語句作為劃分單位的。例如int i = 5;,雖然這是一個完整的語句,但稱它是聲明性代碼或是行為性代碼是沒有意義的,因為它實際上包含兩條代碼:int i;(變量聲明,聲明性代碼)和i = 5;(賦值,行為性代碼)。不過對于常數聲明來說,例如const int c = 5;,盡管其中出現了賦值運算符=,但仍屬于聲明性代碼。

      對于C#語言來說,行為性代碼只能出現在方法體、屬性/索引器的get/set訪問器中。而類型的成員(域、屬性、方法和事件)聲明,都是聲明性代碼。那么,為什么上面提到的int i = 5;在C#中可以作為一個類型的域聲明呢?來看一個例子,例如有下面這樣一個簡單的類定義:

    namespace AndersLiu.Test
    {
    ??? class CSample
    ??? {
    ??????? int i = 10;
    ??????? static int si = 5;
    ??? }
    }

      使用/t:library參數將其編譯為一個dll,并使用ILDASM對其進行Dump,可以從返回編出來的代碼中看到這樣的類定義(其中的中文注釋是我自己添加的):

    .class private auto ansi beforefieldinit AndersLiu.Test.CSample
    extends [mscorlib]System.Object
    {
    // 兩個私有域的定義,一個實例域i,一個靜態域si
    .field private int32 i
    .field private static int32 si

    // 編譯器自動生成的實例默認構造器 .ctor
    .method public hidebysig specialname rtspecialname
    instance void .ctor() cil managed
    {
    ??? // Code size 16 (0x10)
    ??? .maxstack 8
    ??? IL_0000: ldarg.0

    ??? // 為實例域i賦初值10
    ??? IL_0001: ldc.i4.s 10
    ??? IL_0003: stfld int32 AndersLiu.Test.CSample::i

    ??? // 賦值完畢,調用父類實例默認構造器
    ??? IL_0008: ldarg.0
    ??? IL_0009: call instance void [mscorlib]System.Object::.ctor()
    ??? IL_000e: nop
    ??? IL_000f: ret
    } // end of method CSample::.ctor

    // 編譯器自動生成的靜態構造器 .cctor
    .method private hidebysig specialname rtspecialname static
    void .cctor() cil managed
    {
    ??? // Code size 7 (0x7)
    ??? .maxstack 8

    ??? // 為靜態域賦si初值5
    ??? IL_0000: ldc.i4.5
    ??? IL_0001: stsfld int32 AndersLiu.Test.CSample::si

    ??? // 賦值完畢,返回
    ??? IL_0006: ret
    } // end of method CSample::.cctor

      從這里可以看出,編譯器自動將帶有初始化器的域聲明代碼拆成了兩個部分,域的聲明保留在類型(元數據)中,而對域的賦值則被插入到了自動生成的構造器代碼的最前面(形成IL代碼)。

      而下面的代碼就沒有那么幸運了,它們只能作為局部變量,如果將它們作為類型的域定義,就會發生編譯錯誤。

    int i = 5;
    int j = i + 5;

      這是因為C#編譯器只會將無順序性的(不相關的)行為性代碼轉移到構造器中,上面的代碼明顯存在強烈的順序性,因此編譯器為了確保程序行為的一致性,就會拒絕翻譯這段代碼。

    小議代碼自動生成

      各大軟件公司(姑且這么稱呼他們)和各種計算機方面的研究機構都一直在研究代碼自動生成的技術。編譯器其實是代碼自動生成的最好例子,我們編寫程序的行為可以認為是在干涉編譯器,影響它生成代碼的行為。

      不過提到代碼自動生成,更多人的直觀認識是“源代碼的自動生成”,其實本文要討論的,也正是源代碼的自動生成。因此在本文中,如果不是特殊強調,就認為代碼自動生成等于源代碼自動生成。

      研究機構我不清楚,但在商業領域,在代碼自動生成技術上走得最遠的恐怕就是微軟了。從很久很久以前,微軟的各種開發工具(甚至包括像Office這類非嚴格意義上的開發工具)就都提供了豐富的代碼自動生成功能。這些功能體現在各種各樣的開發向導上,如著名的MFC應用程序框架、Visual Basic的“所見即所得”開發環境等等。

      過去的代碼自動生成功能往往有限,雖然生成了大量的代碼,但程序員的工作依然是比較繁重的。且不說很多工作要靠程序員手工完成,遇到生成的代碼難以滿足系統需求時,修改自動生成的代碼的任務量就足以讓一般開發愛好者望而卻步。甚至,有時自動生成的代碼還會出現BUG,要靠程序員手工fix。

      但自動生成代碼的功能還是或多或少會在程序員中引發一些焦慮。隨著.NET的出現(尤其是Visual Studio 2005的出現),很多代碼是不需要程序員來完成的,甚至程序員都可以忽視它們的存在。比如Typed DataSet、Web Services Proxy,有多少一線的程序員有空或者是愿意去看看它們的代碼是什么樣子的?

      前不久參加了Vista的開發培訓,看到無論是WPF、WCF還是WWF,開發起來都不用編寫太多的代碼,無非就是改改配置文件,或是寫上一兩句“膠水代碼”。難道,程序員的“末日”真的來臨了?

      在解決這個問題之前,還是看看究竟哪些代碼能夠自動生成吧。

      很簡單,一句話可以概括:聲明性代碼和形成了模式的行為性代碼可以自動生成。

      以Visual Studio 2005的Class Diagram為例,Class Diagram除了可以將項目中現有代碼中的類結構表示出來以外,還可以通過將Toolbox中表示各種類型和類型間關系的圖示拖到類圖中來完成系統的設計。通過圖形化方式進行編程的時代終于正式到來了。

      但是對Class Diagram自動生成的代碼稍作觀察就能發現,這些代碼只是類型的一個大致的“框架”,只是類型及其成員的聲明而已——這些不都是聲明性代碼么。真的遇到方法體或者屬性/索引器的get/set訪問器,還不是要拋一個NotImplementedException異常出來?

      另外一類能夠自動生成的代碼是已經形成了模式的行為性代碼。例如前面提到的Typed DataSet和Web Services Proxy,其中都有一些行為性代碼存在,這些代碼很簡單,任誰都會編寫這樣的代碼去完成相應的工作,因此可以自動生成。還有一類形成了模式的行為性代碼,它們以“語法糖”的形式出現,由編譯器在真正的編譯開始之前完成代碼自動生成工作,例如C#中的foreach語句、using語句(并非“using指令”)和lock語句等。

      此外,Visual Studio 2005中還強調了Code Snippets的概念,這從某些角度來看,也是在自動生成形成了模式的行為性代碼。

    程序員的出路

      文章進行到這里,結論不言而喻了吧?

      不過這一部分的標題起得不好,僅作為標題使用,請不要就這個標題對我的闡述進行攻擊。首先就微軟的作風來講,不會把程序員逼到“找出路”的境地。微軟很懂得“生態環境”的概念,明白沒有更多的開發者就沒有更多的Windows應用,沒有更多的Windows應用就沒有更多的Windows市場,沒有更多的Windows市場,微軟也就失去了生機。因此微軟“自古以來”就一直給開發者提供者最好的資源和廣泛的生存空間,無論是初出茅廬的編程新手,還是深諳理論和實踐的技術大師,在微軟的平臺上都有自己的舞臺。今天是這樣,今后也是這樣。其次,就算程序員真的要“找出路”,這里一沒給出最佳選擇,二并沒有提到所有可供參考的選擇,只是說一些自己的想法而已。說到這里不得不申明以下,本文中提到的“程序員”,都特指“微軟平臺上的程序員”。

      因此,對于想一直搞開發,而不想轉向管理者或轉向其他領域的程序員來說,這部分內容可能會有一些參考意義。

      綜合前幾部分的論述,程序員要想找到“出路”,或者想使自己的工作更有意義,無外乎向兩個方向發展——一是向宏觀發展,做系統架構師,或者至少是做設計者;二就是向微觀發展,在沒有模式的行為性代碼上下功夫。

      當代的開發工具盡管可以極大程度地便利設計工作,但畢竟只是工具,真正的設計思想和設計實踐依然是開發者自己的財富。我不敢說設計工作在將來能不能實現自動化(實際上有些已經實現了),但目前很多設計工作還是靠人為來完成的。學會站在一個很高的層次上,對系統整體進行把握,在很長時間內還是可以利于不敗之地的。

      然而,設計上也存在很多模式,如果選擇作為一個設計者,絕對不能沉浸在已有的模式中沾沾自喜。一旦某日設計工作得以完善的自動化,形成了模式的設計思想將是第一批被設計工具所淹沒的。一定要在反復的設計工作中磨練自己的思維,清醒地認識到那些設計已經形成了模式,在套用模式的同時對現有思路進行突破。

      而所謂的行為性代碼,其實往往體現著一系列的算法。何謂“算法”?解決特定理論問題的思維模式而已。因此,在學習現有算法的原理和使用現有算法解決問題的同時,仍不要忘記突破模式,尋求更新鮮的思路。如果只是掌握了很多爆難無比的算法的使用,依然尋求不到“出路”,因為它仍然是模式,仍然可以自動生成。比如編譯原理,很多人并不能深刻掌握,但有很多工具可以自動生成詞法和語法的分析器源代碼。那么,掌握了編譯原理中的理論,掌握了分析器生成器的使用方法,能解決問題嗎?

      總而言之,程序員,優秀的程序員并不好做,以前是這樣,以后也是這樣。只有提高自己的思維能力,說白了就是做個聰明人,才能有飯吃。不管啥年頭,混計算機這行光靠體力活可不行……

    posted on 2007-03-27 13:35 阿蜜果 閱讀(688) 評論(3)  編輯  收藏 所屬分類: Auto Code


    FeedBack:
    # re: [轉]關于編碼的思考
    2007-06-28 18:14 | chars
    很有收獲,謝謝老師  回復  更多評論
      
    # re: [轉]關于編碼的思考
    2007-07-25 08:42 | sitinspring
    微軟把人當SB就不提了?  回復  更多評論
      
    # re: [轉]關于編碼的思考
    2008-01-08 13:09 | hbyufan@hotmail.com
    程序員,優秀的程序員并不好做,以前是這樣,以后也是這樣。只有提高自己的思維能力,說白了就是做個聰明人,才能有飯吃。不管啥年頭,混計算機這行光靠體力活可不行……
      回復  更多評論
      
    <2007年3月>
    25262728123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

          生活將我們磨圓,是為了讓我們滾得更遠——“圓”來如此。
          我的作品:
          玩轉Axure RP  (2015年12月出版)
          

          Power Designer系統分析與建模實戰  (2015年7月出版)
          
         Struts2+Hibernate3+Spring2   (2010年5月出版)
         

    留言簿(263)

    隨筆分類

    隨筆檔案

    文章分類

    相冊

    關注blog

    積分與排名

    • 積分 - 2294312
    • 排名 - 3

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲GV天堂GV无码男同| 亚洲日本成本人观看| 成人免费一区二区三区| av无码东京热亚洲男人的天堂| 亚洲国产成人精品无码区花野真一| 卡1卡2卡3卡4卡5免费视频| 亚洲免费网站观看视频| 国产精品jizz在线观看免费| 真人无码作爱免费视频| 免费一级毛片不卡不收费| jizz免费在线影视观看网站| 亚洲中文字幕无码永久在线| 国产亚洲免费的视频看| 久久久亚洲欧洲日产国码农村| 精品视频一区二区三区免费| 亚洲色图古典武侠| 成年女人喷潮毛片免费播放| 日韩色视频一区二区三区亚洲| 亚洲精品无码永久在线观看| 国内精品一级毛片免费看| 亚洲高清资源在线观看| 免费人成视频在线| 黄网站在线播放视频免费观看| 亚洲精品国产精品国自产观看| 成人一区二区免费视频| 亚洲国产精品成人精品软件| 国产成人在线观看免费网站| 国产高潮流白浆喷水免费A片 | 亚洲精品线在线观看| 好先生在线观看免费播放| 人妻仑刮八A级毛片免费看| 亚洲成AV人在线观看天堂无码| 99久久免费国产香蕉麻豆 | 免费在线视频一区| 99久久免费国产特黄| 亚洲av产在线精品亚洲第一站| 国产精品久久免费视频| 久久久久久成人毛片免费看| 亚洲最大的成人网| 亚洲精品乱码久久久久66| 性做久久久久久久免费看|