沒頭沒尾--專案開發筆記:工具能生成多少程式碼!? (轉)

amyz發表於2007-10-17
沒頭沒尾--專案開發筆記:工具能生成多少程式碼!? (轉)[@more@]

標題:沒頭沒尾--專案開發筆記:工具能生成多少程式碼!?

關鍵詞:分散式開發 專案分工 與C#的混合開發 程式碼生成工具 掃描

12月2號:開始寫程式碼生成工具了,真有點千頭萬緒不知從何說起……

 :namespace prefix = o ns = "urn:schemas--com::office" />

程式碼工具包括程式碼的生成工具以及程式碼同步工具兩種型別的工具。當然,可以將程式碼的生成與同步寫在同一個工程專案中。如果有充分時間進行考慮的話,那麼我們的程式碼工具也的確是應該包含在一個工程中。但事實上由於時間與的關係,我沒有做到把這兩種東東放在一個工程中,而是分別的做出幾個不同的程式碼生成工具與程式碼同步工具。為了說明的方便,下面的討論都只是針對程式碼生成工具。(程式碼同步在一開始我考慮的比較少,所以後來出現了一些小問題,這個在下面會有描述。)

還有一點要強調的是,下面有很多的想法是在專案開發過程之中,或者已經開發完成之後才想出來的,所以有很多是隻有想法,而沒有具體的實現J。

