所谓工程学就是把大问题拆成小问题,再把这些问题的解决方案放回一起。把这条原则应用于代码会使代码更健壮且更易读。
本章建议是:积极发现并抽取出不相关的子逻辑。
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 = "{ "; 6 for (var key in response_data) { 7 str += " " + key + " = " + response_data[key] + " "; 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 = "{ "; 18 for (var key in obj) { 19 str += " " + key + " = " + obj[key] + " "; 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)
总结:把项目专有代码和一般代码(使之成为辅助函数)分开。