前言

​ 细节决定成败。

​ 习艺之要有二:知和行,学而用。整洁代码,需要自行实践,体验自己的失败。观测他人的实践与失败。阅读代码–大量代码。代码好在什么地方,坏在什么地方。

第一章、整洁代码

​ 2个原因:第一,你是个程序员;第二,你想成为更好的程序员。

1.1 要有代码

​ 代码呈现了需求的细节。细节无法被忽略或抽象。代码确然是我们最终用来表达需求的那种语言。我们可以创造帮助把需求解析和汇整为正式结构的各种工具。但是我们无法抛弃必要的精确性,所以代码用存。

1.2 糟糕的代码

​ 沼泽(wading)。我们趟过代码的水域,我们穿过灌木密布、瀑布暗藏的沼泽地。我们拼命的想寻找出路,期望有什么线索能启发我们到底发生了什么事:但目光所及,只是越来越多死气沉沉的代码。

​ 勒布朗法则:稍后等于永不(Later equals never)。

1.3 混乱的代价

​ 对代码的每次修改都影响到其他两到三处代码,修改无小事。

1.3.1 新设计

​ 当旧系统无法在开发时。就会开发全新的设计。会诞生两两个团队,新团队开发一套新系统,必须实现旧系统的所有功能,另外,还得跟上对旧系统的持续改动。在新系统的功能可以抗衡旧系统时管理层是不会换掉旧系统的。

1.3.2 态度

​ 用户指望我们验证需求是否都在系统中实现。项目经理指望我们遵守进度。我们与项目的规划脱不了干系,对失败有极大责任;医生对病人做手术之前都会洗手。程序员遵从了不了解混乱风险的经理的意愿,是不专业的做法。

1.3.3 谜题

​ 谜题:开发者背负期限的压力,只好制造混乱。但是这个谜题说错了,制造混乱无助于赶上期限,只会立刻拖慢你。赶上期限的唯一方法,始终尽可能保持代码清洁

1.3.4 整洁代码的艺术

​ 代码就像绘画。多数人知道一幅画是好还是坏,但不代表会会绘画。整洁代码,需要遵循大量的小技巧,贯彻刻苦习得的“整洁感”。

​ 缺乏“代码感”的程序员,看混乱是混乱,无处着手。有“代码感”的程序员能从混乱中看出其他的可能与变化。“代码感”帮助程序员选出最好的方案,并指导程序员制订修改行动计划,按图索骥。

1.3.5 什么是整洁代码

1
我喜欢优雅和高效的代码。代码逻辑应当直截了当,叫缺陷难以隐藏;尽量减少依赖关系,使之便于维护;依据某种分层战略完善错误处理代码;性能调至最优,省得引诱别人做没规矩的优化,搞出一堆混乱来。整洁的代码只做好一件事。Bjarne

​ C++语言的发明者Bjarne认为整洁代码读起来令人愉悦。

​ 破窗理论:窗户破损了的建筑让人觉得似乎无人照管。于是别人也不在关心。放任窗户继续破损。最终自己也参加破坏活动。

​ Bjarne:整洁的代码只做好一件事。每个函数、每个类和每个模块都全神贯注于一事。

1
整洁的代码简单直接。整洁的代码如同优美的散文。整洁的代码从不隐藏设计者的意图,充满了干净利落的抽象和直截了当的控制语句。Grady(面向对象分析与设计作者)

​ Grady,整洁的代码如同优美的散文。