開始之前一定要介紹一本書,書名:《 企業應用高階》(清華大學出版社),這本書中講述了一個程式碼生成工具的簡單例子。這個簡單的例子核心的東東包括兩塊:一塊是對資料庫進行掃描,將資料庫的結構取出放入中的一個樹形的結構;另一塊是程式碼的生成與同步。不過這本書的程式碼生成與同步是運用Vs.net本身包含的Code 。所以最後生成出來的程式碼是隻能在VS.net的環境中進行使用(只能生成C#或的程式碼)。而本專案的要求是要使用程式碼生成工具生成很多種型別的檔案,於是我們只是參考了這本書的思路,如果有朋友們是完成使用Vs.net開發解決方案的話,是可以完全的參考此書。

 

程式碼生成工具這種東東在我們的專案之中應用的非常廣泛。舉幾個例子來說吧

1.  對應資料庫表以及過程的資料程式碼的生成;

2.  對應資料庫表以及儲存過程的從service到DataAccess所有檔案;

3.  對應生成所有資料庫表的快取檔案程式碼,以及快取機制中的程式碼;

4.  透過伺服器端C#生成的XSD檔案自動生成客戶端Delphi可以用的ClientDataSet程式碼(專案組中Delphi的牛人制作);

5.  掃描資料庫生成資料庫表的基礎儲存過程;

6.  ………………

由於我們做出的程式碼生成工具本身都是一些比較零散的,所以我們都沒有對他們進行總結,呵呵,每次我想去總結的時候總是給自己找到一個藉口:總不能把程式碼生成工具做的比程式還有複雜吧,那要程式碼生成工具幹嘛?所以上面寫的那些類都還是單獨的零零碎碎的工具。真是有點無從說起的感覺。

 

下面主要從程式碼生成工具的簡述,程式碼生成工具開發後的一些感想,以及程式碼生成工具帶來的開發過程的一些變化三個方面來描述。

程式碼生成工具簡述

這樣吧,我先從程式碼輸入、生成、輸出三個方面講講我理解的寫程式碼生成工具的原則(如果這些可以叫原則的話)。

 

l  輸入

如何找出輸入是程式碼生成工具的核心。我覺得這個部分是很能體現出開發人員的想像力。(有點自賣自誇。)我覺得理論上如果你可以把你的需求完成與直接的變成程式碼生成工具的輸入,那麼其它的開發人員就可以什麼都不用幹了J。你可以嗎?目前當然是不行。但是我們可以儘可能的找出多種方式的輸入,多種型別的輸入,以使我們的程式碼生成工具生成更加靠近最後實現程式的程式碼。

由於我們的層次分的很多,那麼也就存在如何組織每一層程式碼的問題。我不清楚其它朋友們對分層次的結構中程式碼的組織定義出什麼樣的規則。我對這事是簡單的定義出三種型別的程式碼組織方式;DO層可以按照資料庫表與資料庫儲存過程對應的結構來組織程式碼;在BusinessRules層可以按業務設計中的來組織;而facade,webservice與UI層當然是要按面向的模組來進行組織。針對上面三種程式碼組織方式,都可以透過程式碼生成工具至少生成基礎的檔案,以及檔案的組織形式。但是各種情況的輸入方式是不一樣的,下面分別進行說明。

n  面向使用者的介面

介面的程式碼組織情況是需要按照互動設計的具體情況來進行組織。比如中可以按照總公司模組,分公司模組等等方式來進行介面程式碼檔案的組織。在這種情況下,如果要生成面向使用者介面的程式碼框架,除了首先要統一的製作出各個介面的模板之外,還必須要有一個面向使用者介面的程式碼組織形式的描述。我們在這裡本來是希望使用一個檔案描述這個組織形式,然後透過VBA將內容讀出,生成程式碼,不過後來由於時間的關係,並沒有真正這樣進行:(;這個原理應該是與ROSE中生成程式碼的原理基本相同的。

對應生成的是本系統中的UI,Web Service層的程式碼。

n  物件導向的業務

物件導向的業務組織形式不用多說的。本身我們的系統設計上做的粒度非常的粗,所以從物件上我們也只是分成了一些大的物件,比如機構,商品,單據。沒有具體的進行細分。也就存在著按這種分類方式來組織我們的程式碼。同樣由於時間的關係,這一部分我們暫時也沒有

層與Business Rules層的程式碼。

n  面向關係的資料庫

寫到這裡真的是有一點慚愧,上面基本上都是光說不練的。有的部分我也只是寫了一些從excel檔案中讀取一些資料的類而已,這些也就不多說了。也許會在專案的中後期去實現的,讓以後的專案筆記中去記錄吧。

資料庫關聯的程式碼生成是我們已經完成了,我做的工具是根據負責資料庫層開發的同仁已經對應資料庫的表結構生成了Common Data與DataAccess.Base中的程式碼之後(這兩層的程式碼是透過拖拽方式來生成。生成之初是與資料庫中的表進行了一次組織,對簡單的程式碼表,表與操作類是一一對應的關係,對於主子表,是放在一個操作類來進行處理的。)我根據他的程式碼以及程式碼的結構生成對應的DataAccess.Template與DataAccess層的程式碼。其中生成的DataAccess.Template中的程式碼類是繼承DataAccess.Base中對應父類的一個子類。主要的作用是針對不同種操作類生成的一些固定的方法(對簡單表的All, Insert, Updata, Delete方法,單據表的單號生成等等),同時生成了繼承DataAccess.Template的DataAccess層的所有程式碼。

生成的過程中需求對資料庫進行掃描來得到對應的Key column,各個Column的名字,可以採用的系統檢視來得到資料庫的結構。比如:information_schema.tables、information_schema.columns等等,可以參考上面提到的書。

實際上,在做上面的過程之前,我還並沒有意識程式碼的組織形式可以是面向使用者,物件導向,關聯式資料庫等三種組織形式。我只是最簡單的認為只要提供出資料庫表以及儲存過程對應可以呼叫的方式,就可以在這個基礎上完成所有的介面程式碼編寫所需要的支援(如果對我定義的開發過程不瞭解可以參考以前的專案筆記)。這一部分工作實際上是先於開發編碼過程的。按照我對開發過程的規劃,我希望是在編碼的第二步中讓開發人員使用生成的程式碼來完成介面層與資料庫的連線。想透過生成的程式碼實現對介面程式設計的伺服器端的支援。於是我對應生成不只是Do層的程式碼,而且將Business Rules層、Facade層、Web Service層的程式碼按關聯式資料庫組織形式進行了一次組織。

對應生成的是本系統中的Data Access層與Data Access. Template層的程式碼。

 

上面說的這三類我想主要描述的是,開發過程的開始階段,專案中已經設計或已經實現的部分是如何一一對應到編碼的過程中。比如面向使用者的介面互動設計完成之後,會按什麼樣的方式組織客戶端的編碼過程;又比如資料庫結構已經基本定下來了以後,如何去的生成伺服器端的可視的資料庫的編碼(雖然這個編碼在後面給我們帶來麻煩,不過專案一開始的時候對開發人員理解專案還是有很多好處的。)

 

還有就是,我對程式碼組織形式的分法也希望與朋友們進行討論。不知道朋友們對自已定義出的工程是如何組織管理的?!

 

l  生成方法

程式碼的生成方法我們主要有三種:

n  字元寫入法

這種方法是我在一開始做的程式碼生成工具的時候採用的方式。可以說是一種比較笨的方法。這種方法就是把大量的要輸出的檔案中固定的字元當成字串寫在程式中。把上面提到的輸入夾在中間,形成個性化的程式碼。比如以下程式碼是生成DataAccess.Template檔案的一段程式碼:

 

String szTemp = String.Empty;

szTemp += “using System;nn”;

szTemp += “namespace XXX.Develop.Builder.ProjectBuildern”;

szTemp += “{n”;

szTemp += “  public class ” + szTableName + “Templaten ”

//生成的DataAccess.Template類統一以CommonData的名稱加上Template作為結尾

………………

 

可以看出,使用這種方式生成程式碼的話,最有可能出現的問題就是如果你的生成規則有變化,那麼你要重新去修改你的程式碼生成工具的源程式。這樣非常的麻煩……

n  字元代替法

這是我目前使用的方法。這個方法是將相對於輸入是有規則的程式碼檔案生成模板檔案。這樣模板檔案生成之後,程式碼生成工具將會在的過程中使用輸入來替換模板中對應的特殊符號塊。下面同樣以生成上面的程式碼為例:

首先是生成程式碼模板檔案:

 

using System;

namespace XXX.Develop.FrameworkBuilder.ProjectBuilder

{

  public class //?? CommonData ??//Template

  {………………

然後針對每一個CommonData中有的類,取出類名,替換上面的特殊符號塊//?? CommonData ??//,這樣同樣可以生成與字元寫入法相同的程式碼。

同樣可以使用這種方式來修改Vs.net中的工程檔案。比如下面是對應StaticData層的工程檔案StaticData.csproj中的模板中的一段程式碼:

 

 

<!-- StaticDataList --&gt

<!-- //??

 

  RelPath = "//?? CommonData ??//StaticData.cs"

  SubType = "Code"

  BuildAction = "Compile"

  />

//?? --&gt

<!-- EndStaticDataList --&gt

 

 

 ………………

(注:其中“<!-- StaticDataList --&gt”是迴圈生成的開頭特殊符號,“<!-- EndStaticDataList --&gt”是迴圈生成的結束特殊符號,“<!-- //??”是迴圈中每一項要生成的開始特殊符號,“//?? --&gt”是迴圈中每一項要生成的結束特殊符號。中間的

這樣的話可以在重新生成程式碼時同時工程檔案(不過這樣可能會與Safe配合使用時需要注意Check的問題)

n  Code DOM

Code DOM是VS.net中提供的程式碼生成工具,上面推薦的書中使用了這個進行程式碼生成。Code DOM對C#與VB.net的程式碼生成支援的很好,不過似乎沒有看見可以使用Code DOM來對工程檔案進行修改,而且也不支援生成Delphi的程式碼。所以本專案沒有采用這種方式。

l  輸出

輸出的應該是寫程式碼的人員可以“利用”的程式碼。“利用”的意思是就是應該是可以在生成的程式碼的基礎上進行不同層次的跳躍開發,以及可以對生成的程式碼進行修改。對於輸出的我想說的只有,如果你在開始去製作一個程式碼生成工具的時候,最好在設計的時候就把程式碼的生成與程式碼的同步,維護放在一起進行考慮。(本專案實際上並沒有做到這一點,所以後來對生成的程式碼的維護比較頭痛。)

一些感想

製作程式碼生成工具的時候,我一直有一些想法,雖然這個想法現在還很不成熟,但是我還是想先說出來與朋友們討論一下。

一直以來,我所呆過的幾家公司都有這樣的問題,那就是如何共享開發人員的經驗,專案得來的經驗。我記得在以前的專案筆記中我提到過,如何去把專案的經驗留下來?如何使得專案的經驗成為公司的財產,而不是個人的財產?對於這個問題,我以前的想法非常的簡單,就是專案文件化,加強專案文件痕跡管理。可是這樣又會直接的出現一個問題,就算我完成一個專案留下10000篇的專案文件,可是當下一個專案來臨的時候,誰又有時間去仔細的體會你的10000篇文件?我也和一個以前是國企的朋友聊過專案經驗的儲存問題。他告訴我,從他的經驗看專案經驗在國企的儲存與傳遞的方法就是“帶徒弟”。老師付透過帶徒弟把經驗一代一代的傳下去。可是在新技術發展的今天,專案經驗的保持還只是靠這種方式來做的話,就已經跟不上時代了。

我的想法是,程式碼生成這種形式其實可以很好的應用到儲存專案經驗中。上面已經寫了,我們的工程生成的程式碼與具體的開發語言是沒有什麼關係的。並且一但定義好了那些用來替換的特殊符號,以及真正去想清楚你的輸入可能會有什麼情況。一個富於經驗的人來寫出模板檔案,此模板檔案,或者說此模板工程(模板檔案的組合)將會作為經驗的延繼。新的專案中可以透過修改以前專案的模板檔案來生成新模目的所有支援檔案,開發人員可以將精力更多的集中到業務中。如果這種方法可以的話,那麼會不會還有類似這樣的輔助過程來修改開發過程,實現對專案小組中全部人員的提高?(這還只是一個想法,希望與朋友們討論)

 

對開發過程的改造

使用程式碼生成工具的好處我想在這裡我也不多說了,不外乎提高開發之類的說法。這裡我想強調的一點是在我們使用程式碼生成工具之後(實際上我最多的情況還是與資料庫的開發人員一起來用程式碼生成工具)。我們對於程式碼的規範性,命名的規範性其實提高了一個新的層次。以前你的檔名,資料庫表,儲存過程名稱都可以在規則許可的條件下自由的命名,但是這一次的檔案命名,以及其中資料庫建立的表結構將會直接與你是否好使用程式碼生成工具生成程式碼有關。也就是實際上進一步的加強了對資料庫,編碼規則的控制(要不能用生成工具生成程式碼的話,資料庫負責的哥們就要自已手工寫很多的程式。)

例如:由於我們對主表與明細表的關聯是放在一個CommonData中,那麼我們定義出必須將明細單的名字取成“主表名+Detail”,這樣的話,生成程式碼時可以少判斷一些條件。類似這樣的規則的強化還有。

 

程式碼生成工具的三個部分就先寫到這裡,如果下面有時間的話,我會具體的寫一寫與資料庫聯絡部分的程式碼生成工具的具體過程。

(哈,專案中的負責資料庫的同仁也開始做出一個小的生成工具來生成比較統一的儲存過程程式碼,加一條記錄,刪除記錄,還有分段取資料,呵呵,專案中的同仁這麼幹我覺得真的很開心。)

 

(這幾天專案中已經陸陸續續的出現我們使用分層開發方式的一些問題與優勢。不過還沒有來的及進行總結。有時間的話再寫出來吧。)

 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752019/viewspace-977185/,如需轉載,請註明出處,否則將追究法律責任。

相關文章