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

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

if (length >= 10)    // Good
if (10 <= length)    // Badwhile (bytes_received < bytes_expected)  // Good
while (bytes_expected < bytes_received)  // Badif (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";  // Badif (hour >= 12) {       // Good: more cleartime_str += "pm";
} else {time_str += "am";
}

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

return exponent >= 0 ? mantissa * (1 << exponent) : mantissa / (1 << -exponent);  // Badif (exponent >= 0) {     // Goodreturn 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 beginif (other.begin >= end) return false;    // They begin after we endreturn 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
}

如何善用变量提高代码的可读性?(chap 9)

* 变量带来的问题
1. 变量越多,越难跟踪它们
2. 变量的作用域越大, 需要跟踪越久
3. 变量的值改变越多, 越难跟踪他的当前值

* 减少变量(与之前的explaining/summary变量不矛盾,这里减少不必要的变量)
* 省去无用的临时变量

// Bad
now = datetime.datetime.now()
root_message.last_view_time = now// Good
root_message.last_view_time = datetime.datetime.now()

理由:
  1. now的引入并没有分解一个复杂的表达式
  2. datetime.datetime.now()本身已经很清楚
  3. now只用了一次, 并没有解决冗余代码  
key: 这种类型的变量("leftovers"),往往保存一个临时结果,可以通过立即处理临时结果来省掉它们.
 (complete the task as quickly as possible)

