学会利用“配置文件”优化我们的代码结构

       之前我们讲过某些时候可以利用数组来代替if/else来优化代码, 在本文中, 我们再次来复习一下, 顺便学学利用配置文件来优化代码结构, 好, 开始吧。

 

       假设有这样一个场景: 某系统会产生三类错误, 分别是:ERROR_TYPE_ONE, ERROR_TYPE_TWO, ERROR_TYPE_THREE. 但是呢, 各省份有不同的需求, 比如:

      1. 安徽省要求遇到上述三种错误后分别显示:101, 102, 103

      2. 湖北省要求遇到上述三种错误后分别显示:1001, 1002, 1003

      3.广东省要求遇到上述三种错误后分别显示:10001, 10002, 10003

      4.黑龙江要求遇到上述三种错误后分别显示:201, 202, 203

      5.浙江省要求遇到上述三种错误后分别显示:2001, 2002, 2003

 

      面对这些省份的不同要求, 我们该怎么搞呢? “最勤奋”的程序猿写出来的代码是:

 

#include <iostream>
using namespace std;

enum ErrorType
{
	UNDEFINED,
	ERROR_TYPE_ONE,
	ERROR_TYPE_TWO,
	ERROR_TYPE_THREE,	
};

int main()
{
	char szProvince[100] = {0};
	cin >> szProvince;
	
	int error = -1;
	cin >> error;

	if(0 == strcmp("anhui", szProvince))
	{
		if(ERROR_TYPE_ONE == error)
		{
			cout << 101 << endl;
		}
		else if(ERROR_TYPE_TWO == error)
		{
			cout << 102 << endl;
		}
		else if(ERROR_TYPE_THREE == error)
		{
			cout << 103 << endl;
		}
	}

	if(0 == strcmp("hubei", szProvince))
	{
		if(ERROR_TYPE_ONE == error)
		{
			cout << 1001 << endl;
		}
		else if(ERROR_TYPE_TWO == error)
		{
			cout << 1002 << endl;
		}
		else if(ERROR_TYPE_THREE == error)
		{
			cout << 1003 << endl;
		}
	}

	if(0 == strcmp("guangdong", szProvince))
	{
		if(ERROR_TYPE_ONE == error)
		{
			cout << 10001 << endl;
		}
		else if(ERROR_TYPE_TWO == error)
		{
			cout << 10002 << endl;
		}
		else if(ERROR_TYPE_THREE == error)
		{
			cout << 10003 << endl;
		}
	}

	if(0 == strcmp("heilongjiang", szProvince))
	{
		if(ERROR_TYPE_ONE == error)
		{
			cout << 201 << endl;
		}
		else if(ERROR_TYPE_TWO == error)
		{
			cout << 202 << endl;
		}
		else if(ERROR_TYPE_THREE == error)
		{
			cout << 203 << endl;
		}
	}

	if(0 == strcmp("zhejiang", szProvince))
	{
		if(ERROR_TYPE_ONE == error)
		{
			cout << 2001 << endl;
		}
		else if(ERROR_TYPE_TWO == error)
		{
			cout << 2002 << endl;
		}
		else if(ERROR_TYPE_THREE == error)
		{
			cout << 2003 << endl;
		}
	}

	return 0;
}

       我们看看上面的代码结果, 一看就感觉是重复啰嗦加累赘, 可能有的初学者说, 这很自然啊, 如果优化的话, 可以用switch来优化啊.  其实, 用switch又怎样呢? 还不是一样的垃圾代码?

 

 

      我们之前说过用数组优化if/else,   我们可以考虑一下数组。 但此处我自问一下, 为什么数组可以优化? 因为数组的本质就是映射! 废话少说, 直接上代码:

 

#include <iostream>
using namespace std;

int a[][3] = 
{
	{101, 102, 103},
	{1001, 1002, 1003},
	{10001, 10002, 10003},
	{201, 202, 203},
	{2001, 2002, 2003}
};

