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

《Clean Code》读书笔记之一

2017-04-04 15:19 169 查看

写在前面

很多时候,写代码我们更多追求的是更快地完成任务,而往往会忽视掉很重要的一样东西–代码整洁性。本着提高代码质量的目的,我决定阅读《Clean Code》(中文译名:代码整洁之道)一书,并对阅读过的内容做点整理写成博客,以便未来的回看和复习,也希望能与各位分享此书的技巧。

第一章 整洁代码

第一章主要讲述好代码是什么和学习写出整洁代码的重要性。

阅读本书的目标:能说出好代码和坏代码的差异,学会写出好代码的同时也能将坏代码转化成好代码。

阅读本书的原因:代码是永远都不可能被抛弃的,有些人以为随着技术的提升,很多程序都可以通过规约来自动生成代码,但这种规约依旧还是要通过程序员写代码 实现啊。因而学习写出好的代码永远不会有错。混乱的设计有时会带来可怕的灾难,它会一步一步蚕食我们的生产力,直到最终降为零,这是一个恶性循环的过程,早期为了加快生产力团队没有从整体上考虑软件的代码架构以及细节处的种种问题,只想着快速实现需求,没错,这种做法在早期的时候很有效,但是到了开发的中后期,随着系统复杂度的提高以及加入的功能特性越来越多,系统团队对于代码的掌控力下降的会越来越快,即使妄图通过增加人力来提高生产力也帮助不大,反而会加快生产力下降的过程,因为新来的人员不了解系统的设计意图以及写出哪些才能符合系统的整体原则,这只会增加代码的混乱度,直到最后代码变得不再可以管理和添加新特性。制造混乱代码是使一个软件系统最终走向灭亡的一个导火线。

第二章 有意义的命名

第二章是对命名规范的总结,主要是以下11点:

1. 名副其实,写出的代码应该能让读者了解大部分的意图,如果还需要通过注释来补充就不算是名副其实,比如下面的这段代码:

public List<int[]> getThem(){
List<int[]> list1 = new ArrayList<>();
for(int[] x:theList){
if(x[0]==4){
list1.add(x);
}
}
return list1;
}


从代码的缩进和空格方面看代码是没问题,但我们并不能从这段代码中看出其意图。上述代码可能要求我们需要了解如下四个问题的答案:

- theList是什么类型的东西?

- theList零下标表示什么意思?

- 值4的意义是什么?

- 返回的列表可以做什么?

问题显而易见,代码没有体现我们所需要了解的东西。比方说我们现在在开发一款扫雷游戏,盘面是名为theList的单元格列表,可将theList改名为gameBoard,盘面上每个单元格都用一个简单数组表示,零下标条目是一种状态值表示“已标记”,只要改为有意义的名称,代码就会得到相当程度的改进。其中我们用自定义类Cell来表示单元格比起用int数组会更加明晰。

public List<Cell> getFlaggedCells(){
List<Cell> flaggedCells = new ArrayList<>();
for(Cell cell:gameBoard){
if(cell.isFlagged()){
flaggedCells.add(cell);
}
}
return flaggedCells;
}


因而命名要做到名副其实。

2. 避免误导

避免使用一些专用名词或者一些对程序员有特殊意义的词汇来构造变量名。比如说,我们想要用accountList来表示一组账号,对于程序员来说就可能会判断这个是一个List类型的,而如果accountList实际上并非是个List的话,就会引起错误的判断,因而用AccountGroup或bunchOfAccounts会更好。

3. 做有意义的区分

如果缺少明确规定,变量moneyAmount和money没区别,customerInfo于customer没区别,要区分名称,就要以读者能鉴别不同之处的方式来区分。

4. 使用读的出来的名称

试想一下在一家公司中,有个程序里面写了这样一个类genymdhms(表示生成日期,年,月,日,时,分,秒),如果照着自创单词照读听起来就很奇怪,特别是在讨论代码的时候,因此这里的类我们可以命名为generationTimestamp,这样的单词短语不仅容易理解也好读。

5. 使用可搜索的名称

大部分情况下,我们需要查找某个变量或常量,如果我们的名称是单字母或数字常量就很难找到。因此单字母名称仅适用于短方法中的本地变量,而不适用于长方法或全局变量,若变量或常量在代码中多处使用,则应赋予其可搜索的名称,例如用WORD_NUM表示数字5。

6. 避免使用编码

在以前,由于编译器不会对类型进行检查,程序员需要通过匈牙利语标记法( 变量名以表明该变量数据类型的小写字母开始)来帮助自己记住类型,而现在编程环境强大到在编译前就能检查出类型错误,因此这种命名方式显得很多余。另外也不需要使用m_前缀来标志成员变量,应当把类和成员做的足够小,消除对成员前缀的需要。接口一般也不需要加I前缀,如果接口和实现中必须选一个来编码的话,选择实现进行编码要好的多。比如一个抽象工厂是一个接口,应命名为ShapFactory而不是IShareFactory,而ShapeFactoryImpl可以用来表示接口的实现。

7. 避免思维映射

不应当让读者在脑中把你的名称翻译为他们熟知的名称。这种问题经常出现在选择是使用问题领域术语还是解决方案领域术语时。

8. 不要耍宝

不要让读者去猜测名称的含义,应该给定明确的名称。例如不要用eatMyShorts()这类与文化紧密相关的笑话来表示abort()。

9. 每个概念对应一个词

不要同一个概念用多个词,比如retreive,get,fetch被用来给多个类中的同种方法命名,这种做法就不可取。

10. 类名和对象名应用名词或名词短语,如Customer,Account,而不能用动词。

11. 方法名应当是动词或动词短语,如postPayment,deletePage,属性访问器,修改器和断言应当根据其值命名,并依JavaBean加上get,set和is前缀。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息