让我们看看垃圾代码长什么样子(以及重构的思路)

下面的代码实现连接数据库的功能,但是用的是全局函数实现。

函数也就罢了,里面的变量又用到了全局变量来访问数据库,由于多线程调用,所以还要支持多线程。

多线程访问全局变量就要支持并发,加临界区(或者说Guard)。

访问数据库又有可能出错,出错又要退出,退出又要在流程上处理错误处理,临界区控制更麻烦。

只要哪里写的不完备,你懂的,多线程临界区出了问题,多个线程的调用全局变量,这些线程就会像一把把锋利的匕首一样从你的四面向你刺来。你可能死都不知道是被谁弄死的。

让我们来看看这个超级烂的烂代码吧:

如何改进呢?

1 功能封装到class里

2 new的对象用类的普通成员变量表示(不是指针成员变量)

3 访问数据库的时候在线程内创建栈对象(这样不同的线程就会使用不同的栈对象,互不关联,免去了临界区那些个同步垃圾代码)

改进后的代码基本上是下面这个样子:

#include <string>
#include <Windows.h>

class QueryResult {};//第三方库的代码:仅仅作为示例
class ADO //第三方库的代码:仅仅用来说明:真正操作数据库的客户端类(或者函数族)
{
public:
	bool Connect(const std::string& connectInfor) { return true; }//仅仅作为示例:连接数据库
	bool Query(const std::string& querySql, QueryResult& result) { return true; }//仅仅作为示例:增删改查只用查询做例子
	bool Disconnect(void) { return true; }//断开连接数据库
};
class DataBaseHelper //你的代码:你使用这个类来访问数据库(主要封装连接和断开连接)
{
public:
	bool Connect(const std::string& connectInfor) { return  m_databaseHandle.Connect(connectInfor); }//仅仅作为示例
	bool Query(const std::string& querySql, QueryResult& result) { return  m_databaseHandle.Query(querySql, result); }//仅仅作为示例
	~DataBaseHelper();//析构函数负责断开连接
private:
	ADO m_databaseHandle;//真正操作数据库的类(或者函数族)
};
DataBaseHelper::~DataBaseHelper()
{
	m_databaseHandle.Disconnect();//程序员不需要记住要断开连接,这里总是自动调用(无需使用new动态对象)
}
void FunctionUseDatabaseExample(void)//这个函数代表所有访问数据库的模块(或者是线程函数)
{
	//有了以上的代码:我们就可以自由的使用临时变量(栈对象)访问数据库了
	DataBaseHelper dbHelper;//注意这里是临时变量,所以多线程是安全的(每个线程函数内使用各自的临时变量,不存在临界区)
	std::string databaseInfor("root/123456@my_odbc_name");
	if (!dbHelper.Connect(databaseInfor))//每次访问数据库之前都先连接,断开连接由析构函数调用
	{
		//错误处理程序,通常是退出当前函数,不往后执行;打印日志;或者同时弹出弹框提示(客户端)
	}
	//正常的操作数据库的增删改查在这里进行
	std::string querySql("balabala");
	QueryResult result;
	if (!dbHelper.Query(querySql, result))
	{
		//错误处理程序,通常是退出当前函数,不往后执行;打印日志;或者同时弹出弹框提示(客户端)
	}
	//继续走后续流程
	//to do your other work
	while (true)
	{
		dbHelper.Query(querySql, result);//这里表示有频繁访问数据库的需要
		int sometime = 1000 * 2;//2秒访问一次;如果更长时间(比如50秒,超过了连接超时时间),可以在这里再次使用循环内的临时变量(替代本函数一开始创建的dbHelper)
		Sleep(sometime);//假设这里是一个线程函数的话
	}
}//这里释放dbHelper,析构函数会断开与数据库的本次连接

int main()
{
	FunctionUseDatabaseExample();

    return 0;
}

以上DataBaseHelper类对象随用随创建,不用手动断开连接;可以被反复使用,安全可靠,省心。

其实真正的封装就这几行代码:

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C++程序员Carea

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值