simplify_loop_and_logic
本文为"the art of readable code"一书的笔记
making control flow easy to read
- 下面的代码:
if (length >= 10)
要比
if (10 <= length)
更容易看懂。这是很显然的。而在C语言中,有的人为了避免=与==的错误,常常把 代码写成:
if (10 == length)
这种做法是为了避免错误的。其实在我看来,这明显是在掩饰自己区分不了=与==的 弱点,如果你真的理解赋值与相等的含义,就从来不会在比较相等的时候写成=,以 我使用C语言这么多年来,我从来没有犯过这种错误。上面的代码对于一个正常人来 说,很难理解,因为程序员首先是一个人,自然的语言是“长度等于10”,而不是 “10等于长度”,所以为了使代码更可读,我建议使用下面这种:
if (lenght == 10)
- 上面的是有数字,有常量的比较,下面这个:
while (bytes_received < bytes_expected)
要比
while (bytes_expected > bytes_received)
更容易看懂,因为第一个的阅读顺序符合人类的自然语言。
- 对于三目运算符?:,当表达式很长时不要使用。
- 不要使用do/while。当你阅读do/while的时候,因为你刚开始不知道条件,你会
把循环的主体阅读两次。我几乎不写do/while,而且我非常讨厌看do/while代码。
- 尽量不要使用嵌套的if/else,想尽办法使得只有一个层次。
breaking down giant expressions
- 利用宏来简化代码。看下面的例子:
void AddStats(const Stats &add_from, Stats *add_to)
{
add_to->set_total_memory(add_from.total_memory() +
add_to->total_memory());
add_to->set_free_memory(add_from.free_memory() +
add_to->free_memory());
add_to->set_swap_memory(add_from.swap_memory() +
add_to->swap_memory());
}
不管是谁,看到这样的代码都会头晕,但是你会发现其实它们都在做同一件事:
addto->setXXX(addfrom.XXX + addto->XXX);
于是,通过定义带参数的宏,可以简化成这样:
void AddStats(const Stats &add_from, Stats *add_to)
{
#define ADD_FIELD(field) \
add_to->set_#field(add_from.#field() + add_to->#field())
ADD_FIELD(total_memory);
ADD_FIELD(free_memory);
ADD_FIELD(swap_memory);
}
这样不仅视觉上看起来舒服,而且理解起来非常容易。
variables and readability
- 可去除一些多余的变量
- 尽量缩小变量的范围,即使是全局变量,这样才能让程序更清晰。
- 在C++中,有这样一个例子:
int size = list.size();
if (size > 0) {
cout << size << endl;
}
假设后面再也没有用到size了,但是阅读代码的人会一直把这个变量记住,因为 他以为后面还会用到这个变量。我们可以把它改成这样:
if ((int size = list.size()) > 0) {
cout << size << endl;
}
当然,在C语言中,这需要C99的支持,当读者看完这段代码时,就会忘记这个变量, 因为后面已经用不上了。 作者是这样说的,但是我觉得这不太可能,因为写代码的人不可能预知未来,它总是 喜欢先把变量缓存起来,说不定以后还会用到,所以我不太赞成这种写法,除非是非常 简单,很明显后面用不上的变量。
- 尽量使变量只能改变一次(prefer write-once varaibles)