代码规范


参考了谷歌的开源代码规范

虽然好像写了很多代码,但是我还是有一个一上来就写代码的坏毛病。现在的代码不是以前的作业了,动辄上百行,如果写出混乱的代码不仅别人看不懂,自己在debug的时候也会带来麻烦。因此保持一个好的代码习惯非常重要。

命名规范

好的命名能够省去很多不必要的注释,现在IDE的自动补全功能十分强大,没必要为了省那一点点时间而使用简陋的命名。
比如

int n;                     // 毫无意义.
int nerr;                  // 含糊不清的缩写.

还有这种一个字母的变量除非用在循环中,否则也不要用。

int a, b, c, d;

生存期较长的变量比如全局变量尽可能用长的命名。而作用域比较短的变量可以用比较短的命名。作用域越长,命名越长。

然后有几种命名。

变量命名

变量命名不要大小写混合,全部使用小写。使用python的命名规范,单词之间用下划线连接。

string table_name;  // 好 - 用下划线.
string tableName;   //不好 - 大小写混合

类变量使用下划线结尾。结构体不用。struct用于只有数据,其它情况使用class。

class TableInfo {
  ...
 private:
  string table_name_;  // 好 - 后加下划线.
  static Pool<TableInfo>* pool_;  // 好.
};
struct UrlTableProperties {
  string table_name;
  static Pool<UrlTableProperties>* pool;
};

常量和枚举命名

推荐用k开头然后帕斯卡命名法。也可以全部大写,但是全部大写感觉可读性很差。

const int kDaysInAWeek = 7;
enum UrlTableErrors {
    kOK = 0,
    kErrorOutOfMemory,
    kErrorMalformedInput,
};

类结构枚举等类型名

// 类和结构体
class UrlTable { ...
class UrlTableTester { ...
struct UrlTableProperties { ...

// 类型定义
typedef hash_map<UrlTableProperties *, string> PropertiesMap;

// using 别名
using PropertiesMap = hash_map<UrlTableProperties *, string>;

// 枚举
enum UrlTableErrors { ...

函数命名

常规函数使用大小写混合, 取值和设值函数则要求与变量名匹配: MyExcitingFunction(), MyExcitingMethod(), my_exciting_member_variable(), set_my_exciting_member_variable().

也就是说,功能性接口性的函数用帕斯卡命名法,与变量的取值赋值有关的参照变量的命名即可。

最后, 有时候想不出命名了或者和系统命名冲突了. 比如信号signal与结构signal冲突了, 可以去CodeDef上搜.

注释

好的命名 + 不注释 > 坏的命名 + 好的注释 因此命名通常比注释更加重要.
多用文件注释和函数注释. 也就是这个文件干了什么, 这个函数干了什么.

函数的注释

单行注释和多行注释还是要统一, 尽量只用一种. 在主流的IDE都喜欢单行注释的情况下, 最好用单行注释.
比如这样的注释就非常好, 解释了函数的用法以及参数和返回值的类型. 以及在什么情况下参数会是什么值, 返回值会是什么值.

/**
 * Make a connection to the database server
 * Create (open) a database with name DB_NAME having 1 table named TABLE_NAME  
 * \param clear_up_flag if the table existed, clear up the existing data when clear_up_flag is set to 1
 * \return the connection for success, NULL if an error occurs
 */
DBCONN *init_connection(char clear_up_flag);

函数内部要分段, 注释紧贴所在的那一段. 如果其中某一段超过了20行, 那么就再抽象成一个函数.

你所提供的注释应当解释代码 为什么 要这么做和代码的目的.

// Find the element in the vector.  <-- 差: 这太明显了!
auto iter = std::find(v.begin(), v.end(), element);
if (iter != v.end()) {
  Process(element);
}

对还可以完善的代码使用TODO注释

重用和抽象

代码尽可能被抽象成扁平的形状, 让人容易理解. 大量复制粘贴的代码会给维护带来很大的困难.

void PushElephantToFridge(Elephant& elephant)
{
  OpenFridge();
  PushElephant(elephant);
  CloseFridge();
}

这样自顶向下的结构就很容易让人理解.
函数的参数尽可能用&, 如果不想改变函数的值的话用const&


Author: 蒋璋
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source 蒋璋 !