首页 > 其他 > 详细

读书笔记之《The Art of Readable Code》Part 2

时间:2017-01-17 00:32:19      阅读:165      评论:0      收藏:0      [点我收藏+]

如何写好流程控制语句(if-else/switch/while/for)使得代码更可读些?(chap 7)

* 提高条件语句的可读性(if语句, 或者bool型summary变量)

if (length >= 10)    // Good
if (10 <= length)    // Bad

while (bytes_received < bytes_expected)  // Good
while (bytes_expected < bytes_received)  // Bad

if (NULL == obj) ...  // Not suggested now
if (obj == NULL) ...  // Good

分析:
    left-hand side放我们需要检查的, 经常变化的变量
    right-hand side放常量或者不容易变化的值,这样更容易阅读和理解

* 考虑if/else语句块的顺序
    注意:
    - prefer positive case first instead of negative
    - prefer simple case first to get it out of the way
    - prefer more interesting or conspicuous case first

    e.g.例外
    if not file:
       # log the error ...
    else:
       # ...
* 条件运算符(conditional expression, ?:)

time_str += (hour >= 12) ? "pm" :"am";  // Bad

if (hour >= 12) {       // Good: more clear
    time_str += "pm";
} else {
    time_str += "am";
}

key idea: 与其减少代码的行数,不如减少别人理解代码所花的时间.

return exponent >= 0 ? mantissa * (1 << exponent) : mantissa / (1 << -exponent);  // Bad

if (exponent >= 0) {     // Good
    return mantissa * (1 << exponent);
} else {
    return mantissa / (1 << -exponent);
}

* 避免do/while循环,避免goto语句
* 让函数提前退出
* 减少折叠的层数
    理由: 层数越深,别人阅读代码就越复杂,没深入/退出一层,别人需要在脑中进行入栈/出栈的操作
    方法: 当你在已有的代码上做修改时,请试图从全新的角度审视这段代码. 往回看, 把之前修改和
    现在需要做的修改当成一个整体考虑.
    技巧:
       1. 及时返回以减少嵌套的层数.
       2. 循环中用continue减少嵌套       

if (results[i] != NULL) {            // Bad
    ....
}
if (results[i] == NULL) continue;    // Good

* 其他能导致代码很难读的流程控制,需要特别注意
     1. 线程/进程/异常处理/信号量
     2. 函数指针/匿名函数/虚函数

技术分享

如何将长而大的表达式化小?(chap 8)

* 解释性变量(Explaining variables)

// Bad : too long, hard to grasp meaning
if line.split(‘:‘)[0].strip() == "root":
    ...
// Good : clear enough, understand by the variable name
username = line.split(‘:‘)[0].strip()
if username == "root":
    ...

 * 总结型变量(summary variables)

// Bad : five variables in a line
if (request.user.id == document.owner_id) {
    // user can edit this document...
}
...
if (request.user.id != document.owner_id) {
    // document is read-only...
}

// Good : easy to catch the meaning by variable name
final boolean user_owns_document = (request.user.id == document.owner_id);
if (user_owns_document) {
    // user can edit this document...
}
...
if (!user_owns_document) {
    // document is read-only...
}

* 善用德摩根定律提高条件表达式的可读性 (De morgan‘s Laws)
1) !(a || b || c) <==> (!a) && (!b) && (!c)
2) !(a && b && c) <==> (!a) || (!b) || (!c)

// Bad
if (!(file_exists && !is_protected)) Error("Sorry, could not read file.");

// Good : clear logic
if (!file_exists || is_protected) Error("Sorry, could not read file.");

 * 不要滥用短路逻辑(short-circuit logic)

// Bad : not clear
assert((!(bucket = FindBucket(key))) || !bucket->IsOccupied());

// Good : clear enough
bucket = FindBucket(key);
if (bucket != NULL) assert(!bucket->IsOccupied());

// except: 可以使用下面这种风格
if (object && object->method()) ...
x = a || b || c;

 * 简化复杂的逻辑 (方法: 反过来思考)

//集合覆盖
struct Range {
    int begin;
    int end;

    // For example, [0,5) overlaps with [3,8)
    bool OverlapsWith(Range other);
};

// Bad: hard to check , with bug
bool Range::OverlapsWith(Range other) {
    // Check if ‘begin‘ or ‘end‘ falls inside ‘other‘.
    return (begin >= other.begin && begin <= other.end) ||
        (end >= other.begin && end <= other.end);
}

// Good: clear logic , easy to check , bug free
bool Range::OverlapsWith(Range other) {
    if (other.end <= begin) return false;    // They end before we begin
    if (other.begin >= end) return false;    // They begin after we end

    return true;     // Only possibility left: they overlap
}

 * 将大的表达式分解
方法: 重复的较长的变量或语句重新定义变量表示

* 另一种新颖方法简化表达式(善用C/C++宏,不可滥用宏)

// Bad : too many, hard to check
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());
    add_to->set_status_string(add_from.status_string() + add_to->status_string());
    add_to->set_num_processes(add_from.num_processes() + add_to->num_processes());
    ...
}

// Good : easy to check/read
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);
    ADD_FIELD(status_string);
    ADD_FIELD(num_processes);
    ...
    #undef ADD_FIELD
}

 

 

 




读书笔记之《The Art of Readable Code》Part 2

原文:http://www.cnblogs.com/xianzhon/p/6291322.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!