基本原则:好的代码,能够减少 "别人" 理解它的时间。 "别人" 不仅指的是 其他人,也可能是 以后的自己

1 代码应易理解
1.1 符合习惯
下面两种形式等效,但方式2 更符合编码习惯,容易理解
// 方式 1
Node* node = list->head;
if (node == NULL) return;
while(node->next != NULL) {
Print(node->data)
node = node->next;
}
if(node != NULL) Print(node->data);
// 方式 2
for (Node* node = list->head; node != NULL; node = node->next)
Print(node->data);
1.2 少且易懂
1) 少 + 易懂
// 多 - if 语句
if(exponent >= 0) {
return mantissa * (1 << exponent);
} else {
return mantissa / (1 << -exponent);
}
// 少 - 条件运算符
return exponent >= 0 ? mantissa * (1 << exponent) : mantissa / (1 << -exponent);
2) 少 + 不易懂
// 少 - 不易理解 assert ((!(bucket = FindBucket(key))) || !bucket->IsOccupied()); // 多 - 易理解 bucket = FindBucket(key); if(bucket != NULL) asset(!bucket->IsOccupied());

2 封装信息到名字
2.1 命名要贴切
2.1.1 使用特有的词
BinaryTree 类中的 Size() 不如 Height()、NumNodes() 或 MemoryBytes() 更明确;Thread 类中 通常是 Kill(),而不是 Stop(),且 Pause() 和 Resume() 成对出现
常用词语的替代词,如下:
// send = deliver, dispatch, announce, distribute, route // find = search, extract, locate, recover // start = launch, create, begin, open // make = create, set up, build, generate, compose, add, new
2.1.2 避免通用名
retval 是 “平方和”,不如 sum_squares 合适
var euclidean_norm = function (v) {
var retval = 0.0;
for (var i = 0; i < v.length; i += 1)
retval += v[i] * v[i];
return Math.sqrt(retval);
};
如下 tmp 较为合适
if (right < left) {
tmp = right;
right = left;
left = tmp;
}
但下例的 tmp 就不如 tmp_file 更明确
tmp_file = tempfile.NamedTemporaryFile() ... SaveDate(tmp_file, ...)
i, j, k 易混淆,不如 clubs_i, members_i, users_i 方便,或简化为 ci, mi, ui
for (int i = 0; i < clubs.size(); i++)
for (int j = 0; j < clubs[i].members.size(); j++)
for (int k = 0; k < users.size(); k++)
if (clubs[i].members[k] == users[j])
cout << "user[" << j << "] is in club[" << i << "]" << endl;
2.1.3 使用具体的名
谷歌早期的 C++编码规范,为了避免编译器自动生成拷贝构造函数和赋值算子,定义了如下宏:
#define DISALLOW_EVIL_CONSTRUCTORS(ClassName) \ ClassName(const ClassName&); \ void operator=(const ClassName&);
这个名字不如后来的 DISALLOW_COPY_AND_ASSIGN(ClassName) 贴切
实际上,C++11 有了 delete 关键字,无须使用该宏了,参见 C++11 之 delete 和 default
2.2 附加额外信息
2.2.1 类型
某些变量,附加额外的信息可以更好的理解,如,一个16进制的变量,命名为 hex_id 比 id 更贴切
// Example: "af84ef845cd8" string hex_id;
2.2.2 单位
如下 getTime() 返回值的单位是 ms 而不是 s,可将 _ms 作为后缀加到变量的后面,则会使代码变得更为清晰
var start_ms = (new Date()).getTime(); // top of the page ... var elapsed_ms = (new Date()).getTime() - start_ms; // bottom of the page document.writeln("Load time was: " + elapsed_ms / 1000 + " seconds");
除了时间,还有别的单位:
// 带单位的函数参数 Start (int delay_secs) CreateCache (int size_mb) ThrottleDownload (float limit_kbps) Rotate (float angle_cw)
2.2.3 其它属性
一些有关安全的变量命名,也常需要一些额外的信息
// A password is in "plaintext" and should be encrypted before further processing std::string plaintext_password; // Byte of html have been converted to UTF-8 std::string html_utf8; // Incoming data has been "url encoded" std::string data_urlenc;
2.3 格式要求
2.3.1 作用域和缩写
- 长名长域,短名短域:变量 m 并没有封装任何信息,但是因为只在 if 作用域内有效,所以并不对妨碍代码的理解
- 善用缩写:当变量名实在太长,可考虑缩写,但要注意团队中的新人,也能理解缩写的含义。如,evaluation 常缩写为 eval,document -> doc,string -> str
- 去掉无用词:ToString() 优于 ConvertToString(),ServeLoop() 比 DoServeLoop() 简洁
if (debug) {
map<string,int> m;
LookUpNamesNumbers(&m);
Print(m);
}
2.3.2 下划线和大写
谷歌 C++ 编码规范中:
- 类名一般是各个首字母大写,类成员函数名也是如此;
- 类成员变量名后都带有下划线 "_";
- 常量命名为 kConstantName,和 #define MACRO_NAME 宏区分
static const int kMaxOpenFiles = 100;
class LogReader {
public:
void OpenFile(string local_file);
private:
int offset_;
DISALLOW_COPY_AND_ASSIGN(LogReader);
};
原文链接: http://www.cnblogs.com/xinxue/
专注于机器视觉、OpenCV、C++ 编程
浙公网安备 33010602011771号