养成好的code style

这里主要从代码格式标识符命名注释三个方面,讲一下怎么“写出好的code style”。

留白的艺术

好程序里的空白行至少要占到总行数的20%以上

恰当地运用空格和空行,不为了“节省篇幅”和“紧凑”而把很多语句挤在一起,保持适当的阅读节奏。

演示示例:

  • 未留白的代码
  1. if(!value.contains("xxx")){
  2. LOGIT(WARNING,"value is incomplete.\n")
  3. return;
  4. }
  5. char suffix[16]="xxx";
  6. int data_len = 100;
  7. if(!value.empty()&&value.contains("tom")){
  8. const char* name=value.c_str();
  9. for(int i=0;i<MAX_LEN;i++){
  10. ... // do something
  11. }
  12. int count=0;
  13. for(int i=0;i<strlen(name);i++){
  14. ... // do something
  15. }
  16. }
  • 留白的代码
  1. f (!value.contains("xxx")) { // if后{前有空格
  2. LOGIT(WARNING, "value is incomplete.\n") // 逗号后有空格
  3. return; // 逻辑联系紧密就不用加空行
  4. }
  5. // 新增空行分隔段落
  6. char suffix[16] = "xxx"; // 等号两边有空格
  7. int data_len = 100; // 逻辑联系紧密就不用加空行
  8. // 新增空行分隔段落
  9. if (!value.empty() && value.contains("tom")) { // &&两边有空格
  10. const char* name = value.c_str(); // 等号两边有空格
  11. // 新增空行分隔段落
  12. for(int i = 0; i < MAX_LEN; i++){ // =;<处有空格
  13. ... // do something
  14. }
  15. // 新增空行分隔段落
  16. int count = 0; // 等号两边有空格
  17. // 新增空行分隔段落
  18. for(int i = 0; i < strlen(name); i++){ // =;<处有空格
  19. ... // do something
  20. }
  21. }

命名的艺术

做好代码格式的调整后,接下来我们要操心的就是里面的内容了,而其中一个很重要的部分就是为变量、函数、类、项目等的命名。

函数的命名风格已知的有匈牙利命名法CamelCasesnake_case,这里选择自己喜欢的方式即可。

这里演示我的命名习惯。

演示示例:

  1. #define MAX_PATH_LEN 256 // 宏定义,全大写
  2. int g_sys_flag; // 全局变量,加g_前缀
  3. namespace linux_sys { // 名字空间,全小写
  4. void get_rlimit_core(); // 函数,全小写
  5. }
  6. class FilePath final // 类名,首字母大写
  7. {
  8. public:
  9. void set_path(const string& str); // 函数,全小写
  10. private:
  11. string m_path; // 成员变量,m_前缀
  12. int m_level; // 成员变量,m_前缀
  13. };

除此之外,变量名和函数名等尽量使用英文命名。而不是无意义的字符汉语拼音汉语拼音的缩写无意义的单词缩写,当然还可以用一些已经在程序员之间形成了普遍共识的变量名,比如用于循环的i/j/k、用于计数的count、表示指针的p/ptr、表示缓冲区的buf/buffer、表示变化量的delta、表示总和的sum等。

还有一点建议是:变量/函数的名字长度与它的作用域成正比,也就是说,局部变量/函数名可以短一点,而全局变量/函数名应该长一点。(个人感觉在阅读代码时可以起到一定的作用)

用好注释

注释主要用来阐述目的用途工作原理注意事项等代码本身无法“自说明”的那些东西。因此,注释必须要正确、清晰、有效,尽量言简意赅、点到为止,不要画蛇添足,更不能写出含糊、错误的注释。

演示示例:

未注释的模板函数

  1. template<typename T>
  2. int get_value(const T& v);

注释的模板函数

  1. /**
  2. * @author : zaizai is here
  3. * @date : 2022-08-30
  4. * @purpose : get inner counter value of generic T
  5. * @notice : T must have xxx member
  6. * @notice : return value maybe -1, means xxx, you should xxx
  7. */
  8. template<typename T>
  9. int get_value(const T& v);

虽然代码很简单,但未注释时可用的信息太少了,并不知道各个参数的具体要求,但可以给它加上作者、功能说明、调用注意事项、可能的返回值,等等,这样看起来就会清晰很多。当然,写法只是提供参考,具体风格可以参考doxygenjavadoc-The Java API Documentation Generator等工具。

此外,除了给代码、函数、类写注释,最好在文件的开头写上本文件的注释,里面有文件的版权声明、更新历史、功能描述,等等。

演示实例:

  1. /**
  2. * Copyright (c) 2022 by zaizai is here
  3. * @file : zaizai is here
  4. * @date : 2022-08-30
  5. * @desc : ...
  6. */

另外,注释还有一个很有用的功能就是todo,作为功能的占位符,提醒将来的代码维护者,比如:

  1. /**
  2. * @TODO: change it to unordered_map
  3. * @XXX: fixme later
  4. */

总的来说,要写好注释,你要时刻“换位思考”,设身处地去想别人怎么看你的代码,这样的话,上面的那些细则也就不难实施了。