您的位置:首页 > 编程语言

《编写可读代码的艺术》

2019-01-18 13:26 211 查看

表面层次的改进

把信息塞入名字中

使用专业的单词
不用Get,而是用Fetch、Download

为作用域更大的名字采用更长的名字

首字母缩略词和缩写
BackEndManager 缩写成BEManager,这种方式不可取。

丢掉没用的词
convertToString,不如toString

三、不会误解的名字

filter会产生误解,是挑出来还是减掉。

推荐用min、max表示极限

CART_TOO_BIG_LIMIT = 10

if(shop_cart.num_items >= CART_TOO_BIG_LIMIT){
error
}

建议改成

MAX_ITEMS_IN_CART = 10

if(shop_cart.num_items > MAX_ITEMS_IN_CART){
error
}

表示开头和结尾,并且无包含的意思。建议用first、last代替start、stop

给布尔值命名

is、has、can、should可以让布尔值变得明确。

get 轻量级访问器,只返回一个内部成员变量

涉及相对复杂的操作,如计算
computeMean(),会比getMean()要好。

size通常用作表示,直接返回一个固定的大小

如果size涉及计算,使用countSize或countElements更合适。

审美

使用一致的布局
让相似的代码看上去相似

选择一个有意义的顺序,始终一致地使用它
关于变量排序:

  • 从 最重要到最不重要排序
  • 按字母排序

把声明按块组织起来

把代码分成段落

  • 通过换行
  • 通过注释

一致的风格,比正确的风格更重要

第5章 该写什么样的注释

注释的目的是尽量帮助读者了解得和作者一样多。

什么不需要注释

阅读注释会占用阅读真实代码的时间,并且每条注释都占屏幕的空间。所以注释最好物有所值。

代码本身就能快速推断的事实就不需要写注释了。

一个好的名字比一个好的注释更重要。

记录你的思想

在代码中加入注释,记录你对代码有价值的见解

为代码中的瑕疵写注释

例如

//TODO : 采用更快的算法
  • TODO:还没有处理的事情
  • FIXME:已知的无法运行的代码
  • HACK:对一个问题不得不采用的比较粗糙的解决方案
    -XXX:危险!这里有重要的问题

给常量加注释

  • 注释解释这个常量值的效果

例如

NUM_THEADS = 8 //线程数最好是2的倍数

IMAGE_QUALITY=0.72 //使用0.72可以达到性能最优

站在读者的角度

通过注释来解答意料之中的疑问。

//这里因为什么原因,所以要用redis存储数据
redisUtils.put("xxx","xxx");

公布可能的陷阱

例如

//调用外部服务发送邮件(1分钟以后超时)
void sendEmail();

全局观注释

文件级别的注释,可以解释一个模块的代码逻辑,可以减少团队成员理解整体代码的时间。
通过这种注释,可能你不需要对新同事将一遍代码逻辑,而是直接让他看简短的文件级别的注释即可。

可以做任何能帮助读者更容易理解代码的事情。

第6章 写出言简意赅的注释

注释应当有很高的信息/空间率

避免使用不明确的代词,如it,用具体的词代替,如data

//不同的优先级,取决于我们是否爬取

不如

//未爬取的网页给更高的优先级

用输入/输出例子来说明特别的情况。实例要选择具有代表性的,不要选模棱两可的。

//例子:Strip("abba/a/ba","ab") returns "/a/"

声明代码的意图

注释不要只停留在代码层面的意思,要从更高层次解释

//逆序遍历列表

不如

//展示所有价格,从高到低

采用信息量更高的词,缩减注释

简化循环和逻辑

第7章 把控制流变得易读

条件语句中参数的顺序

if(length >= 10)

要好于

if(10 <= length)
while(byte_recived < byte_expected)//更好

while(byte_expected > byte_received)

原则

比较的左侧:被问询的表达式,值更倾向于不断变化
比较的右侧:用来做比较的表示,更倾向于常量

if/else语句块的顺序

if(a==b){
//case one...
}else{
//case two

}

if(a !=b){
//case two
}else{
//case one
}

这两者孰优孰劣

原则:
优先处理正逻辑,而不是负逻辑。用if(debug)而不是if(!debug)
先处理简单的情况。
先处理有趣的或者可疑的情况。

这就好比有人说“不要去想一头粉红色的大象”,“不要“容易被”粉红色的大象“淹没。

当然如果负逻辑更简单、更有趣或更危险,可以先处理它。要根据具体情况来。

避免使用三目运算符,因为一个思想是:

相对于追求最小化代码行数,一个更好的度量方法,是最小化人们理解它所需的时间。

避免do/while循环

逻辑条件应该出现在它所保护的代码之前。

大多数的do、while都可以写成while循环。

while(){
if(xxxx){
break;
}

}

从函数提前返回,没有问题,而且常常很受欢迎

最小化嵌套
嵌套很深的代码,难以理解

if(user_result == SUCCESS){
if(permission_result != SUCCESS){
...
...
...
}
}else{
....
}

上面的代码很不好。要如何改呢

可以通过提早返回来减少嵌套

if(user_result == SUCCESS){
return ..
}

if(permission_result != SUCCESS){

return ..
}

return ...

减少循环内的嵌套

for(int i = 0;i<result.size();i++){

if(...){

if(....){
....
}

}

}

可以使用continue来减少嵌套

for(int i = 0;i<result.size();i++){

if(result == null){
contitue;
}

if(....){
....
}

}

你能理解执行的流程吗

不要在代码中使用 线程、信号量、异常的比例太高。容易让程序流程变得难读。

第八章 拆分超长的表达式

代码越长就越难理解。

用作解释的变量

if line.split(':')[0].strip() == "root":
...

不如替换成

username = line.split(':')[0].strip()
if username == 'root'

总结变量

if(request.user.id == document.owner_id){
...
}

if(request.user.id != document.owner_id){
...
}

将条件提取出来作为一个单独的变量

user_owns_document = request.user.id == document.owner_id

使用德摩根定理

(1) not( a or b or c) 等价于 (not a) and (not b) and (not c)
(2)not (a and b and c) 等价于(not a) or (not b) or (not c)

例子

if(!(file_exists && !is_protected)) ...

改成

if(!file_exists || is_protected) ...

滥用短路逻辑,在很多逻辑中布尔操作都会做短路计算。

一个滥用的例子,相对让人难理解

asset((!(bucket = FindBucket(key))) || !bucket -> IsOccupied());

应改为

bucket = FindBucket(key);
if(bucket != NULL) assert( !bucket -> IsOccupied())

与复杂的逻辑战斗

如果逻辑过于复杂,容易滋生Bug

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: