《编写可读代码的艺术》第10章 抽取不相关的子问题

时间:2021-01-12
本文章向大家介绍《编写可读代码的艺术》第10章 抽取不相关的子问题,主要包括《编写可读代码的艺术》第10章 抽取不相关的子问题使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

    所谓工程学就是把大问题拆成小问题,再把这些问题的解决方案放回一起。把这条原则应用于代码会使代码更健壮且更易读。

    本章建议是:积极发现并抽取出不相关的子逻辑。

1. 纯工具代码

 1 //C++中没有一个库函数读取整个文件,所以不可避免地要写以下的代码:
 2 ifstream file(file_name);
 3 // Calculate the file's size, and allocate a buffer of that size.
 4 file.seekg(0, ios::end);
 5 const int file_size = file.tellg();
 6 char* file_buf = new char [file_size];
 7 // Read the entire file into the buffer.
 8 file.seekg(0, ios::beg);
 9 file.read(file_buf, file_size);
10 file.close();
11 
12 //这就是一个工具代码,应该抽取到一个新函数中(例如ReadFileToString)。
13 //经过一段时间,你会建立起一组不错的工具代码,可用于多个项目。

2. 其他多用途代码

 1 ajax_post({
 2     url: 'http://example.com/submit',
 3     data: data,
 4     on_success: function (response_data) {
 5         var str = "{\n";
 6         for (var key in response_data) {
 7             str += " " + key + " = " + response_data[key] + "\n";
 8         }
 9         alert(str + "}");
10         // Continue handling 'response_data' ...
11     }
12 });
13 
14 //从中抽取出format_pretty可以使代码使用更简单,更易读。
15 //同时,功能的修改或添加也更简单
16 var format_pretty = function (obj) {
17     var str = "{\n";
18     for (var key in obj) {
19         str += " " + key + " = " + obj[key] + "\n";
20     }
21     return str + "}";
22 };

 3. 简化已有接口

 1 var max_results;
 2 var cookies = document.cookie.split(';');
 3 for (var i = 0; i < cookies.length; i++) {
 4     var c = cookies[i];
 5     c = c.replace(/^[ ]+/, ''); // remove leading spaces
 6     if (c.indexOf("max_results=") === 0)
 7         max_results = Number(c.substring(12, c.length));
 8 }
 9 
10 //创建一个新的函数get_cookie
11 var max_results = Number(get_cookie("max_results"));

 

4. 按需重塑接口

 1 user_info = { "username": "...", "password": "..." }
 2 user_str = json.dumps(user_info)
 3 cipher = Cipher("aes_128_cbc", key=PRIVATE_KEY, init_vector=INIT_VECTOR, op=ENCODE)
 4 encrypted_bytes = cipher.update(user_str)
 5 encrypted_bytes += cipher.final() # flush out the current 128 bit block
 6 url = "http://example.com/?user_info=" + base64.urlsafe_b64encode(encrypted_bytes)
 7 
 8 #抽取出url_safe_encrypt
 9 def url_safe_encrypt(obj):
10     obj_str = json.dumps(obj)
11     cipher = Cipher("aes_128_cbc", key=PRIVATE_KEY, init_vector=INIT_VECTOR, op=ENCODE)
12     encrypted_bytes = cipher.update(obj_str)
13     encrypted_bytes += cipher.final() # flush out the current 128 bit block
14     return base64.urlsafe_b64encode(encrypted_bytes)
15 
16 #真正的逻辑代码将变得非常简单
17 user_info = { "username": "...", "password": "..." }
18 url = "http://example.com/?user_info=" + url_safe_encrypt(user_info)

 

5. 过犹不及

 1 #对于上面的代码可能可以进一步拆分,但是这么多小函数对可读性是不利的
 2 #因为读者需要关注过多的东西,并且按照执行路径跳来跳去
 3 #如果项目其他部分需要这些小函数,那么增加这些小函数是没问题的
 4 def make_cipher():
 5     return Cipher("aes_128_cbc", key=PRIVATE_KEY, init_vector=INIT_VECTOR, op=ENCODE)
 6 
 7 def encrypt(data):
 8     cipher = make_cipher()
 9     encrypted_bytes = cipher.update(data)
10     encrypted_bytes += cipher.final() # flush out any remaining bytes
11     return encrypted_bytes
12 
13 def url_safe_encrypt_str(data):
14     encrypted_bytes = encrypt(data)
15     return base64.urlsafe_b64encode(encrypted_bytes)
16 
17 def url_safe_encrypt_obj(obj):
18     obj_str = json.dumps(obj)
19     return url_safe_encrypt_str(obj_str)
20 
21 user_info = { "username": "...", "password": "..." }
22 url = "http://example.com/?user_info=" + url_safe_encrypt_obj(user_info)

 

总结:把项目专有代码和一般代码(使之成为辅助函数)分开。