? ?
"Code should be written to minimize the time it would take for someone else to understand it."
日常工作的事实是:
写代码前的思考和看代码的时间远大于真正写的时间
读代码是很平常的事情,不论是别人的,还是自己的,半年前写的可认为是别人的代码
代码可读性高,很快就可以理解程序的逻辑,进入工作状态
行数少的代码不一定就容易理解
代码的可读性与程序的效率、架构、易于测试一点也不冲突
整本书都围绕"如何让代码的可读性更高"这个目标来写。这也是好代码的重要标准之一。
如何命名
变量名中应包含更多信息
使用含义明确的词,比如用download而不是get,参考以下替换方案:
1
2
3
4
send -> deliver, dispatch, announce, distribute, route
find -> search, extract, locate, recover
start -> lanuch, create, begin, open
make -> create,set up, build, generate, compose, add, new
避免通用的词
像tmp和retval这样词,除了说明是临时变量和返回值之外,没有任何意义。但是给他加一些有意义的词,就会很明确:
1
2
3
tmp_file = tempfile.NamedTemporaryFile()
...
SaveData(tmp_file, ...)
不使用retval而使用变量真正代表的意义:
1
sum_squares += v[i]; // Where‘s the "square" that we‘re summing? Bug!
嵌套的for循环中,i、j也有同样让人困惑的时候:
1
2
3
4
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;
换一种写法就会清晰很多:
1
if (clubs[ci].members[mi] == users[ui]) # OK. First letters match.
所以,当使用一些通用的词,要有充分的理由才可以。
使用具体的名字
CanListenOnPort就比ServerCanStart好,can start比较含糊,而listen on port确切的说明了这个方法将要做什么。
--run_locally就不如--extra_logging来的明确。
增加重要的细节,比如变量的单位_ms,对原始字符串加_raw
如果一个变量很重要,那么在名字上多加一些额外的字就会更加易读,比如将string id; // Example: "af84ef845cd8"换成string hex_id;。
1
2
3
4
Start(int delay) --> delay → delay_secs
CreateCache(int size) --> size → size_mb
ThrottleDownload(float limit) --> limit → max_kbps
Rotate(float angle) --> angle → degrees_cw
更多例子:
1
2
3
4
password -> plaintext_password
comment -> unescaped_comment
html -> html_utf8
data -> data_urlenc
对于作用域大的变量使用较长的名字
在比较小的作用域内,可以使用较短的变量名,在较大的作用域内使用的变量,最好用长一点的名字,编辑器的自动补全都可以很好的减少键盘输入。对于一些缩写前缀,尽量选择众所周知的(如str),一个判断标准是,当新成员加入时,是否可以无需他人帮助而明白前缀代表什么。
合理使用_、-等符号,比如对私有变量加_前缀。
1
2
3
4
5
6
7
8
var x = new DatePicker(); // DatePicker() 是类的"构造"函数,大写开始
var y = pageHeight(); // pageHeight() 是一个普通函数
?
var $all_images = $("img"); // $all_images 是jQuery对象
var height = 250; // height不是
?
//id和class的写法分开
<div id="middle_column" class="main-content"> ...
命名不能有歧义
命名的时候可以先想一下,我要用的这个词是否有别的含义。举个例子:
1
results = Database.all_objects.filter("year <= 2011")
现在的结果到底是包含2011年之前的呢还是不包含呢?
使用min、max代替limit
1
2
3
4
5
6
7
CART_TOO_BIG_LIMIT = 10
if shopping_cart.num_items() >= CART_TOO_BIG_LIMIT:
Error("Too many items in cart.")
?
MAX_ITEMS_IN_CART = 10
if shopping_cart.num_items() > MAX_ITEMS_IN_CART:
Error("Too many items in cart.")
对比上例中CART_TOO_BIG_LIMIT和MAX_ITEMS_IN_CART,想想哪个更好呢?
使用first和last来表示闭区间
1
2
3
4
print integer_range(start=2, stop=4)
# Does this print [2,3] or [2,3,4] (or something else)?
?
set.PrintKeys(first="Bart", last="Maggie")
first和last含义明确,适宜表示闭区间。
使用beigin和end表示前闭后开(2,9))区间
1
2
3
PrintEventsInRange("OCT 16 12:00am", "OCT 17 12:00am")
?
PrintEventsInRange("OCT 16 12:00am", "OCT 16 11:59:59.9999pm")
上面一种写法就比下面的舒服多了。
Boolean型变量命名
1
bool read_password = true;
这是一个很危险的命名,到底是需要读取密码呢,还是密码已经被读取呢,不知道,所以这个变量可以使用user_is_authenticated代替。通常,给Boolean型变量添加is、has、can、should可以让含义更清晰,比如:
1
2
SpaceLeft() --> hasSpaceLeft()
bool disable_ssl = false --> bool use_ssl = true
符合预期
1
2
3
4
5
6
7
public class StatisticsCollector {
public void addSample(double x) { ... }
public double getMean() {
// Iterate through all samples and return total / num_samples
}
...
}
在这个例子中,getMean方法遍历了所有的样本,返回总额,所以并不是普通意义上轻量的get方法,所以应该取名computeMean比较合适。
漂亮的格式
写出来漂亮的格式,充满美感,读起来自然也会舒服很多,对比下面两个例子:
1
2
3
4
5
6
7
8
9
10
11
12
class StatsKeeper {
public:
// A class for keeping track of a series of doubles
void Add(double d); // and methods for quick statistics about them
private: int count; /* how many so far
*/ public:
double Average();
private: double minimum;
list<double>
past_items
;double maximum;
};
什么是充满美感的呢:
1
2
3
4
5
6
7
8
9
10
11
12
// A class for keeping track of a series of doubles
// and methods for quick statistics about them.
class StatsKeeper {
public:
void Add(double d);
double Average();
private:
list<double> past_items;
int count; // how many so far
double minimum;
double maximum;
};
考虑断行的连续性和简洁
这段代码需要断行,来满足不超过一行80个字符的要求,参数也需要注释说明:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class PerformanceTester {
public static final TcpConnectionSimulator wifi = new TcpConnectionSimulator(
500, /* Kbps */
80, /* millisecs latency */
200, /* jitter */
1 /* packet loss % */);
?
public static final TcpConnectionSimulator t3_fiber = new TcpConnectionSimulator(
45000, /* Kbps */
10, /* millisecs latency */
0, /* jitter */
0 /* packet loss % */);
?
public static final TcpConnectionSimulator cell = new TcpConnectionSimulator(
100, /* Kbps */
400, /* millisecs latency */
250, /* jitter */
5 /* packet loss % */);
}
原文:http://www.cnblogs.com/rootbin/p/4463280.html