常言道:“字如其人”。对于程序员来说,代码就是他们的著作。好的编程风格是成为一个好的程序员的必要条件。
编程风格是一个程序员在写代码时的一些惯例。好的编程风格,与代码的可读性有着不可分割的关系。好的编程风格,并不是个性的写法,而是大多程序员都共同认可的、可读性强的习惯性代码写法。
本文主要总结《The Art of Readable Code》一书,来说明编程风格与代码可读性的问题。(The Art of Readable Code by Dustin Boswell and Trevor Foucher. Copyright 2012 Dustin Boswell and Trevor Foucher, 978-0-596-80229-5)。
优秀编程风格的原则:代码应该易于理解。阅读代码的人是否能快速的读懂你的代码(Time-Till-Understanding),是编程风格好坏的关键。
基础层面的改进
一、关于命名
(1)选用特定的单词
例:
class BinaryTree {
int Size();
...
};
上面代码中,Size() 的返回值是这个二叉树的节点数能,还是二叉树的高度?如果将Size()替换成NumNodes()或Height(),则能直接传递更多的信息。
(2)避免一般的命名
①tmp :temporary一般用于存放临时变量。
当变量tmp的生命周期只有几行代码时,使用tmp是一个很好的选择。例:
if (right < left) {
tmp = right;
right = left;
left = tmp;
}
而当tmp在函数直接传递,或者需要被修改和多次使用时,使用tmp作为变量名是一个偷懒的行为。例:
string tmp = user.name();
tmp += " " + user.phone_number();
tmp +- " " + user.email();
...
template.set("user_info", tmp);
在上面代码中,tmp改为user_info则能更好的描述变量本身。
②retval : return value。一般用于存放返回值。 当你使用retval时,就在向阅读代码的人说,我想不到名字。例:
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);
};
在上面代码中,retval改为sum_squeares则更佳。
③Loop Iterators(i, j, iter)。i,j,k,iter为常用的迭代器名。例:
for (int i = 0; i < club.size(); i++)
for (int j = 0; j < club[i].members.size(); j++)
for (int k = 0; k < users.size(); k++)
if (clubs[i].member[k] == users[j])
cout << "user[" << j << "] is in club[" << i << "]" << endl;
如果细心的话,就会发现if (clubs[i].member[k] == users[j]) 这句的迭代器写错了。如果将(i, j, k)改成(ci, ui, mi),则判断语句为if (clubs[ci].member[ui] == users[mi]) 可以明显看出迭代器使用的错误。
(3)用具体的变量名替换抽象的变量名
例如:void CleanRepley(),从函数名中我们只能知道函数的作用是对Repley进行一些整理,但具体的工作我们并不了解。如果将变量名改为 void DeleteReply(),则可以清晰的知道,函数的作用为删除回复。
(4)在变量名中附加信息
①在变量名里加上单位。例:
var start = (new Date()).getTime(); // top of the page
...
var elapsed = (new Date()).getTime() - start; // bottom of the page
document.writeln("Load time was: " + elapsed + "seconds")
上述代码中,没有明显错误。但是getTime() 的返回值的单位为ms,而不是s。为了使表达更清晰,我们可以将start与elapsed加上单位在后面,代码更改如下:
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 + "seconds")
②在变量名里加上特征。例:
如果是以明文保存的password,可改变量名为plaintext_password。
(5)变量名的长度问题
变量名长短的限制,要根据具体使用情况分析。
①作用于小范围内(在代码中出现的行数)的变量可以简短。 例:
if (debug) {
map<string, int> m;
LookUpNamesNumbers(&m);
Print(m);
}
虽然变量名 m 没有携带太多信息,但是它已经拥有了它所要所有信息。然而,在全局变量中使用m ,则不妥。如下例:
LookUpNamesNumbers(&m);
Print(m);
②对于长的变量名,现在的编译器大都有自动补全功能。所以,输入长的变量名,不再是一个烦人的问题。
③单词缩写的使用。
在命名中,我们常常使用单词的缩写。将FormatString()缩写为FormatStr(),我们也可以很清楚明白意思。然而,将BackEndManager缩写为BEManager,我们就很难明白。所以在命名的缩写中,我们要注意惯用的缩写。
④扔到没有的单词
例如:ConvertToString()可以简化为ToString(),DoServeLoop()可以简化为ServeLoop()。
(6)形成一些惯例
例如,通过 _ 和 - 的不同来区分变量特征。<div id="middle_column" class="main-content">。
The Art of Readable Code by Dustin Boswell and Trevor Foucher. Copyright 2012 Dustin Boswell and Trevor Foucher, 978-0-596-80229-5