carchive的版本控制功能
1 引言
visual c++ 6.0語言開發環境在mfc中以carchive類為中心提供輸入輸出的序列化和資料版本控制功能。一般來說,隨著軟體的公升級,對應的輸入輸出也會發生改變,如何保證多個版本的軟體與多種輸入輸出資料之間的親和性成為問題。比如說,當使用者使用1.0版的軟體,而提供的輸入卻是2.0版軟體的輸出,結果會如何呢?同樣2.0版的軟體如何處理1.0版生成的資料呢?
的確,使用者可以定義一套自己的檔案格式為上述因版本不同造成的造成的麻煩提供解決方案,許多軟體都是這麼幹,但如果你所編制的軟體規模很小,功能單一,對資料格式並不在意(當然要保證輸入輸出正確),那麼花力氣指定自己的資料檔案格式似乎過於繁瑣。使用carchive可以簡化這類軟體的編制。
2 carchive
的版本控制方式
當你使用declare_serial和implement_serail巨集時,你就在你的類中宣告並定義了乙個cruntimeclass類的靜態結構成員,該結構中的m_wschema可以記錄你指定的版本號。注意雖然按照命名約定m_wschema似乎是個word,但實際它是個uint。當序列化輸出時,類資訊(即類名和版本號的低字,高字是標誌)被寫入資料檔案,而序列化輸入時carchive::readclass()和carchive::readobject()根據這些資訊以及後面的物件資料重建物件,返回物件指標。這一切均在類似pobject<
雖然這一切工作的很好,但問題並非象看上那麼簡單,因為你的軟體在不同版本中會有改動。由於carchive::readclass()是根據類名來獲取cruntimeclass類成員的,而carchive::readobject()又是根據carchive::readclass()返回的cruntimeclass類成員物件來建立序列類物件的(cruntimeclass成員是序列類的靜態成員)。因此,如果新的軟體中根本沒有對應的序列類,那麼必然失敗!
3 類的改動對版本控制的影響
版本公升級需要擴充套件或改變類的介面,從序列類的定義來看,有多種方式類中擴充套件新的功能:
(1). 修改原先的類定義,同時改變類名
這時實際上原先的類已經不存在,那麼carchive無法根據資料檔案建立對應的物件,因此新版本與舊版本之間完全無法相容,如同兩個完全無關的軟體。不僅舊軟體無法識別並處理新軟體的資料檔案,新軟體同樣無法識別並處理舊軟體的資料檔案。你需要自己識別處理資料檔案的轉換,mfc無法識別處理。
(2). 修改原先的類定義,但類名保留
此時,carchive可以根據舊的資料檔案建立物件,但在新版本序列類的carchive::serailize()需要根據版本好做不同的輸入輸出處理。由於類定義已經改變,對舊資料的處理可能同舊版本處理方法上有差異,需要小心從事。而舊版本可以識別出新版本,但一般無法處理。
(3). 從原先的類派生新類支援擴充套件功能
這種方式充分利用了c++語言的特性,新版本可以根據版本號對不同版本資料檔案進行處理,並且依然可以生成舊版本的資料檔案,相容性非常好。但舊版本無法識別出新版的資料檔案,更談不上處理了。
比較看來,方式(1)比較粗暴,完全不考慮軟體公升級的相容性問題,方式(2)和(3)均考慮到了相容問題,但方式(2)的程式設計複雜,序列類要針對版本號編制處理**,而方式(3)利用c++語言的特性比較好處理多版本資料問題,只要注意虛函式就可以了。但如果軟體公升級次數很多,從1.0不停地公升到8.0,那麼顯然有點不舒服。另外乙個重要的不足是舊版本無法識別新版本的資料檔案,只能提示資料檔案格式不對。
4 例子
下面的例子是公升級後的**,採用方式(3)處理不同版本問題:
// 注意:雖然使用某些
mfc的**,但為了簡單沒有使用
// 嚮導生成的初始化**,因此對
mfc的支援是不全的!
// 宣告物件的標頭檔案
#ifndef __lcg_object_h__
#define __lcg_object_h__
#include
// 版本
1.0採用的物件
class cobject1 : public cobject ;
// 版本
(2)擴充套件了版本
1.0的類
class cobject2 : public cobject1 ;
#endif
// 物件的.cpp
檔案#include "object.h"
implement_serial( cobject1, cobject, (versionable_schema|1) )
cobject1::cobject1()
// 1.0
版的版本檢查函式,版本檢查函式要宣告為虛擬的,
// 這樣實際的物件才可能進行正確的檢查,否則,即使物件正確,
// 但由於呼叫指標是基類的指標,檢查結果不正確!
bool cobject1::isokver( uint nver )
void cobject1::serialize( carchive& ar )
else
int nlen; ar>>nlen;
ar.read( m_str.getbuffer(nlen), nlen ); }
} // 2.0
版的物件
implement_serial(cobject2,cobject1, (versionable_schema|2))
cobject2::cobject2()
void cobject2::serialize( carchive& ar )
else
int nlen; ar>>nlen;
ar.read( m_str2.getbuffer(nlen), nlen ); }
} bool cobject2::isokver( uint nver )
// 主程式,對不同版本使用不同的物件
#include
#include"object.h"
#pragma comment( lib, "msvcrt.lib" )
int winapi winmain( hinstance hinst, hinstance hnull,
lpstr lpcmdline, int ncmdshow )
catch( carchiveexception, pe )
end_catch
if( berror )
return 0;
// 根據不同的版本呼叫不同的類
switch((pb->getruntimeclass()->m_wschema)&
~(versionable_schema) )
delete pb;
return 0; }
5. 結束語上述思路和例子是一般軟體版本控制的乙個簡單的模擬,實際中要複雜的多,甚至需要為版本控制生成專用資料,但對於那些需要快速開發的小規模的軟體,上述方法可以作為一種選擇。
參考文獻
1 visual c++ 6.0 msdn
2 visual c++ 6.0 mfc原始碼
CArchive的版本控制功能
1 引言 visual c 6.0語言開發環境在mfc中以carchive類為中心提供輸入輸出的序列化和資料版本控制功能。一般來說,隨著軟體的公升級,對應的輸入輸出也會發生改變,如何保證多個版本的軟體與多種輸入輸出資料之間的親和性成為問題。比如說,當使用者使用1.0版的軟體,而提供的輸入卻是2.0版...
版本控制 設計模式 模式版本控制
版本控制 設計模式 schema versioning changing a namespace is not versioning,it is new type creation.meta douglasp 架構版本控制 更改命名空間不是版本控制,而是建立新型別。meta douglasp ok....
版本控制的簡介
cvs採用客戶端 伺服器架構設計,版本庫位於伺服器端,實際上就是乙個rcs檔案容器。每乙個rcs檔案以 v 作為檔名字尾,用於儲存對應檔案的歷次更改歷史。rcs檔案中只保留乙個版本的完全拷貝,其他歷次更改僅將差異儲存其中,使得儲存變得更加高效。圖1 1展示了cvs版本控制系統的工作原理,可以看到作為...