2008年6月25日 星期三

測試驅動開發

有一種關於開發方法的觀念,叫做「測試驅動開發」。意思是先寫下用來測試物件或程式功能的程式碼,然後再以「通過測試」為目標,開發物件或是程式功能。

不過我並沒有老老實實的用這個方法。

開發遊戲引擎的同時,我建立了一個專職拿來測試用的專案,隨時將需要測試的重要功能,寫一個小程式進行測試。算是做單元測試,也算是一種「測試驅動開發」的方法。

舉例來說,建立遊戲引擎所需要的數學函式庫之後,可以先寫一個測試程式來檢驗這個函式庫裡面的運算是否正確,而這個測試程式是要保留下來的,當做是整個開發專案的一部份。

保留下來有幾個作用。

第一,可以當作程式庫的應用範例程式。也許對於數學函式庫來說,不太需要這樣的應用範例,但是對於遊戲引擎的其他系統而言,這會是一個很好的範例程式。

第二,當我們對程式庫進行程式碼的修改之後,我們只需要將這個測試程式再跑個幾遍,就可以知道我們是不是已經將程式庫改壞掉了....這個很重要,因為一旦程式越來越龐大,那麼程式越改Bug越多的狀況就會常常出現......

用正確的測試方式也很重要。例如說,要測試數學函式庫裡的反矩陣運算是否正確,可以將矩陣與它的反矩陣相乘,所得的結果必須為單位矩陣,如果不是,那麼這個反矩陣運算就有問題。不需要把另外的演算法寫在測試程式中進行測試,一來我們未必能找到其他的演算法,二來,誰知道這另一個演算法有沒有寫錯咧?

這種開發的觀念很有用,也很實在。隨著開發的內容越來越多,範例測試程式也會跟著越來越多,因為有測試程式隨時可以檢查,開發的內容可以一直保持著好的程式穩定性,不至於出什麼太大的狀況。

2008年6月24日 星期二

寫不完的遊戲引擎設計

遊戲引擎設計是一個很大的主題,所以絕對會寫不完,而且也不知道能寫多久。想寫這個,其實是為了讓我自己留下一點記錄,也許哪一天可以當作設計文件來用也說不定。

寫下來的內容,應該會很雜很亂,覺得什麼是該記錄的,就會把什麼寫下來。不過,這麼沒系統的做法,好像不是一個程式人所該有的.....

且不管它,哪一天內容豐富到了可以做系統化整理的時候再來考慮這件事吧......

在寫這一系列之前,先列出兩本書。作者是同一個人。

3D Game Engine Design, Second Edition: A Practical Approach to Real-Time Computer Graphics (The Morgan Kaufmann Series in Interactive 3D Technology) (Hardcover)
by David H. Eberly (Author)

http://www.amazon.com/Game-Engine-Design-Second-Interactive/dp/0122290631/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1206069057&sr=1-1

3D Game Engine Architecture: Engineering Real-Time Applications with Wild Magic (The Morgan Kaufmann Series in Interactive 3D Technology) (Hardcover)
by David H. Eberly (Author)

http://www.amazon.com/Game-Engine-Architecture-Engineering-Applications/dp/012229064X/ref=pd_bbs_sr_3?ie=UTF8&s=books&qid=1206069057&sr=1-3

一本講的是設計,一本講的是架構。因為是同一個人寫的,而設計與架構又彼此關聯很深,所以兩本書的內容就有不少的重複。我比較推薦的是關於架構的第二本,因為書裡面不但說明如何去設計所要的架構,還解釋了為何要做如此設計。等於是作者把他的思路告訴了我們,我們可以順著他的思路去了解他的設計,甚至於修改成適合我們的設計。這就已經不只是Copy,而是進階到Steal的境界了。(啊....又回到了那句話...)


2008年6月21日 星期六

設計模式的二三事

這是在Wiki中有關Bridge Pattern所舉出的物件架構範例。
這個架構沒有什麼問題,問題在應用的範例上。
int main(void) {
DrawingAPI1 dap1;
DrawingAPI2 dap2;
CircleShape circle1(1,2,3,&dap1);
CircleShape circle2(5,7,11,&dap2);
circle1.resizeByPercentage(2.5);
circle2.resizeByPercentage(2.5);
circle1.draw();
circle2.draw();
return 0;
}這個範例,用了Bridge的架構,但卻沒有將Bridge的精神發揮出來。
這裡面有兩個circle,用不同的drawing api,這樣的需求,我們可以用更簡單的物件結構來做。
但是這麼一來,就跟Bridge Pattern無關了。
這讓我想到最近在書上讀到的一個觀念--不要為了使用Pattern而使用Pattern。要用Pattern來簡化設計,而不是讓Pattern把設計搞得更複雜。
好,所以說,這個範例應該改成這樣...
CircleShape1與TriangleShape1使用同樣的DrawingAPI1,CircleShape2與TriangleShape2則使用DrawingAPI2,這時候,Bridge Pattern就能夠將四種物件的關係簡化,變成這樣:
這個架構,跟原來的並沒有多大不同,但是能夠表達出Bridge的精神所在。

2008年6月19日 星期四

"Good artists copy, great artists steal."

前一陣子電視上演了一部電影--微軟英雄。講的是Apple的兩個史蒂夫跟微軟的比爾蓋茲兩組人的創業傳奇。也許是編劇有心的安排,史蒂夫到「全錄」去偷圖形化操作介面以及比爾到Apple再去偷過來的時候,說的是同一句話:
"Good artists copy, great artists steal."
差別在,比較懂藝術的史蒂夫賈伯知道這是畢卡索說的(誰知道真的假的?),比爾蓋茲就遜了點,"好像是梵古說的吧!"
我說,這句話指的就是這兩夥人。

這句話也很好用,你可以把artists改為各式各樣的身份跟職業,一樣適用。
"Good programmers copy, great programmers steal."
我說的。