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