我们都曾经瞟一眼自己亲手造成的混乱,决定弃之于不顾,走向新的一天。
我们都曾经说过有朝一日要回头清理。
当然,那是我们都没听过勒布朗法则:稍后等于永不(Later equals never)。
-
随着混乱的增加,团队的生产力不断下降,趋向于零。
假如你是位医生,病人请求你在给他做手术前别洗手,因为那会花太多时间,你会照做吗? -
整洁的代码只做好一件事,糟糕的代码想做太多事。
每个函数每个类每个模块都应全神贯注于一事,完全不受四周细节的干扰和污染。
简单直接,又如有没得散文,不隐藏意图,充满了干净利落的抽象和直接了当的控制语句。 -
简单代码规则
- 能通过所有的测试
- 没有重复代码
- 体现系统中的全部设计理念
- 包括尽量少的实体,包括类、方法、函数等
-
消除重复和提高表达力让我在整洁代码方面受益良多。
-
读与写的比例超过10:1
写新代码时,我们一直在读旧代码
取个好名字的规则
- 名副其实,见名知意
a. 使用有意义的命名 int d -> int daysSinceCreate - 避免误导
a. 不用已有的名称如 accountList,除非确实是List类型 - 做有意义的区分
a. productInfo/productData 等,而a可用于域内变量,the用于函数参数
b. 冗余命名,如NameString,CustomerObject等 - 使用读得出来的名字
- 使用可搜索的名称
- 避免使用编码
a. 匈牙利语标记法 要求首字母体现出类型,不推荐使用
b. 不需使用成员前缀 - 避免思维映射
- 类名和对象应该是名词或名词短语,不应当是动词
- 方法名应该是动词或动词短语
- 别扮可爱,宁为明确,勿为好玩
- 每个概念对应一个词,并且一以贯之
- 别用双关语
- 使用解决方案领域名称
- 使用源自所涉问题领域的名称
- 添加有意义的语境
a. 添加名字前缀
b. 更好的方案是创建相关类 - 不要添加没用的语境(前缀)
函数的规则
- 函数的第一规则是短小,第二规则是还要更短小
a. 函数以20行封顶最佳。 - 函数应该做一件事,做好一件事,只做一件事
- 每个函数一个抽象层级
a. 让代码拥有自顶向下的阅读顺序
b. 每个函数后面都跟着位于下一抽象层级的函数。 - switch使用多态替换
- 使用描述性名称
a. 别害怕长名称
b. 别害怕花时间取名字
c. 命名方式要保持一致 - 函数参数避免出现三个及以上
a. 出现则需要考虑将其封装为类了 - 无副作用
a. 副作用是一种谎言,函数承诺只做一件事,却做了其它事
b. 有时会对自己类中的变量做出未能语气的改动
c. 有时把变量搞成向函数传递的参数或是系统全局变量
d. 这将具有破坏性,导致时序性耦合或顺序依赖
e. 普遍而言,应该避免使用输出参数,可换为修改所属对象的状态 - 使用异常替代错误返回码
a. 抽离Try/Catch代码块,形成一个单独函数
b. 新异常可以从异常类派生出来,无需重新编译或重新部署 - 避免重复
- 别重复自己
a. 重复可能是软件中一切邪恶的根源
b. 自程序发明以来,软件开发领域的所有创新都是在不断尝试从源代码中消灭重复 - 结构化编程
a. Dijkstra认为,每个函数、函数中的每个代码块都应该只有一个入口,一个出口(单入单出)
b. 对于大函数很有用,对于小函数反而缺少表达力
c. 所以要尽量保持函数短小 - 如何写出这样的函数
写代码和写别的东西很像。在写论文或文章时,你先想什么就写什么,然后再打磨它。
a. 初稿也许粗陋无序,你就斟酌推敲,直至达到你心目中的样子。
b. 我写函数时,一开始都冗长而复杂。有太多缩进和嵌套循环。有过长的参数列表。名称是随意取的,也会有重复的代码。不过我会配上一套单元测试,覆盖每行丑陋的代码。
c. 然后我打磨这些代码,分解函数、修改名称、消除重复。我缩短和重新安置方法。有时我还拆散类。同时保持测试通过。
d. 最后,遵循本章列出的规则,我组装好这些函数。