会说话的代码——书写自表达代码之道

会说话的代码——书写自表达代码之道

王洪亮 著

ISBN 978-7-121-20876-8

2013年8月出版

定价:45.00元

204页

16开

内容提要

写得不好的代码有各种各样的问题,会给读者带来不好的阅读体验,并且如果代码写得不够好,文档和代码不一致,注释和代码不一致,那么对维护人员来说,理解代码和进入项目组都是有困难的。如果代码写得不够好,就需要扩展功能,修改Bug时所需要花费的时间也较长。

自表达代码是一种采用接近于自然语言的方式书写代码的主张。

代码可读性、可扩展性、可测试性是关联代码质量的重要参考指标。本书从各个角度来分析产生劣质代码的原因,并从代码的命名、注释、风格、结构、架构等方面着手,对提高设计能力、熟悉开发环境、了解编程语言、提高英语能力等诸多方面提出了具体的改善建议。

目录

第1章  劣质代码带来的劣质体验     1

1.1  代码的可读性问题        1

1.1.1  命名类问题         2

1.1.2  注释类问题         6

1.1.3  风格类问题         8

1.1.4  结构类问题         11

1.1.5  架构类问题         18

1.2  代码的可测试性问题   22

1.3  代码的可维护性问题   22

1.3.1  需求变更难以应对    23

1.3.2  纠缠不清的Bug 23

第2章  劣质代码是怎么产生的          25

2.1  理论知识匮乏        25

2.2  对编程语言不熟悉        29

2.3  对开发环境不熟悉        31

2.4  对设计方法不了解        32

2.5  编程习惯不佳        32

2.6  英语能力不足        35

2.7  管理人员误导        36

第3章  自表达代码     39

第4章  理论知识的补充     41

4.1  面向对象的基础知识   41

4.1.1  封装    41

4.1.2  继承    42

4.1.3  多态    44

4.2  设计的基本原则   45

4.2.1  单一职责原则    45

4.2.2  开放封闭原则    46

4.2.3  里氏代换原则    48

4.2.4  接口分离原则    48

4.2.5  依赖倒置原则    49

4.2.6  迪米特法则         50

4.2.7  不要重复你自己         51

4.3  圈复杂度        52

第5章  编程环境的熟悉     53

5.1  保存动作与自动格式化        53

5.2  快速修复        58

5.2.1  缺少类         59

5.2.2  缺少方法    60

5.2.3  缺少变量    61

5.2.4  类型不匹配         62

5.3  重构        63

5.3.1  改名    64

5.3.2  改变方法签名    68

5.3.3  提取方法    69

5.3.4  移动    73

5.3.5  引入参数对象    76

5.3.6  引入接口    77

5.3.7  向上提取    78

5.3.8  提取常量    81

5.3.9  局部变量变为域变量         82

5.3.10  引入工厂  82

5.4  自动完成        83

5.5  大纲        84

5.6  Eclipse快捷键        86

第6章  编程语言的学习     88

6.1  注解        88

6.2  异常        94

6.3  反射        97

6.4  泛型        100

第7章  设计方法的学习     101

7.1  设计模式        101

7.2  依赖注入        102

7.3  Map的妙用   103

7.4  采用位掩码减少类的个数   107

7.5  List处理Z-Order   110

第8章  英文能力的提升     113

8.1  词性        113

8.2  时态        115

8.3  语法        116

8.4  否定词   117

8.5  成对词   119

8.6  近义词   120

8.7  前缀、后缀   120

8.8  缩写        122

8.9  正确用词        122

第9章  编程习惯的改进     124

9.1  命名方面的改进   124

9.1.1  命名的基本原则         124

9.1.2  包的命名    125

9.1.3  接口的命名         125

9.1.4  类的命名    125

9.1.5  注解的命名         126

9.1.6  枚举的命名         126

9.1.7  方法的命名         127

9.1.8  变量    129

9.1.9  常量的命名         130

9.1.10  相似的命名       130

9.2  注释方面的改进   131

9.2.1  JavaDoc       131

9.2.2  TODO、FIXME和XXX         132

9.2.3  其他注释    133

9.2.4  方法的注释         133

9.2.5  类的注释    133

9.2.6  版权声明    134

9.3  风格方面的改进   135

9.3.1  缩进与对齐         135

9.3.2  空格与空行         138

9.3.3  行长与换行         140

9.4  结构方面的改进   140

9.4.1  缩短长判定         140

9.4.2  缩短长分支         144

9.4.3  减少参数个数    148

9.4.4  减少嵌套的层数         150

9.4.5  去掉重复代码    152

9.4.6  分离暧昧关系    155

9.4.7  多维度变化         156

9.4.8  缩短长方法         158

9.4.9  正则表达式         158

