概要
ブロブ、画像、ファイルなどの「重い」プロパティを処理するためのアイデアをいくつか提案します。「すべてに1つの解決策」はないことを忘れないでください。私は個人的に「すべての重いプロパティをロードする」フラグのアイデアを拒否し、別のアイデアを提案します。
前に、続行します。小さな構文エラーまたはロジックエラーを無視し、コード例のロジックに焦点を合わせてください。
[1]例を定義する
まず、簡単な例から始めましょう。
public class EmployeeClass
{
public:
int Key;
char FirstName[150];
char LastName[150];
Image* Photo; // <- picture
Blob* Contract; // <- scanned contract
}; // class
まず第一に、「エンティティ」モデルまたは他のプログラミング手法がそう言うので、「重い」プロパティをロードする必要もロードしない必要もありません。
実際、重いオブジェクトのフラグは追加しません。これは、すべての「重い」プロパティをロードするか、「重い」プロパティをまったくロードしないことを意味するためです。また、すべてではなく、一部をロードする必要がある場合もあります。
[2]ロードプロパティ
通常、プログラムのロジックは、プロパティをいつロードするかを示します。
一般的な方法は、それぞれの場合に異なるコンストラクターを使用することです。
public class EmployeeClass
{
public:
int Key;
char FirstName[150];
char LastName[150];
Image* Photo;
Blob* Contract;
public:
// --> generic constructor
EmployeeClass()
{
Key = 0;
strcpy(FirstName, "");
strcpy(LastName, "");
Photo = null;
Contract = null;
} // EmployeeClass()
// --> "light" constructor
EmployeeClass
(
int AKey,
char* AFirstName,
char* ALastName
)
{
Key = AKey;
strcpy(FirstName, AFirstName;
strcpy(LastName, ALastName);
Photo = null;
Contract = null;
} // EmployeeClass()
// --> "heavy" constructor
EmployeeClass
(
int AKey,
char* AFirstName,
char* ALastName,
Image* APhoto,
Blob* AContract
)
{
Key = AKey;
strcpy(FirstName, AFirstName;
strcpy(LastName, ALastName);
Photo = APhoto;
Contract = AContract;
} // EmployeeClass()
void Insert();
}; // class
void Test()
{
...
int AKey = 0;
char AFirstName[150];
char ALastName[150];
Image* APhoto = null;
Blob* AContract = null;
// --> calling "light" constructor
AKey = 1;
strcpy(AFirstName, "Mary");
strcpy(ALastName, "Thompson");
EmployeeClass* AEmployee = new EmployeeClass
(AKey, AFirstName, ALastName);
AEmployee->Insert();
// --> calling "heavy" constructor
AKey = 2;
strcpy(AFirstName, "John");
strcpy(ALastName, "Doe");
Image* APhoto = LoadPhoto();
Blob* AContract = LoadContract();
EmployeeClass* AEmployee = new EmployeeClass
(AKey, AFirstName, ALastName, APhoto, AContract);
AEmployee->Insert();
// --> calling "dummy" constructor,
// --> more work, but, more flexible
AKey = 1;
strcpy(AFirstName, "Mary");
strcpy(ALastName, "Thompson");
EmployeeClass* AEmployee = new EmployeeClass();
AEmployee->Key = AKey;
strcpy(AEmployee->FirstName, AFirstName);
strcpy(AEmployee->LastName, ALastName);
AEmployee->Photo = LoadPhoto();
AEmployee->Contract = LoadContract();
AEmployee->Insert();
...
} // void Test()
多くの開発者は「一般的なライトコンストラクター」のみを使用し、複数のコンストラクターを持つという考えを拒否します。
[3]追加のヘルプ
しばらくスキップしましょう。「重い」プロパティは後で続行されます。
これは、多くのC / C ++開発者が気に入らないことを示唆していますが、私は個人的に、エンティティオブジェクトを処理するときに非常に役立ちます。「2段階初期化」を使用しています。
エンティティクラスごとに、フィールドをクリアするパラメーターを指定せずにコンストラクターを宣言し、さらに、コンストラクターの役割を果たす非常に具体的な識別子を持つ仮想メソッドを追加します。
次に、「重い」プロパティをロードするかどうかを決定するなど、コンストラクターとして機能するいくつかの仮想メソッドを追加する場合があります。
したがって、前の例は次のようになります。
public class EmployeeClass
{
public:
bool F_EmployeeClass_IsReady;
public:
int Key;
char FirstName[150];
char LastName[150];
Image* Photo;
Blob* Contract;
public:
// --> only generic constructor
Employee()
{
F_EmployeeClass_IsReady = false;
Key = 0;
strcpy(FirstName, "");
strcpy(LastName, "");
Photo = null;
Contract = null;
} // EmployeeClass()
virtual bool IsReady()
{
return F_EmployeeClass_IsReady;
} // bool IsReady(...)
// --> works like "generic" constructor from previous example
virtual void Create()
{
Key = 0;
strcpy(FirstName, "");
strcpy(LastName, "");
Photo = null;
Contract = null;
F_EmployeeClass_IsReady = true;
} // void Create()
// --> works like "light" constructor from previous example
virtual void CreateLight
(
int AKey,
char* AFirstName,
char* ALastName
)
{
Key = AKey;
strcpy(FirstName, AFirstName);
strcpy(LastName, ALastName);
Photo = null;
Contract = null;
F_EmployeeClass_IsReady = true;
} // void CreateLight()
virtual void Destroy()
{
F_EmployeeClass_IsReady = false;
} // void Destroy()
// --> works like "heavy" constructor from previous example
virtual void CreateHeavy
(
int AKey,
char* AFirstName,
char* ALastName,
Image* APhoto,
Blob* AContract
)
{
Key = AKey;
strcpy(FirstName, AFirstName);
strcpy(LastName, ALastName);
Photo = APhoto;
Contract = AContract;
F_EmployeeClass_IsReady = true;
} // void CreateHeavy()
void Insert();
}; // class
void Test()
{
...
int AKey = 0;
char AFirstName[150];
char ALastName[150];
Image* APhoto = null;
Blob* AContract = null;
// --> calling "light" constructor
AKey = 1;
strcpy(AFirstName, "Mary");
strcpy(ALastName, "Thompson");
EmployeeClass* AEmployee = new EmployeeClass();
AEmployee->CreateLight(AKey, AFirstName, ALastName);
AEmployee->Insert();
AEmployee->Destroy();
delete AEmployee;
// --> calling "heavy" constructor
AKey = 2;
strcpy(AFirstName, "John");
strcpy(ALastName, "Doe");
Image* APhoto = LoadPhoto();
Blob* AContract = LoadContract();
EmployeeClass* AEmployee = new EmployeeClass();
AEmployee->CreateHeavy
(AKey, AFirstName, ALastName, APhoto, AContract);
AEmployee->Insert();
AEmployee->Destroy();
delete AEmployee;
// --> calling "dummy" constructor,
// --> more work, but, more flexible
AKey = 1;
strcpy(AFirstName, "Mary");
strcpy(ALastName, "Thompson");
EmployeeClass* AEmployee = new EmployeeClass();
AEmployee->Create();
AEmployee->Key = AKey;
strcpy(AEmployee->FirstName, AFirstName);
strcpy(AEmployee->LastName, ALastName);
AEmployee->Photo = LoadPhoto();
AEmployee->Contract = LoadContract();
AEmployee->Insert();
AEmployee->Destroy();
delete AEmployee;
...
} // void Test()
前の例では、各エンティティは2つのステップ、「ダミー」コンストラクター、およびエンティティオブジェクトの準備方法を選択するときに役立つ、意味のある識別子を持つ、ケースごとに異なる補完的なメソッドを使用して作成されます。
各オブジェクトの破壊についても同じことが言えます。
[4]ヘビープロパティメソッド
最後に、必要に応じて「重い」プロパティのロードを担当するメソッドを追加することもできます。明示的に呼び出されることもあれば、自動的に呼び出されることもあります。
public class EmployeeClass
{
public:
bool F_EmployeeClass_IsReady;
public:
int Key;
char FirstName[150];
char LastName[150];
Image* Photo;
Blob* Contract;
public:
// --> only generic constructor
Employee()
{
F_EmployeeClass_IsReady = false;
Key = 0;
strcpy(FirstName, "");
strcpy(LastName, "");
Photo = null;
Contract = null;
} // EmployeeClass()
virtual bool IsReady()
{
return F_EmployeeClass_IsReady;
} // bool IsReady(...)
void LoadPhoto();
void SavePhoto();
void LoadContract();
void SaveContract();
// --> works like "generic" constructor from previous example
virtual void Create()
{
Key = 0;
strcpy(FirstName, "");
strcpy(LastName, "");
Photo = null;
Contract = null;
F_EmployeeClass_IsReady = true;
} // void Create()
// --> works like "light" constructor from previous example
virtual void CreateLight
(
int AKey,
char* AFirstName,
char* ALastName
)
{
Key = AKey;
strcpy(FirstName, AFirstName);
strcpy(LastName, ALastName);
Photo = null;
Contract = null;
F_EmployeeClass_IsReady = true;
} // void CreateLight()
virtual void Destroy()
{
F_EmployeeClass_IsReady = false;
} // void Destroy()
// --> works like "heavy" constructor from previous example
virtual void CreateHeavy
(
int AKey,
char* AFirstName,
char* ALastName,
Image* APhoto,
Blob* AContract
)
{
Key = AKey;
strcpy(FirstName, AFirstName);
strcpy(LastName, ALastName);
Photo = APhoto;
Contract = AContract;
F_EmployeeClass_IsReady = true;
} // void CreateHeavy()
// --> works like "heavy" constructor from previous example
virtual void CreateAndLoad
(
int AKey,
char* AFirstName,
char* ALastName
)
{
Key = AKey;
strcpy(FirstName, AFirstName);
strcpy(LastName, ALastName);
LoadPhoto();
LoadContract;
F_EmployeeClass_IsReady = true;
} // void CreateAndLoad()
void Insert();
}; // class
void Test()
{
...
int AKey = 0;
char AFirstName[150];
char ALastName[150];
Image* APhoto = null;
Blob* AContract = null;
// --> calling "load" constructor
AKey = 1;
strcpy(AFirstName, "Mary");
strcpy(ALastName, "Thompson");
EmployeeClass* AEmployee = new EmployeeClass();
AEmployee->CreateLoad(AKey, AFirstName, ALastName);
AEmployee->Insert();
AEmployee->Destroy();
delete AEmployee;
...
} // void Test()
追加のメソッドを使用すると、それらを無視する[fake]コンストラクターがあり、それらを呼び出す[fake]コンストラクターである「heavy」プロパティをロードしない場合があります。または、それらを使用しない[fake]コンストラクターを使用し、特定の「重い」プロパティに対してローダーを明示的に呼び出します。
これらは、ファイルシステムパスから画像をロードしてデータベースフィールドに保存する場合、またはその逆の場合に、データベースフィールドからファイルをロードしてファイルシステムパスに保存する場合にも役立ちます。
乾杯。