参考了谷歌的开源代码规范
虽然好像写了很多代码,但是我还是有一个一上来就写代码的坏毛病。现在的代码不是以前的作业了,动辄上百行,如果写出混乱的代码不仅别人看不懂,自己在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&