9.4.10  自相似对象       160

9.4.11  同质化处理       161

9.5  架构方面的改进   162

9.5.1  MVC    162

9.5.2  包含关系    164

9.5.3  继承关系    164

9.5.4  包的划分    165

9.5.5  内部类、内部接口及内部枚举         166

9.5.6  匿名类         167

9.5.7  有限取值范围    168

第10章  测试代码的自表达改进       174

10.1  测试代码的可读性      175

10.2  测试代码的可维护性 179

10.3  测试代码的可扩展性 179

10.4  测试语法      180

第11章  Lambda表达式     182

11.1  filter      183

11.2  forEach 183

11.3  findAny与findFirst       184

11.4  sorted   184

11.5  uniqueElements   185

附录         186

媒体评论

推荐序

 

经典的教人写程序的书,如《Java编程思想》,类似教材的定位,由浅入深地教会新程序员写代码。充满丰富经验的《Effective Java》、《设计模式》等书,将众多的编程经验进行组织并进行深入浅出的讲解。在《Clean Code》中也描述了许多如何写干净代码的技巧和经验。

而这本《会说话的代码》,却从截然不同的视角,尝试帮助那些真正处于一线的程序员写出更容易理解的代码。写代码就像盖楼房,我们怀着美好的希望,希望所有的项目代码如同一片尚未开垦的处女地,但真实情况往往是面对拆迁房的废墟。这些令人费解的代码要么是别人留下的,要么是自己许久之前留下的,而我们的往往选择不多。

《会说话的代码》从一线角度重新描述了这些现象,并极富关怀地提出了解决方案。例如,当需要滚动鼠标滚轮或者不断拉动滚动条时,你的方法或者类是不是过长?需要不断查看方法实现时,是不是方法名无法表达实现的含义?需要画流程图才能理解某个方法的逻辑时,是不是嵌套太深?

这本书从命名、注释、结构、架构、编程风格等方面,做出了具体的阐述。其中的某些建议甚至详细到了需要用is还是can,接口要不要加I还是用-able的后缀等。文中还阐述了设计模式和面向对象的设计原则如何帮助程序员写出自描述的代码,要想理解透彻,还需要阅读相关书籍。对于尚未正式发布的Java 8,作者在第11章也进行了Lambda的介绍。

另外,我认识王洪亮已久。十多年前,当程序员新兵们还在受谭浩强的《C程序设计》“折磨”时,尚在西北工业大学的王洪亮已经在宿舍里用C++写出令人眼馋的RPG游戏。现在,他依然没有放弃一线开发。作为程序员,我心生佩服。

希望本书能够帮助程序员们写出更为直观、简洁的代码。

 

ThoughtWorks敏捷咨询顾问

陈金洲(@mechiland)

2013年2月21日

前言

自表达代码的由来

 

我们曾经阅读过很多阅读体验很糟糕的代码,其中有鼠标滚轮测试程序(指长文件、长方法)、脑筋急转弯程序(指逻辑判定复杂、关系混乱)、记忆力测验程序(指一大堆变量或者常量)、眼神测验程序(指命名类似,但意思不一样)、逻辑思维测试程序(指循环引用式包含关系),等等。这些劣质代码给我们带来各种各样的劣质阅读体验。

我们也曾经苦于一个偶然出现的Bug再也无法重现,好不容易重现,却发现其必要步骤达三十多步,重现以后却找不到问题的根本原因,也无从下手解决,铺天盖地地插入了几十条log语句后终于能够定位Bug的原因,却又不敢动手修改。十分小心地分析,慢慢地修改,改掉这个Bug之后却发现它又引起了新的Bug。

需求变更可能是令程序员最头疼的事情之一了,它引起了一个新的流程,需要分析、修改和测试。更困难的还在于,如果这个需求实现了,另外一个已经完成的功能必须被破坏掉,而用户却想鱼和熊掌兼得。

当新进入一个既有的开发项目时,常常面临代码和设计文档不一致、代码和注释不一致、代码结构混乱、代码风格不统一等问题,不得不花大量的时间来学习。面对体积庞大有效信息却很少的代码库是一件痛苦的事情,让人产生一种要推翻重写的冲动。可是开发时项目经理却总是在催促:时间很紧,放弃文档,放弃注释。

到底是什么问题导致这些痛苦的体验?为什么会产生这些痛苦的体验?如何才能避免这些痛苦的体验?本书第1章以这个为切入点,从代码的可读性、可测试性和可扩展性三方面入手,对劣质代码产生的原因进行分析,分别从命名、注释、风格、结构、架构五方面进行总结,并依次提出相应的改进方案。

