C ++ code maintenance starts with an instance.

Source: Internet
Author: User

Originally published in the QQ space, see:C ++ code maintenance, starting from the instance

Big intelligence-agent server monitoringIt was an article a few months ago. I recently encountered a question about how to set up a proxy and reviewed some of the Code. Although the time was not long, I still cannot remember many of them ., As a result, I sorted out the function for setting proxy. The code is a science of practice. Every time I write it, I will have a bit of experience.

Paste the code first. The general process of this function is to first query the current browser settings, and then decide based on the user settings.

1. No proxy

2. Use the automatic configuration script

3. Use a proxy

One of the three options sets specific values based on different options, and then calls the API to set proxy options.

Void cwrsbar: modifysetting (const option: proxyentryinfo & Pei) {// refer to following value in wininet. h // so as to use these values as index in array. /// * # define internet_per_conn_flags 1 # define internet_per_conn_proxy_server 2 # define limit 3 # define internet_per_conn_autoconfig_url 4 # define limit 5 * // initialize the data structure, mainly the option array Internet _ Per_conn_option_list list; internet_per_conn_option option [6]; unsigned long nsize = sizeof (list); Option [0]. dwoption = 0; Option [0]. value. dwvalue = 0; // connection flags option [internet_per_conn_flags]. dwoption = internet_per_conn_flags; Option [internet_per_conn_flags]. value. dwvalue = proxy_type_direct; // | proxy_type_auto_detect; // proxy server option [internet_per_conn_proxy_server]. dwoption = Internet_per_conn_proxy_server; Option [internet_per_conn_proxy_server]. value. pszvalue = NULL; // proxy bypass option [internet_per_conn_proxy_bypass]. dwoption = internet_per_conn_proxy_bypass; Option [internet_per_conn_proxy_bypass]. value. pszvalue = NULL; // auto config URL option [internet_per_conn_autoconfig_url]. dwoption = internet_per_conn_autoconfig_url; Option [internet_per_conn_autoconfig_url]. Value. pszvalue = NULL; // others... option [internet_per_conn_autodiscovery_flags]. dwoption = internet_per_conn_autodiscovery_flags; Option [internet_per_conn_autodiscovery_flags]. value. dwvalue = auto_proxy_flag_user_set | auto_proxy_flag_detection_run; List. dwsize = nsize; // sizeof (internet_per_conn_option_list); list. pszconnection = NULL; List. dwoptioncount = 5; List. dwoptionerror = 0; List. popt Ions = & option [1]; // use it like C macro class justforoutputoption {public: void operator () (internet_per_conn_option * P) {atlassert (P ); internet_per_conn_option * option = P; wrst (log_trend_proxy) (text ("option [internet_per_conn_flags] (0x % x): (0x % x ),") text ("option [internet_per_conn_proxy_server] (0x % x): (% s),") text ("option [internet_per_conn_proxy_bypass] (0x % x): (% s ),") text ("option [int Ernet_per_conn_autoconfig_url] (0x % x): (% s), ") text (" option [internet_per_conn_autodiscovery_flags] (0x % x): (0x % x ). "), option [internet_per_conn_flags]. dwoption, option [internet_per_conn_flags]. value. dwvalue, option [internet_per_conn_proxy_server]. dwoption, option [internet_per_conn_proxy_server]. value. pszvalue? Option [internet_per_conn_proxy_server]. value. pszvalue: Text ("null"), option [internet_per_conn_proxy_bypass]. dwoption, option [internet_per_conn_proxy_bypass]. value. pszvalue? Option [internet_per_conn_proxy_bypass]. value. pszvalue: Text ("null"), option [internet_per_conn_autoconfig_url]. dwoption, option [internet_per_conn_autoconfig_url]. value. pszvalue? Option [internet_per_conn_autoconfig_url]. value. pszvalue: Text ("null"), option [internet_per_conn_autodiscovery_flags]. dwoption, option [internet_per_conn_autodiscovery_flags]. value. dwvalue) ;}} debugoutputoption; // query the current settings. if (internetqueryoption (null, internet_option_per_connection_option, & list, & nsize) {debugoutputoption (option); int proxytype = option: manual; STD: tstring proxyauto, Proxydirect; g_wrscfg.getopt (wrs_trendproxy_auto_name, proxyauto); g_wrscfg.getopt (wrs_trendproxy_direct_name, proxydirect); If (PEI. name = proxyauto) proxytype = option: auto; If (PEI. name = proxydirect) proxytype = option: Direct; STD: bit32 flag; Enum {use_old_pac = 1, use_old_bypass, use_old_proxy ,}; flag [use_old_pac] = Flag [use_old_proxy] = Flag [use_old_bypass] = true; tchar proxy [B Ufsize], bypass [bufsize]; proxy [0] = bypass [0] = 0; // set the switch (proxytype) according to the user's configuration) {// use the automatic configuration script. If there is a value, use the original value. Case option: Auto: {Option [internet_per_conn_flags]. value. dwvalue = proxy_type_direct | proxy_type_auto_proxy_url; If (! Option [internet_per_conn_autoconfig_url]. value. pszvalue |! Lstrlen (Option [internet_per_conn_autoconfig_url]. value. pszvalue) {// use auto value now // option [0]. value. pszvalue = const_cast <lptstr> (PEI. server. c_str (); Option [internet_per_conn_autoconfig_url]. value. pszvalue = const_cast <lptstr> (random (); flag [use_old_pac] = false ;}} break; // directly connect to case option: Direct: {Option [internet_per_conn_flags]. value. dwvalue = proxy_type_direct;} break; // use the user-configured proxy case option: Manual: {Option [internet_per_conn_flags]. value. dwvalue = proxy_type_direct | proxy_type_proxy; If (Option [internet_per_conn_proxy_server]. value. pszvalue) globalfree (Option [internet_per_conn_proxy_server]. value. pszvalue); _ sntprintf (proxy, BufSize-1, text ("% s: % d"), Pei. server. c_str (), Pei. port); atlassert (lstrlen (proxy); Option [internet_per_conn_proxy_server]. value. pszvalue = proxy; flag [use_old_proxy] = false; If (Option [internet_per_conn_proxy_bypass]. value. pszvalue) globalfree (Option [internet_per_conn_proxy_bypass]. value. pszvalue); lstrcat (bypass, g_wrstrendproxycfg.bypass.c_str (); If (lstrlen (bypass) lstrcat (bypass, text (";"); lstrcat (bypass, text ("<local>"); Option [internet_per_conn_proxy_bypass]. value. pszvalue = bypass; flag [use_old_bypass] = false;} break;} debugoutputoption (option); // sets the proxy option internetsetoption (null, internet_option_per_connection_option, & list, nsize ); // free memeory if (Option [internet_per_conn_proxy_bypass]. value. pszvalue & flag [use_old_bypass]) globalfree (Option [internet_per_conn_proxy_bypass]. value. pszvalue); If (Option [internet_per_conn_proxy_server]. value. pszvalue & flag [use_old_proxy]) globalfree (Option [internet_per_conn_proxy_server]. value. pszvalue); If (Option [internet_per_conn_autoconfig_url]. value. pszvalue & flag [use_old_pac]) globalfree (Option [internet_per_conn_autoconfig_url]. value. pszvalue); // system // notifies the system that the registry settings have been changed so that it verifies the settings on the next call to internetconnect. // This is used by internetsetoption. internetsetoption (null, internet_option_settings_changed, null, 0); // ie // causes the proxy data to be reread from the registry for a handle. no buffer is required. // This option can be used on the hinternet handle returned by internetopen. it is used by internetsetoption. // so if we don't call this API ie might show previous value even after last API call. /// internetsetoption (null, internet_option_refresh, null, 0 );}}

There are two special points in this Code,

1. for the use of option arrays, numbers are directly used as indexes at the beginning, that is, option [0], option [1], option [2],..., this can certainly work. But a few days later, you will find that you cannot remember the meanings of each index, which is put by proxy, which is put by URL, and that is put by bypass, it is especially unfavorable for subsequent code maintenance. After thinking about it, I think it is more appropriate to use meaningful enumeration names. I read wininet. the several values defined by H can be directly indexed, so the code is slightly changed to the above. Option [0] is used as a placeholder. The meaningful option starts with option [1. In this way, it is very clear whether it is the initialization part at the beginning of the function or the assignment of some options in the middle of the function.Magic numberNo. Make a simple comparison between this method and the original method:

A. before coding the design, before writing the code, there will be an idea in the metropolis: Option [0] Put what, option [1] Put what, but because of the use of numbers for indexing, the code is similar to this

Option[1].dwOption = INTERNET_PER_CONN_FLAGS;Option[1].Value.dwValue = PROXY_TYPE_DIRECT;

At the beginning, I may know what 1 represents, but I actually look at the code and analyze it from the code perspective, but in turn, the meaning of the Left variable is derived from the value on the right, this violates the basic coding principles and is sometimes confusing. Even if option [1] is not designedInternet_per_conn_flags,It cannot be seen from the Code. On the contrary, if the statement is as follows,

Option[INTERNET_PER_CONN_FLAGS].dwOption = INTERNET_PER_CONN_PROXY_SERVER;

You will soon find the error because the left and right do not match.

B. A's good coding can also show its advantages in the future,Debugoutputoption (option );The value of the Option array is output. If you use numbers for indexing, you can also understand what option [0] And Option [1] represent and what their types will be? You need amazing memory. By using meaningful enumeration names as indexes, you can easily implement this function and get twice the result with half the effort. You can easily determine which is DWORD and which is a string.

Option[INTERNET_PER_CONN_FLAGS].Value.dwValueOption[INTERNET_PER_CONN_PROXY_BYPASS].Value.pszValue 

2.JustforoutputoptionIt is a local class. The code that actually works is a statement. For the definition of the local class, what about the partial class? At first, after querying the browser's proxy settings and before starting the new proxy settings, the statement of debugging information was printed directly. At that time, I thought that even though the code was output by debugging, however, this code is complex and repeated twice. It is necessary to encapsulate it. However, at that time, it was not because of laziness. Later, for the reason of option 1, the order in the option array changed and the two debugging statements had to be modified. It was very troublesome, so I had the idea of packaging. The first thing that comes to mind is to use an independent function packaging. If you think about it, it is not appropriate to use function packaging.

A. if a separate function is used, the function range must at least be a member function of the class, but it is only used inside the function,

B. If other functions will use this function, how should I design the function parameters? Pass the pointer of the Option type and the size of the array. What about the order of the Option array? The order of option array members of other functions cannot be ensured.

Therefore, from the perspective of scope, the scope is limited to the inside of the function, and there is no need to affect the entire class or even the global. From the perspective of function design, it is not suitable for designing functions because they are not universal. For developers familiar with C, macro is a choice in this place and can be used to replace simple text. For C ++ developers, local class is a better choice. After all, macros have many disadvantages. Therefore, the local class is used to wrap the debug output statement and operator () is overloaded, which is as convenient as function call.

DebugOutputOption( Option );

The local class has other purposes, such as raiI. By the way, C ++ is a controversial language. Many fans of other languages have ridiculed C ++ for its many useless features. The local class is one of them. Under these people.

The above two points are almost the same. Finally, the Code is well written. Without QA testing, the possibility of bugs is not ruled out.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.