C ++ Object Design Challenge: Create Objects Efficiently and Safely and Save / Load with Database
my english is not good enough to explain my problem. But I will try my best.
I was a Java programmer but have been using C ++ for over a year. I am always worried about the strategy of creating business objects from the network (for example via SNMP, web service or other data sources ...) and storing it in a database and loading it when the application starts. Usually my design looks like this:
class Object{
/* this is just a demonstration, in real code, there are all kinds of Object and has relationships*/
friend class DBConnection;
friend class SNMPConn
private:
std::string& m_strName;
//... all kinds of properties
}
class DBConnection
{
int load(Object& obj);
int save(Object& obj);
int modify(Object& obj);
int loadAll(std::vector);
}
class SNMPConn
{
int load(Object& obj);
...
}
What I disagree with is the line "friend class ...". This breaks encapsulation. I found some frameworks like litesql (sourceforge.net/apps/trac/litesql) and other commercial ones, but these frameworks are difficult to integrate with my existing code. I'm trying to do it manually and trying to find a general strategy for this kind of work.
I was a Java developer, C ++ design is something I don't like. I don't know what is best for this kind of design.
a source to share
As I understand from this problem (violation of encapsulation when reading and writing to DB or SNMP connection), first you need the right design to eliminate these "friends". define an abstract class for connections (like IDBConnection), also persistent objects (like IPersistent). You can use the Abstract Factory template to create them. Also, isolate the load and save methods in another class and use a "visitor pattern" to initialize or save your objects from / to your database.
One more point, if you need an embedded DB for your application, use SQLite , there are many good C ++ skins for that. Hope it helps.
a source to share
This is how I can do it in pseudocode:
class Result {
public:
int getField(name);
string getField(name);
}
class Connection {
public:
void save(list<pair<string, string>> properties);
Result query();
}
class DBConnection {
private:
class DBResult : public Result {
}
public:
Result query() {
return ( DBResult );
}
void save
}
class Object {
public:
void load(Result);
void save(Connection) {
// make properties list
connection.save(properties);
}
}
Without Java-style reflection, perhaps how I would do it without getting caught up in a friend relationship. Then you will not tightly associate knowledge of connection logic with connection classes.
...
You can also create template functions for this, but you still need friendships.
class Object {
public:
friend template<class Conn, class Obj> load(Conn c, Obj o);
friend template<class Conn, class Obj> save(Conn c, Obj o);
}
load<Connection, Object>(Connection c, Object o) {
//access o.private to load into c
}
I'm not sure where I would go. In one aspect, you encapsulate the load / save logic in object classes, which is great for localization, but it can tightly tie your persistence and business logic in one place.
a source to share