// Bad
var remove_one = function (array, value_to_remove) {var index_to_remove = null;for (var i = 0; i < array.length; i += 1) {if (array[i] === value_to_remove) {index_to_remove = i;break;}}if (index_to_remove !== null) {array.splice(index_to_remove, 1);}
};// Good
var remove_one = function (array, value_to_remove) {for (var i = 0; i < array.length; i += 1) {if (array[i] === value_to_remove) {array.splice(i, 1);  // process immediatelyreturn;}}
};

* 省去流程控制变量(Control flow variable)

// Bad : 不必要的变量
boolean done = false;
while (/* condition */ && !done) {...
}
if (...) {done = true;continue;
}// Good : 这类流程控制变量都可以通过if-break/continue来做到
while (/* condition */) {...if (...) {break;}
}

* 缩短变量的作用域
key: 减少变量的可见范围,越少越好.
原因: 通过减少变量的可见范围,读者阅读代码时需要记住的变量就越少.

* C++中的if-语句的作用域

// Bad
PaymentInfo* info = database.ReadPaymentInfo();
if (info) {cout << "User paid: " << info->amount() << endl;
}
// Many more lines of code below ...// Good : 用户看完之后就不需要关心info了
if (PaymentInfo* info = database.ReadPaymentInfo()) {cout << "User paid: " << info->amount() << endl;
}

* 在js中使用"私有"变量
* 在js中使用var来定义局部变量

* 将声明下移(移到使用变量的附近)

// Bad
def ViewFilteredReplies(original_id):filtered_replies = []root_message = Messages.objects.get(original_id)all_replies = Messages.objects.select(root_id=original_id)root_message.view_count += 1root_message.last_view_time = datetime.datetime.now()root_message.save()for reply in all_replies:if reply.spam_votes <= MAX_SPAM_VOTES:filtered_replies.append(reply)return filtered_replies// Good : 变量的声明以及使用都聚集在一块了
def ViewFilteredReplies(original_id):root_message = Messages.objects.get(original_id)root_message.view_count += 1root_message.last_view_time = datetime.datetime.now()root_message.save()all_replies = Messages.objects.select(root_id=original_id)filtered_replies = []for reply in all_replies:if reply.spam_votes <= MAX_SPAM_VOTES:filtered_replies.append(reply)return filtered_replies

* 倾向于一次写入的变量(常量,Write-once variable)
C++中的const, java中的final. 常量不容易带来问题

static const int NUM_THREADS = 10;

转载于:https://www.cnblogs.com/xianzhon/p/6291322.html

读书笔记之《The Art of Readable Code》Part 2相关推荐

  1. 《The Art of Readable Code》 读书笔记 01

    放假前在学校图书馆借了一本新书<The Art of Readable Code>,寒假回来看看,写写其中的Key Idea .summary和一些读书笔记. Preface 前言部分主要 ...

  2. 《The Art of Readable Code》学习笔记(一)

    放寒假回家有些颓废,就是不想看书.但是已经大三了,春节过后就要找实习了.哎,快乐的大学生活终于要过去了. 先从简单的书看起吧!在图书馆借了本<The Art of Readable Code&g ...

  3. 晒书有礼!《编写可读代码的艺术》(The Art of Readable Code)晒书有礼活动进行中

    值得所有程序员收藏的好书<编写可读代码的艺术>热卖! 为答谢各位读者的关注和支持,华章公司特举办该书的"晒书有礼"活动! 活动时间:2012年7月23日~2012年8月 ...

  4. 晒书有礼!《编写可读代码的艺术》(The Art of Readable Code)晒书有礼活动进行中...

    值得所有程序员收藏的好书<编写可读代码的艺术>热卖! 为答谢各位读者的关注和支持,华章公司特举办该书的"晒书有礼"活动! 活动时间:2012年7月23日~2012年8月 ...

  5. 《编写可读代码的艺术》读书笔记

    2019独角兽企业重金招聘Python工程师标准>>> 最近常常来这个网站看看源码,看看博客,觉得只是从中获益,却没有做出自己的一些贡献,最近正好在读<The Art of R ...

  6. Code in C# and build 3D games with Unity读书笔记

    Code in C# and build 3D games with Unity读书笔记 变量 •从概念上讲,变量是编程的最基本单位,就好比原子,一切都基于变量,没有变量,程序就可能存在. •从技术角 ...

  7. 《编码:隐匿在计算机软硬件背后的语言(Code:The Hidden Language of Computer Hardware and Software)》读书笔记

    声明 该文章是阅读<编码:隐匿在计算机软硬件背后的语言>一书之后整理出的读书笔记.若有错误,还需继续修正与增删. Preface 作者Charles Petzold是Windows编程界的 ...

  8. 《代码整洁之道 clean code》 读书笔记(上篇)

    <代码整洁之道 clean code> 读书笔记(上篇) 这本书我准备用较快的时间来读一下,简单记录一下自己的一些读完的感悟,因为更多地编码技巧还是需要在实际编程和读源码的过程中进行锤炼. ...

  9. Code Clean读书笔记

    代码整洁之道读书笔记 by fangpc 序言部分 "神在细节之中" - 建筑师路德维希 5S哲学(精益) 整理(Seiri):搞清楚事物之所在--通过恰当地命名之类的手段--至关 ...

最新文章

  1. python学习笔记(生成xml)
  2. step3 . day7数据结构之二叉顺序数的创建和二叉树的栈形式遍历
  3. Dapper的正确使用姿势
  4. 谷歌发布最新版安卓Android,谷歌正式除名华为,安卓12华为首发无望,但鸿蒙将迎难顶上!...
  5. batchplot插件用法_Batchplot怎么安装及使用?Batchplot的安装方法及使用方法介绍
  6. enum java 比较_Kotlin与Java比较:枚举类
  7. 【C++】std::是什么?
  8. 概率论与数理统计基础
  9. 【OSPF基础(链路状态路由协议、ospf基础术语、ospf协议报文类型、ospf三大表项、邻居和邻接关系、ospf网络类型、DR与BDR、ospf基本配置)】-20211210、13、14
  10. 传统推荐模型——协同过滤
  11. 图纸上标注的是实际尺寸吗_尺寸数字应该标注图纸上所画实际长度。
  12. Python:实现simpson rule辛普森法则算法(附完整源码)
  13. 免手机验证码网站备案
  14. 快手第三季营收231亿:同比增13% 期内亏损27亿
  15. Python 量化分析——基本面选股模型
  16. (灵魂拷问)MySQL数据库高频面试题,助你脱颖而出
  17. python处理颜色rgb_python – 根据RGB值更改图像的颜色
  18. Pure-ftpd + Mysql + Pureftpd php manager架设FTP 傻子的执著
  19. 摄影后期软件darktable介绍、汉化、使用说明(Lightroom免费替代品)
  20. AF染料试剂Alexa fluor 680 PEG Biotin,AF680 PEG Biotin,荧光强度稳定利于多种荧光标记

热门文章

  1. python左移右移位运算_Python这些位运算的妙用,绝对让你大开眼界
  2. python def函数报错详解_Python函数详解
  3. mysql版本 hibernate_Mysql 不同版本 说明
  4. 【sklearn学习】决策树、分类树、剪枝策略
  5. CF--思维练习--CodeForces - 220C Little Elephant and Shifts (STL模拟)
  6. canal mysql 数据同步
  7. 玩转u-boot之【初探环境变量env/bootcmd/bootargs】
  8. 玩转GIT系列之【如何恢复windows系统下git的状态图标显示】
  9. rsync实现文件同步
  10. Cyclone II FPGA系列简介(备忘)