在c++中建模变量成员类型

Modeling variable member type in C++

本文关键字:成员 成员类 类型 变量 建模 c++      更新时间:2023-10-16

我目前有一个运行代码,我用它通过给定的API (libpq)连接到数据库。

我基本上有两个类:主应用程序类CMain,以及与数据库相关的类CDbConnectorPq(负责连接数据库,发出查询并存储结果)。

在我的CMain构造函数中,我当前实例化了CDbConnectorPq类型的类成员,然后我使用该对象直接从我的CMain对象触发连接和查询:

main->dbConnectorPq->connect();

问题是我现在需要实现另一个API来连接到数据库(ODBC),除了libpq。我试图找出什么可以是一个体面的建模,以保持libpq代码从odbc代码分离,但仍然使用非常相同的接口从我的主要对象。

我想继承,但我最终有2个类,CDbConnectorPq和CDbConnectorODBC,然后在我的主要现在有两个成员:一个libpqxx,一个odbc,并被迫:

if ( gl_use_config_odbc )
  dbConnectorOdbc = new CDbConnectorODBC();
else if ( gl_use_config_libpq )
  dbConnectorPq = new CDbConnectorPq();

然后:

if ( gl_use_config_odbc ) {
  dbConnectorOdbc->connect();
  dbConnectorOdbc->query();
}
else if ( gl_use_config_pq ) {
  dbConnectorPq->connect();
  dbConnectorPq->query();
}

不知道如何在这里利用继承来屏蔽我的主对象的API特定逻辑。

理想情况下,界面应该是(我认为):

(如果gl_use_config = PQ)dbConnector -> setType (gl_use_config);dbConnector ->连接(…);dbConnector>连接(…);

or(如果gl_use_config = ODBC)dbConnector -> setType (gl_use_config);dbConnector ->连接(param1 param2);dbConnector>连接(query1 query2);

因为是的,PQ和ODBC之间的参数数在数量和类型上可能不同…

那么,对于这种情况,什么是明智的建模呢?

这不是典型的SO答案,但这是我对此的感受。在过去的15年里,我用OCI、OCCI、OTL、RogueWave、libpq和libpqxx为不同的公司编写了几个数据库层,我的建议是:不要这样做。认真。

要么只使用ODBC,甚至连接到PostgreSQL(我个人不喜欢),要么你应该开发两个完全分离的数据库访问层。如果你试图统一界面和用法,你将面临许多问题,这需要多年的经验。即使这样,在每一个新项目中,你都会发现另一个问题,界面也会比你想要的更频繁地变化。

如果你想开发单独的层,你可以做一些事情来简化应用程序从一个移植到另一个:

  • 尽量使它们相似,但不要强制!
  • 如果两层具有相同的功能和相同的语义,则使用相同的名称。
  • 如果两层具有相同的功能,但语义不同,则使用不同的名称。
  • 在使用数据库层的应用程序中,使用一个包含数据库头的头,并通过typedef s使用它们,或者更好的是,使用命名空间别名。
有了这个,移植变得更加容易。当您将应用程序从一层移植到另一层时,请更改头文件中的typedef或名称空间别名,并让编译器帮助您找到需要手动调整的内容。

我认为这样做的方法是让你的CMain类持有一个抽象基类的指针,两个子类派生自。例如

class IDatabase
{
public:
   virtual void connect() = 0;
   [...]
};

那么你唯一需要做if/Then逻辑的地方是当你创建适当类的对象时:

if ( gl_use_config_odbc ) {
    dbConnector = new CDbConnectorODBC();
} else {
    dbConnector = new CDbConnectorPq();
}

之后的内容与之前相同:

dbConnector->connect();

…c++的虚拟方法查找机制会根据(dbConnector)所指向的对象类型自动调用相应的方法。

至于不同的参数数,尝试将实现细节的代码保存在两个子类中,这样主代码就不必担心它们。CMain看到的iddatabase接口应该是与实现无关的。