假设有这样一个场景: 某系统会产生三类错误, 分别是: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
面对这些省份的不同要求, 我们该怎么搞呢? “最勤奋”的程序猿写出来的代码是:
我们看看上面的代码结果, 一看就感觉是重复啰嗦加累赘, 可能有的初学者说, 这很自然啊, 如果优化的话, 可以用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的。需要在程序中增加更多异常的判断, 比如检验配置文件格式的合法性。 但是, 在本文中, 我们仅作示例, 所以有很多异常情况并没有考虑。
总结一下:配置文件的引入, 使得程序对于需求变化不敏感, 也就是说, 程序不怕需求变化, 体现了很好的可扩展性, 回味一下, 确实如此。 实际的软件开发中, 有很多类似这样的地方, 建议大家注意程序结构的合理性