“自表达代码”(Self-Expressive Code)这一名词为笔者原创。在此之前,曾经出现过“自文档代码”(Self-Documenting Code)和“自描述代码”(Self-DescribingCode)。笔者认为“自表达代码”比后面二者更具表现力。根据“代码是软件的唯一文档”这一理论,代码应该是能够自我表达的,是能够让读者看到代码就知道软件是做什么工作的,这就是自表达代码一词的由来。如其名字,让代码能够自我表达的书写方式就是自表达代码。书写自表达代码的方式应该像书写文章一样。如果代码书写出来后都像文章一样读起来朗朗上口,那么对代码的理解将不必再依靠繁杂的注释和厚厚的文档,代码本身就可以表明其作用。而维护人员也不必担心代码和文档或者注释不一致这个问题了。

比较糟糕的代码的写法如:

scene.fight(hero, enemy, Kongfu.FIST);都不知道谁打了谁。

普通方式书写的代码如:

hero.fight(enemy, Kongfu.FIST);知道代码的意思,但是阅读体验还不够好。

而自表达的方式书写的代码如:

hero.fight(enemy).with(“FIST”);如果不看那些符号,读起来这就是一句话。

本书第3章对如何采用接近自然语言的方式书写代码进行了详细阐述,并推出“自表达代码”概念。

看到条件就是if,看到循环就是for,这样“直抒胸臆”的代码堆砌起来,相互影响,使代码的复杂度变得很大。然而,形成这一问题的原因是由于缺乏理论知识,代码书写者并不了解代码的复杂度应该如何表征,耦合度应该如何降低。本书第4章就一些面向对象常用的理论知识进行讲解,以帮助程序员初步掌握这些理论知识。

当看到不少有经验的程序员也在用连续按方向键的方式对光标进行定位时,我深感对集成开发环境的不熟悉也是代码质量低劣的原因之一。对于一个提升到主菜单地位的Refactor菜单熟视无睹的程序员不乏其人。而利用Outline快速定位代码,利用Debugger工具、Task List管理技术债务等方法也是这些人同时存在的盲点。因此,本书第5章以Eclipse为例,专门就一些常用的对编程帮助很大的集成开发环境功能进行讲解。

Java 8就快推出了,然而很多程序员还被限制在只能使用Java1.4的条件下,至于中间的若干个版本有什么新特性,程序员根本就没能了解。当程序员看到采用新特性书写的更为简练的代码时,会不明白、不理解,而自己又写不出,因此错过了很多可以改进代码的机会。本书第6章就一些Java 1.5以后推出的新特性进行讲解,并对其中的一些使用技巧进行阐述,以帮助读者更好地理解这些新特性。

以往的代码类书籍都来自美国,可能由于使用英语对于美国人不算是什么问题,在这些书中很少提到英语这一话题。但是在亚洲一些国家,英语可能是程序员的一个重大障碍。由于单词量不够、语法不明确、词性不会用等原因造成很多代码书写上的问题,也带来了很多阅读上的苦恼。其实,书写代码时所需要的英语并不是多么高深,并不需要IELTS成绩达到某个分数线,只要掌握一些基本英语技巧,就可以使代码变得更加易读好懂。本书第8章从正确用词、词性、语法、时态等多个角度对英语进行浅析,以帮助程序员更好地命名。并且本书也给出了一个可用的关于前缀、后缀、成对词、近义词等的列表,成为书写自表达代码技巧的有益补充。

书写代码不是一种体力劳动,而是一种脑力劳动。把书写代码当成体力劳动就难以确保程序员的水平提升,也难以确保软件的质量可靠,更逞论代码的可读性、可测试性乃至可扩展性。书写代码也不仅是个技术工作,更是一个艺术工作,在代码的书写过程中需要不断地调整和修饰,不是把代码写得简练些就够了。代码应该能够让读者快速阅读,能够很容易地进行测试,很容易地进行扩展。本书第9章就如何培养良好的编程习惯进行讲解。

形而上学的规章制度并不能够促成高质量代码的书写,编码的规范也应该与时俱进,管理者也应该随时抛弃那些陈旧的做法和规则。任何一个好方法的应用都离不开管理者的支持。本书就劣质代码产生的管理层面原因进行了分析和总结。但是如何提升管理水平是个庞大的话题,由于它不是本书的主要讨论话题,所以本书对此部分割爱。

作为下一代语言的特性,Lambda表达式已经被加入到若干高级编程语言中去了。但是Java还没有加入Lambda表达式,Java 8已经声明要加入Lamda表达式了,本书第11章通过对Java 8的前瞻版进行体验,以了解Java中Lambda表达式的特性。

愿本书能够为读者带来有益的帮助。

王洪亮

2013年4月

于北京

posted @ 2013-07-15 10:34  博文视点(北京)官方博客  阅读(356)  评论(0编辑  收藏  举报