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代码。

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

int size = list.size();
if (size > 0) {
    cout << size << endl;
}

假设后面再也没有用到size了,但是阅读代码的人会一直把这个变量记住,因为 他以为后面还会用到这个变量。我们可以把它改成这样:

if ((int size = list.size()) > 0) {
    cout << size << endl;
}

当然,在C语言中,这需要C99的支持,当读者看完这段代码时,就会忘记这个变量, 因为后面已经用不上了。 作者是这样说的,但是我觉得这不太可能,因为写代码的人不可能预知未来,它总是 喜欢先把变量缓存起来,说不定以后还会用到,所以我不太赞成这种写法,除非是非常 简单,很明显后面用不上的变量。