int main()
{
	char szProvince[100] = {0};
	cin >> szProvince;
	
	int error = -1;
	cin >> error;

	if(error < 1 || error > 3)
	{
		return 1;
	}

	if(0 == strcmp("anhui", szProvince))
	{
		cout << a[0][error - 1] << endl;
	}

	if(0 == strcmp("hubei", szProvince))
	{
		cout << a[1][error - 1] << endl;
	}

	if(0 == strcmp("guangdong", szProvince))
	{
		cout << a[2][error - 1] << endl;
	}

	if(0 == strcmp("heilongjiang", szProvince))
	{
		cout << a[3][error - 1] << endl;
	}

	if(0 == strcmp("zhejiang", szProvince))
	{
		cout << a[4][error - 1] << endl;
	}

	return 0;
}

      看看, 是不是简洁多了。 其实上述代码还可以优化, 我们只需要建立字符串到整数的映射即可, 如下:

 

 

#pragma warning(disable : 4786)   
#include <iostream>  
#include <string>  
#include <map>  
using namespace std;  

int a[][3] = 
{
	{101, 102, 103},
	{1001, 1002, 1003},
	{10001, 10002, 10003},
	{201, 202, 203},
	{2001, 2002, 2003}
};

typedef map<string, int> strMapInt;
typedef map<string, int> :: iterator It;  
strMapInt g_map;

void buildMap()
{
	g_map.insert(make_pair(string("anhui"), 1));
	g_map.insert(make_pair(string("hubei"), 2));
	g_map.insert(make_pair(string("guangdong"), 3));
	g_map.insert(make_pair(string("heilongjiang"), 4));
	g_map.insert(make_pair(string("zhejiang"), 5));
}

int main()
{
	buildMap();

	char szProvince[100] = {0};
	cin >> szProvince;
	
	int error = -1;
	cin >> error;

	if(error < 1 || error > 3)
	{
		return 1;
	}

	It it = g_map.find(string(szProvince));  
    if(g_map.end() != it)  
    {  
        cout << a[it->second - 1][error - 1] << endl;
		return 0;
    }

	return 1;
}

       但是呢, 上述程序有两个问题: 1. 如果某个省份比较讨厌, 它突然要改变对应的错误码显示, 比如安徽想把101变为1000001. 这个时候, 程序猿不得不动代码了。 2. 如果要增加一些省份怎么办呢? 这个时候, 程序猿也需要动代码了。

 

       下面, 我们考虑利用配置文件来进行优化, 通常来讲, 在这种情况下, .xml文件做配置文件是非常适合的, 但为了简便起见, 我们用.txt文件来代替。 我们在config.txt文件中制作如下内容(以安徽为例):

1
101
2
102
3
103

       然后改程序如下:

 

#include <iostream>  
#include <string>  
#include <fstream>
using namespace std;  

int main()
{
	int error = -1;
	cin >> error;

	ifstream infile("config.txt");
	string line;
	int n = 0;
	if(infile)
	{
		while(getline(infile, line))
		{
			if(atoi(line.c_str()) == error)
			{
				getline(infile, line); // 取下一行
				n = atoi(line.c_str());

				cout << n << endl;
				return 0;
			}
		}
	}

	return 1;
}

       我们可以看到, 这个程序不怕省份增多, 也不怕省份的错误码变更。 我们需要做的是, 对每一个省份, 搞个配置文件即可。

 

       不得不说, 说面的程序还是很fragile的。需要在程序中增加更多异常的判断, 比如检验配置文件格式的合法性。 但是, 在本文中, 我们仅作示例, 所以有很多异常情况并没有考虑。

 

      总结一下:配置文件的引入, 使得程序对于需求变化不敏感, 也就是说, 程序不怕需求变化, 体现了很好的可扩展性, 回味一下, 确实如此。 实际的软件开发中, 有很多类似这样的地方, 建议大家注意程序结构的合理性。

 

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值