杂谈:《编写可读代码的艺术》阅读笔记(二)
一、流程控制
1. 判断
1)条件判断中的参数顺序
| 比较的左侧 | 比较的右侧 |
|---|---|
| “被问询的”表达式,更倾向于不断变化 | 用来做比较的表达式,它的值更倾向于常量 |
PS:但是反着写,能够避免掉那种if(obj = NULL)的错误,俗称“尤达表示法”。
2)if/else 语句块的顺序
三个倾向性:
- 倾向于先处理正逻辑,再处理负逻辑
- 倾向于先处理掉简单情况
- 倾向于先处理掉有趣的或者可疑的状况
3)?:条件表达式
- 并不是很推荐这种写法哈哈哈哈,一旦写了长表达式,就会很难理解
2. 循环
1)避免使用 do/while 循环
通常,逻辑条件应该出现在它们所“保护”的代码前。而且do/while循环中的continue会产生歧义。
2)最小化嵌套
深嵌套会让读者的“思维栈”太深,可以通过提早返回来减少嵌套,可以将代码进行如下变化:
js
if (a) {
if (b) {
// do something 1
return;
}
// do something 2
}
// do something 3
return;js
if (!a) {
// do something 3
return;
}
if (b) {
// do something 1
return;
}
// do something 2
return;二、长表达式拆分
方法一:增加变量:总结为一句话,用额外的变量,来代替一个长表达式,例子:
js// 解释变量 if (line.split(":")[0].strip() == "root") { // ... } // ************************************** // ↓ // ************************************** var userName = line.split(":")[0].strip(); if (username == "root") { // ... }js// 总结变量 if (request.user.id == document.owner_id) { // ... } // ... if (request.user.id != document.owner_id) { // ... } // *********************************************************** // ↓ // ************************************************************ var user_owns_document = request.user.id == document.owner_id; if (user_owns_document) { // ... } if (!user_owns_document) { // ... }方法二:使用德摩根定律
- !(a || b || c) <=> (!a) && (!b) && (!c)
- !(a && b && c) <=> (!a) || (!b) || (!c)
方法三:不要滥用短路逻辑:短路逻辑可能会增加代码的理解难度。
方法四:找到更优雅的方式,一个理念是:
开始还很简单的问题变得非常令人费解,通常预示着一中更简单的方法。
方法五:拆分巨大的语句,把一样的表达式抽离出来作为函数开头的总结变量
- DRY:Don't Repeat Yourself.
三、变量
关于变量的三个问题:
- 变量越多,就越难全部追踪
- 变量作用域越大,就需要跟踪的越久
- 变量改变越频繁,就越难追踪它的当前值
1)减少变量
针对第一个问题,我们提出了以下几种方案,可以去掉以下几种不必要的变量:
没有价值的临时变量:举个例子:
now = datetime.datetime.now(),一般这种变量有以下几种特点,- 没有拆分任何临时变量
- 没有做过多澄清,
datetime.now()已经足够清晰 - 只用一次(或少数几次),没有压缩任何冗余的代码
中间结果:下面例子中,
index_to_remove可以被移除,那些为了保存临时结果,用完即丢的变量,可以考虑丢弃:
js
var remove_one = function (array, value_to_remove) {
var index_to_remove = null;
for (var i = 0; i < array.length; i++) {
if (array[i] == value_to_remove) {
index_to_remove = i;
break;
}
}
if (index_to_remove !== null) {
array.splice(index_to_remove, 1);
}
};
// ***********************************************
// ↓
// ***********************************************
var remove_one = function (array, value_to_remove) {
var index_to_remove = null;
for (var i = 0; i < array.length; i++) {
if (array[i] == value_to_remove) {
array.splice(i, 1);
return;
}
}
};- 流程控制变量:用来控制流程的变量,往往不包含任何程序内的数据,能通过结构化编程来消除。
2)缩小变量作用域
让你的变量对尽量少的代码行可见。
一个做法就是让变量“降级”,尽量降低作用域,比如
- 让类成员变量降级成某个成员函数中的局部变量
- 运用好
C++的块级作用域,那些仅仅用来当做判断条件的变量,可以放在if语句中定义:
cPaymentInfo* info = database.ReadPaymentInfo() if(info){ // ... } // ************************************************ // ↓ // ************************************************ if(PaymentInfo* info = database.ReadPaymentInfo()){ // ... }- 用
JavaScript的立即执行函数制造封闭的作用域
定义下移:将定义移动到使用它之前,增加可读性
3)只写一次的变量更好
尽量减少对变量的赋值的语句,有助于提高可读性。