為了給自己寫的C++ GUI庫做宣傳,在幾個月前我決定要給他做一個網(wǎng)站,經(jīng)歷了這幾個月不斷的重構(gòu),現(xiàn)在網(wǎng)站的架構(gòu)終于定型了。考慮到在這之前我?guī)缀鯖]有開發(fā)網(wǎng)站的經(jīng)驗(yàn),所以在這里做點(diǎn)小總結(jié)來介紹自己一路走來發(fā)生的事情。
一開始為了制作這個網(wǎng)站購買了萬網(wǎng)的域名和一個很便宜的一年500塊錢的空間。這個空間支持低版本的asp.net,不過當(dāng)時還沒學(xué)會這方面的東西。后來我就開始學(xué)習(xí)HTML和CSS,然后做出了幾個頁面。不同的瀏覽器有不同的bug,導(dǎo)致HTML和CSS搞起來相當(dāng)復(fù)雜,特別是div和float的結(jié)合,更是焦頭爛額。后來索性整個網(wǎng)頁都用表格布局。雖然表格布局并不是什么流行的做法,但是鑒于GacUI的網(wǎng)站并沒有多么復(fù)雜的內(nèi)容,因此最后這么做,避開了很多跨瀏覽器的問題。當(dāng)然以后如果網(wǎng)頁內(nèi)容變得太復(fù)雜的話總是要改回div的吧。對于常年寫圖形和編譯器方面的我來說,剛開始深入接觸HTM和CSS的時候就對他的雜亂無章所震驚。使用programming language領(lǐng)域的經(jīng)驗(yàn)和標(biāo)準(zhǔn)來看,HTML、CSS和Javascript作為編程的工具實(shí)在是爛到不能再爛了。不過事物的存在總是有其合理性的,縱觀這三樣?xùn)|西的發(fā)展和歷史,我們會發(fā)現(xiàn)其過程充滿了各種巧合,而且當(dāng)初這些東西在發(fā)明的時候就僅僅是為了解決一些簡單的問題。如今流行了,就跟COBOL、Java和C語言一樣,全世界的程序員都只能接受其不可忽視的弱點(diǎn)而就這么開發(fā)下去了。
在熟悉了簡單的HTML和CSS之后,我就開始給GacUI做網(wǎng)站了。這個網(wǎng)站的主要目的就是用來介紹GacUI的特點(diǎn)、展示一些Demo、告訴人們?nèi)绾蜗螺d并使用,最后就是提供一個在線文檔。文檔就跟MSDN一樣,當(dāng)然搜索功能還不存在。剛開始就遇到了美工問題。技能書都點(diǎn)在了系統(tǒng)軟件上,自己的美工自然是連自己都不能滿足的。后來找了幾個例子,看來看去覺得還是
http://www.codeplex.com最順眼。但是它的代碼復(fù)雜到吐血,我便只好依樣畫葫蘆,自己慢慢復(fù)刻。最后復(fù)刻的結(jié)果還是令我比較滿意的。在做完了導(dǎo)航條之后,我就發(fā)現(xiàn)了一個問題。如果不使用如今的框架來做網(wǎng)頁,而采用手寫的方法來生成HTML文件的話,勢必是無法DIY的。不過那個時候還沒有意識到這個問題的嚴(yán)重性,于是就采用了簡單粗暴的復(fù)制代碼的方法來做好那五個頁面。這也為我之后轉(zhuǎn)向Windows Azure埋下了伏筆。
之后做Demo的展示頁面比較順利。因?yàn)槟壳罢故綝emo的方法就是先貼效果圖,然后貼C++代碼,十分的簡單粗暴。于是立刻就遇到了一個新的障礙,要如何寫一個類似MSDN的HTML文檔。其實(shí)這件事情跟做網(wǎng)站本身是沒什么關(guān)系的,但是自從決定了要提供在線文檔之后,這個問題也就無法避免了。C++生成文檔地方法之前略有研究,畢竟關(guān)于這個功能的一個簡單的原型就是我跟幾個朋友在大一的時候參加學(xué)校的軟件競賽的作品。后來還考慮過諸如Doxygen這樣的工具。但是由于Doxygen生成的文檔很難調(diào)整風(fēng)格,使其整體融入我的網(wǎng)站的樣式里,因此最終就放棄了。然后我便想起了Visual Studio的XML注釋功能。在略為研究之后,我便給我的整個GacUI的類庫的public class編寫了XML注釋。當(dāng)我最終要執(zhí)行生成文檔的這一步的時候,我才發(fā)現(xiàn)所有的工具都不支持原生C++程序和XML注釋的文檔生成功能。不過想來其實(shí)也有道理。Visual Studio在編譯了XML注釋之后提供的一個xml文件只包含符號和注釋的對應(yīng)關(guān)系。至于符號究竟是什么內(nèi)容,則完全沒有。因此.net的程序是怎么生成文檔的呢?自然是利用反射了。C++的苦逼就在這里啊,除了直接寫代碼,就沒有任何方法。但是寫了這么多的XML文檔要放棄實(shí)在是太可惜了,所以我就不斷的找呀找,然后發(fā)現(xiàn)Visual Studio在安裝的時候提供了一個叫做DIA的庫,可以讓我閱讀pdb文件!
這讓我欣喜若狂啊。既然Visual C++的調(diào)試器可以通過閱讀pdb就得到了一切的信息(看那個完美的調(diào)試器界面就知道了!),那我自然也可以從pdb里面找到所有東西的。抱著這個想法,我開始研究原生C++的pdb文件的符號的語義結(jié)構(gòu),后來就把我的經(jīng)驗(yàn)寫成了這兩篇博客:
http://www.shnenglu.com/vczh/archive/2012/03/10/167538.html和
http://www.shnenglu.com/vczh/archive/2012/03/10/167539.html。雖然PDB并沒有包含模板類的直接信息,不過這暫時不成問題,因?yàn)镚acUI的大部分類也不是模板類。經(jīng)過了這些研究,我就得到了一個相當(dāng)于靜態(tài)反射的功能了。之所以說是靜態(tài),是因?yàn)槲覜]辦法跟.net程序一樣通過反射來調(diào)用函數(shù)。但是這對于生成文檔來說已經(jīng)足夠了。后來我做了一件事情,就是寫了個程序,讀pdb獲得所有的符號dump出一份xml,然后再寫一個程序把xml里面的符號和Visual Studio產(chǎn)生的那個XML總注釋文件的符號聯(lián)系起來(這個過程有點(diǎn)復(fù)雜,因?yàn)閮蛇叺谋硎痉椒ú灰粯?#8230;…),得到了一份既包含符號的完整內(nèi)容又包含對應(yīng)的注釋的這么個幾十M的XML文件。之后我設(shè)計了一個簡單的文檔格式,寫了個程序把那個幾十M的XML文件轉(zhuǎn)換成用那個簡單的文檔格式表達(dá)的文檔。之所以這樣做是考慮到將來說不定除了HTML還要生成其他格式的文檔,于是就做了那么個程序可讀的中間格式。最后一步當(dāng)然是讀這些文件產(chǎn)生HTML文件了。整個流程如下所示:
PDB(VC++編譯器提供) -> Symbols.XML (因?yàn)镈IA是一個COM組件,所以這一步我用C++寫,下面所有的步驟都用C#寫。C#用起來還是更容易啊……)
Symbols.XML + Comment.XML(VC++編譯器提供) -> FullSymbols.XML
FullSymbols.XML -> *.docitem.txt
*.docitem.txt -> *.html
經(jīng)過了這些步驟,我就得到了整整一個文件夾的一千五百多個HTML文件了。然后我把這些文件跟我的網(wǎng)站合并在一起上傳,就得到了第一個版本的GacUI網(wǎng)站了:
http://www.gaclib.net。當(dāng)然現(xiàn)在已經(jīng)看不到第一個版本的網(wǎng)站了。做完這些步驟之后,我就暫停了下來,繼續(xù)開發(fā)GacUI。一邊開發(fā)一邊產(chǎn)生Demo,添加Demo頁面,產(chǎn)生新的文檔,消滅一些沒用的函數(shù)的文檔。寫代碼的時候還比較容易,再把代碼的更改反映到這個網(wǎng)站的時候,就體現(xiàn)出了手寫純靜態(tài)網(wǎng)站的弱點(diǎn):維護(hù)起來真TMD麻煩啊!雖然上面的這些步驟已經(jīng)被我合并到了一個bat文件,每次雙擊就能自動完成,但是修改Demo頁面的時候還是人肉的。這讓我十分不爽。
一個偶然的機(jī)會,我用了信用卡注冊了一個Windows Azure的空間。這個空間其實(shí)并不powerful,只給了我相當(dāng)于六顆CPU的計算能力。不過用來做這個網(wǎng)站已經(jīng)足夠了。想到每次修改網(wǎng)站都要復(fù)制HTML代碼,修改了結(jié)構(gòu)的話還要動所有的HTML文件,煩了大概一個月之后我就下定決心要把HTML做成動態(tài)生成的。在看了Windows Azure的一些介紹之后,我覺得ASP.NET MVC3加上Windows Azure的簡單存儲功能十分適合用來作這種東西。
剛開始接觸MVC3還是讓我覺得比較困難,不過最大的困難還是在于理解router的機(jī)制那里。GacUI的網(wǎng)站內(nèi)容簡單,所以并不需要ASP.NET的其他高級技術(shù)。結(jié)果所有的困難都出現(xiàn)在router機(jī)制里面。在經(jīng)過了兩天的學(xué)習(xí)之后,我初步的掌握了它的使用方法。MVC3的router基本上就是一個pattern matching的過程,把你的url映射到一個對controller的調(diào)用上面。你不僅可以映射controller的類名和函數(shù)名,還可以從url抽取一些參數(shù)。在掌握了它的原理之后,操作router的感覺就跟寫haskell一樣,又直接又清爽。接下來就是razor模板的事情。從programming language的觀點(diǎn)上看,razor是一個設(shè)計的相當(dāng)出色地模板語言。第一個特點(diǎn)就是和宿主語言C#融合的十分緊密,第二個特點(diǎn)就是幾乎一點(diǎn)語法噪音都沒有。用過原始asp和php的人都知道代碼里面充滿了<%%>是一件十分令人討厭的事情。每一處代碼和HTML的切換都要<%%>,整個文件一眼望去就是一坨屎。razor很好地解決了這個問題。他采用了復(fù)雜的判斷方法來分辨哪些東西是C#,哪些東西是HTML。小部分C#和HTML的切換至需要一個@符號就搞定了,大部分的切換都是自動的。雖然偶爾razor會有分析錯誤的情況,但是他仍然提供了@:操作符來讓我們workaround這個分析過程。整個模板語言下來毫無語法噪音,寫起來十分直接,十分干凈。
在網(wǎng)站差不多做完之后,我往生成HTML文檔的程序添加了一個功能:生成一個包含HTML文檔內(nèi)容和元數(shù)據(jù)的XML。然后我寫了一個程序把這一大堆XML灌入了Windows Azure的Blob Storage里面。Blob Storage就跟一個硬盤一樣,可以用來存放大量的不需要計算(SQL數(shù)據(jù)庫就屬于那種需要計算的)數(shù)據(jù)。然后我給每一個文檔頁面建立了一個統(tǒng)一的Model,Model里面包含了“讀取和分析這些XML文件”的功能,controller則做一個簡單的轉(zhuǎn)發(fā),最后在model里面把所有被Model標(biāo)記出來的需要改寫的URL都用@Url.Action來處理。在這個過程中我學(xué)到了一個razor的小技巧:雖然不是很安全,但是在razor里面使用MvcHtmlString可以繞過html encoding的功能,把存儲在變量里面的HTML代碼直接嵌進(jìn)頁面。這么用的時候需要有清醒的意識。
如今GacUI終于有了鏡像網(wǎng)站:
http://asia.gaclib.net和
http://us.gaclib.net了。萬網(wǎng)的破爛空間自然不可能直接訪問Windows Azure Storage了。所以我采用了一個看起來比較傻逼的方法。首先我修改好網(wǎng)站之后,上傳到EastAsia和West US兩個服務(wù)器,然后我寫了一個程序再把每一個生成好的HTML頁面下載下來。下載的過程其實(shí)就和寫爬蟲差不多,每獲得一個新的HTML文件就去分析里面的鏈接,然后繼續(xù)下載。寫完了之后我發(fā)現(xiàn)這個小程序還有了發(fā)現(xiàn)死鏈的功能,直接找出了網(wǎng)站代碼的幾個bug。下載完之后FTP到萬網(wǎng)的空間里面。這個服務(wù)器在杭州。因此網(wǎng)站就有三個服務(wù)器了。
整個過程零零碎碎耗費(fèi)了大約半年的時間,都是利用每天下班后的時間完成的。自己又點(diǎn)了技能樹的一個新子樹,漲了點(diǎn)經(jīng)驗(yàn)值,覺得這些經(jīng)驗(yàn)對于某些人來說可能還有參考的價值,于是就寫了這篇博客,大家共勉。
posted on 2012-07-09 10:27
陳梓瀚(vczh) 閱讀(4689)
評論(9) 編輯 收藏 引用 所屬分類:
其他 、
GacUI