在我開發PenPen時,核心的繪圖部份花了二晚就完成了,然後當我寫資料庫時... 花費了意外地多的時間,有時候SQL寫錯了少許,結果到了中期才發現有bug,除錯就得用不少時間。最慘是到了後期發現資料庫設計不對,計劃的宏願過於龐大(Over design),難以在短期內完成,要把不少部份砍掉……
最終資料庫的部份佔了60%的開發時間,實在冤枉得很。
作為應用程式的開發者,又不是要處理龐大的資料,對SQL的效能要求可謂完全沒有,只想要有一個簡單而用的介面。
所以那時我就想為Qt弄一個ORM (Object Retional mapping)的library,可以用Object的方式存取SQL,不用再浪費時間在這方面。
跟著開始了ORM的研究,ORM當中我最熟識的是Django,由資料庫的定義到存取都很簡單,但C++不像Python般的scipting language那麼俱彈性,Django的方法無法直接利用,除非學Qt弄出MOC (Meta-Object Compiler)那樣的東西,不過幾經考慮後還是放棄這個方案。
之後有段時候就好像回到初學編程的時候,研究C++的各種不同寫法,有沒有什麼語法、Macro、template的應用可以做出像Django的效果呢?幾經嘗試以後,終於弄出了一個比較漂亮的方法,只靠Macro及template的混合應用就能模仿MOC的效果:
/// User account database
class User : public DQModel {
DQ_MODEL
public:
/// The user ID
DQField<QString> userId;
/// The account creation date
DQField<QDateTime> creationDate;
/// The karma of the user
DQField
};
/// Declare the model and the field clause
DQ_DECLARE_MODEL(User,
"user", // the table name.
DQ_FIELD(userId , DQNotNull | DQUnique), // The field can not be null and must be unique
DQ_FIELD(creationDate , DQDefault("CURRENT_TIMESTAMP") ), // The default value for the field is the current timestamp
DQ_FIELD(karma) // If no special requirement to the field , you don't need to pass the second argument
);
以上的宣告只要放在header檔裏便可以定議出以下的SQL table:
CREATE TABLE user (
id INTEGER PRIMARY KEY AUTOINCREMENT,
userId TEXT NOT NULL UNIQUE,
creationDate DATETIME DEFAULT CURRENT_TIMESTAMP ,
karma DOUBLE);
所以我決定開始一個叫做DQuest的計劃,並且把程式碼以New BSD license的方式放出。
計劃資料:
Project Page:
http://code.google.com/p/d-quest/
Mailing list:
http://groups.google.com/group/dquest-dev
API Document
http://d-quest.googlecode.com/svn/trunk/docs/annotated.html
沒有留言:
發佈留言