1. 程式人生 > 其它 >談論程式碼生成,我們究竟在談什麼

談論程式碼生成,我們究竟在談什麼

對於程式碼生成技術,我們希望他能幫我們解決什麼問題?

1. 一些邏輯簡單的機械式程式碼,比如大量的get/set(getter/setter)程式碼
2. 一些稍微複雜的套路式的程式碼,比如符合某個框架標準的資料庫的增刪改查程式碼
3. 同時我們希望生成的程式碼是沒有bug的
4. 不僅希望他能代替我們勞動,而且要求他勞動效率很高,即要快速地生成程式碼。

最容易生成的就是類似get/set這樣的機械式程式碼。然後是套路式的程式碼,只要你能手工寫一遍,再把它製作成模板也不會很難。

這裡需要補充說明一下,對於有資料庫操作的軟體而言,業務(即業務邏輯,下同)往往由增刪改查組成,但增刪改查卻不是業務,可能帶有些業務的“味道”,業務是包含增刪改查在內的多種操作的有機組合。

下面我們來談談對程式碼生成器的期望。

高質量

我們希望是無論生成簡單還是生成複雜程式碼,或者從簡單到複雜的發展過程,自始至終的生成的程式碼都沒有bug。但是隻要是人寫的程式碼,就很難沒bug。模板也是一種程式碼。怎麼辦?模板具有大量重複使用的特點,所以,一旦模板有bug容易被發現,一旦修復了某個bug,就意味著以後使用這個模板生成的程式碼都不再有這個bug。這一點跟不使用生成器,手工寫程式碼是不一樣的。手工寫程式碼,這次修復了一個bug,難保下次寫同類程式碼不再出相同的bug。唯有藉助程式碼生成,才能無限的逼近零bug。

高效率

相對於手工寫程式碼,機器寫程式碼的速度是飛快的。人平均一秒鐘寫不了一行程式碼,機器一秒鐘輕輕鬆鬆寫100行,甚至更多。顯然,程式碼生成能極大地提高軟體的生產效率。

模板與非模版

程式碼生成技術大體上可以分成模板與非模板兩大類。他們共同的特點都是要解決死程式碼和活程式碼的組織問題,或者說是固定的程式碼與變化的程式碼的如何正確地編織在一起,這個問題。比如,這樣的模板

print("hello $(name)")

此模板死的部分就是列印功能和字元常量hello,活的部分就是hello後面那個名字。
它可以生成這樣的程式碼

print("hello billy")

或者

print("hello world")

在它的外層還可以加個迴圈從而生成多條print語句。還可以加條件,從而根據條件決定要不要生成某些語句。將資料和模版通過模板引擎的處理,生成目的碼,這個就是基於模板的程式碼生成的基本套路。
(待配圖)

 

為了協調好死程式碼與活程式碼,讓死程式碼能表達任意內容,而不會被誤認為其中有活的內容。同時模板還要直觀、易懂易用。於是形成了各種有效的固定套路,即是模板引擎。所謂模板引擎就是規定了死程式碼與活程式碼的邊界,並能將死與活組裝成目標文件(程式碼)的一套固化的方法。它通常包括兩部分:模板的語法和解析器。我知道的知名的模板引擎有 velocity,razor,T4,各種動態網頁也是模板引擎,比如ASP,JSP,PHP,ASP.NET MVC等。其中ASP.NET MVC用的是razor引擎,ASP用的是T4引擎(是吧?)。
而程式碼生成器有my generation,my generator,easy code等。

 

如今絕大部分的程式碼生成器都是基於模板的方式工作,像上面提到的三個程式碼生成器都是。以至於很多人誤以為程式碼生成必然是使用模板的。基於模板的程式碼生成器,具有簡單易上手、出成果快等優點。但要生成複雜的程式碼,困難比較大。

 

一些複雜的功能,往往需要修改引擎才能支援。更復雜的功能,則需要外建更復雜的擴充套件機制,或者是另一套引擎配合才能做到。總結,基於模板的程式碼生成,面對複雜問題時,容易遇到能力的天花板。

 

基於非模板的引擎暫時還沒有一個統一的名字。我知道的一種模式是,用特定方式表示的資料結構和流程,再加上一些預先定好的規則進行推理,最終生成程式碼。除了最終生成的程式碼是字串之外,中途都是各種各樣的資料結構,唯獨沒有模板。這種工作方式,更接近於程式設計師寫程式碼時的思考方式。

((配圖))

 

還有一種可能的形態也是用於生成複雜的程式碼。就是在基於非模板的基礎上,在區域性範圍引入模板。

展望未來

假設我們已經能夠生成get/set,已經能夠生成資料庫的增刪改查程式碼。我們還想要生成什麼?我們得換一個視角來看待軟體原始碼。一個軟體的全部原始碼,可以看作是包含了從機械式程式碼到核心業務邏輯程式碼之間的多個層次。通俗地講,機械式的程式碼是最笨的程式碼,核心業務程式碼是最聰明的程式碼。一個軟體的全部原始碼是各種不同聰明程式的程式碼的有機組合。

(待配圖)


在程式碼生成器看來,整個軟體的程式碼可以劃分為兩部分:能生成的程式碼和不能生成的程式碼。越是機械式的越容易生成,越是核心業務邏輯往往意味著程式碼的變化多端,就越難生成。而程式碼生成器自身的發展使命就是不斷的增大能生成的程式碼範圍,一點一點地把原本不能生成的程式碼,變成能生成的程式碼。最終的目標是實現100%的程式碼都可以生成,即生成一個軟體的全部原始碼,甚至包括配置檔案、部署指令碼等輔導檔案。

 

生成程式碼的複雜度,比被生成程式碼的複雜度,大約高一個數量級。而複雜的程式碼手寫已經很困難了,為什麼還要追求生成?原因就是前面提到的質量和效率。