1
2
3
4
5
6
7
8
9
10
11
12
近年来,我开始研究贝克的简单代码规则,差不多也都琢磨透了。简单代码,依其重要顺序:
能通过所有测试;
没有重复代码;
体现系统中的全部设计理念;
包括尽量少的实体,比如类、方法、函数等。
在以上诸项中,我最在意代码重复。如果同一段代码反复出现,就表示某种想法未在代码中得到良好的体现。我尽力去找出到底那是什么,然后再尽力更清晰地表达出来。
在我看来,有意义的命名是体现表达力的一种方式,我往往会修改好几次才会定下名字来。借助Eclipse这样的现代编码工具,重命名代价极低,所以我无所顾忌。然而,表达力还不只体现在命名上。我也会检查对象或方法是否想做的事太多。如果对象功能太多,最好是切分为两个或多个对象。如果方法功能太多,我总是使用抽取手段(Extract Method)重构之,从而得到一个能较为清晰地说明自身功能的方法,以及另外数个说明如何实现这些功能的方法。
消除重复和提高表达力让我在整洁代码方面获益良多,只要铭记这两点,改进脏代码时就会大有不同。不过,我时常关注的另一规则就不太好解释了。
这么多年下来,我发现所有程序都由极为相似的元素构成。例如“在集合中查找某物”。不管是雇员记录数据库还是名-值对哈希表,或者某类条目的数组,我们都会发现自己想要从集合中找到某一特定条目。一旦出现这种情况,我通常会把实现手段封装到更抽象的方法或类中。这样做好处多多。
可以先用某种简单的手段,比如哈希表来实现这一功能,由于对搜索功能的引用指向了我那个小小的抽象,就能随需应变,修改实现手段。这样就既能快速前进,又能为未来的修改预留余地。
另外,该集合抽象常常提醒我留意“真正”在发生的事,避免随意实现集合行为,因为我真正需要的不过是某种简单的查找手段。
减少重复代码,提高表达力,提早构建简单抽象。这就是我写整洁代码的方法。Ron(极限编程实施)

​ Ron:不要重复代码,只做一件事,表达力,小规模抽象,该有的都有了。

1.4 思想流派

​ 武术家从不认同所谓的最好武术。别认为我们是”正确的“。

1.5 我们是作者

​ 我们写代码时,我们是作者,要为评判我工作的读者写代码。写新代码时,我们一直在读旧代码。编写代码的难度,取决于读周边代码的难度,要想干的快,要想早点做完,要想轻松写代码,先让代码易读吧。

1.6 童子军军规

​ 把代码写好还不够。必须时时保持代码整洁。童子军军规:让营地比你来时干净。

1.7 前传与原则

​ 本书中会发现对不同设计原则的引用,包括单一权责、开放闭合原则和依赖倒置原则等。

1.8 小结

​ 艺术家并不能保证你读过之后能成为艺术家,只能告诉你其他艺术家用过的工具、技术和思维过程。本书只能展示好程序员的思维过程,还有他们使用的技巧、技术和工具。

​ 和艺术书一样,本书充满了细节。你会看到启发、规条和技巧的列表。最终的结果取决于你。

第二章、有意义的命名

2.1 介绍

​ 软件中随处可见命名。有如此多的命名要做,不妨做好它。

2.2 名副其实

​ 遍历函数或类的名称已经答复了所有问题。如果名称需要注释,就不是名副其实。

2.3 避免误导

​ 避免使用与本意相悖的词。accountList 除非真的是list,否则accountGroup

2.4 做有意义的区分

​ 如果知识为满足编译期或解释器的需要写代码,就会制造麻烦。例如,同一作用域内的2样东西不能重名,你可能会随手改掉其中一个名称。(a1,a2,a3)

2.5 使用能读得出来的名称

2.6 使用可搜索的名称

​ 单字母名称和数字常量,很难在一大篇文字中找出。搜的到的名称胜于自造编码的名称。名称的长短应与其作用域大学相对应。若变量或常量可能在多处使用,则应赋予便于搜索的名称。

2.7 避免使用编码

2.7.1 匈牙利语标记法

2.7.2 成员前缀

​ 不必用m_前缀来表明成员变量,应该吧类和函数做的足够小,消除对成员前缀的需要。

2.7.3 接口和实现

​ 怎么命名接口和实现?不加修饰的接口,然后对实现类加Imp

2.8 避免思维映射

​ 不要让读者在脑中把你的名称翻译为他们熟知的名称。单变量作用域就是这个问题。在作用域较小、也没有名称冲突时,计数器可能为i、j、k,这不是个好选择,读者必须把它映射为真实概念。

2.9 类名

​ 类名和对象名应该是名词或名词短语。

2.10 方法名

​ 方法名应该是动词或动词短语。get、set、is。

2.11 别扮可爱

​ 如果名称太可爱,只有可作者一样的人才能记住。

2.12 每个概念对应一个词