《代码整洁之道》读书笔记

整洁代码
要有代码
我们永远也抛不掉代码,因为代码呈现了需求的细节
糟糕的代码
我们都曾经瞟一眼自己亲手造成的混乱,决定弃之而不顾,走向新一天.我们都曾经看到自己的烂程序居然能运行,然后断言能运行的烂程序总比什么都没有强.我们都曾经说过有朝一日再回头清理.当然,在那些日子里,我们都没听说过勒布朗法则:稍后等于永不
混乱的代价
代码逻辑应当直截了当,叫缺陷难以隐藏;尽量减少依赖关系,是指便于维护;依据某种分层战略完善错误处理代码;性能调至最优,省得引诱别人做没规矩的优化,搞出一堆混乱来.整洁代码整洁代码只做好一件事
童子军军规
让营地比你来时更干净
有意义的命名
- 名副其实
- 避免误导
- 做有意义的区分
比如用数字区区分比如item1,item2在某些场景下很没意义
- 使用读得出来的名称
- 使用可搜索的名称
长名称胜于短名称,搜得到的名称胜于用自造编码代写就的名称
- 避免使用编码
把类型或作用域编进名称里,徒然增加了解码的负担
避免映射思维
不应当让读者在脑中把你的名称翻译为他们熟知的名称,这种问题经常出现在选择使用问题领域术语还是解决方案领域术语时
类名
类名和对象名应该是名词或名词短语
- 方法名
方法名应当是动词或动词短语
- 别扮可爱
把函数HolyHandGrenade改名成DeleteItems比较好
- 每个概念对应一个词
比如,在同一个程序集中,既有controller,又有Manager,driver之类的类名,就会让人困惑
别用双关语
使用解决方案领域名称
只有程序员才会读你的代码,所以尽管用CS术语,算法名,模式名,数学术语吧
- 使用源自所涉问题领域的名称
如果不能用程序员熟悉的术语来给手头的工作命名,就采用所涉问题领域而来的名称吧
- 添加有意义的语境
比如添加前缀,让读者明白这些是某个更大结构的一部分
- 不用添加没用的语境
主要短名称足够清楚,就要比长名称要好
函数
短小
函数的第一规则是要短小,第二条规则是还要更短小
函数的缩进层级不该多于两层
否则,你需要拆分更多更小缩进层级的函数
只做一件事
如果一个函数做的许多事
比如 1.判断是否为测试页面;2.如果是,则容纳近设置和分拆步骤;3.渲染成HTML
你需要拆分更多更小抽象层级的函数
每一个函数一个抽象层级
- 向下规则:自顶向下读代码
我们希望每一个函数后面都跟着位于下一抽象层级的函数
使用描述性的名称
函数参数
最理想的参数数量是0,其次是1,然后是2
尽量避免3个或以上参数的函数
如果你写出了一个3参数的函数,比如这个函数的参数列表是(int x, int y ,int z)
考虑用结构体或类封装参数,例如更改参数列表为(Point thePoint)
无副作用
副作用是一种谎言,函数承诺只做一件事,函数的名称和注释说明了这个函数只做一件事,但还是会做其他被藏起来的副作用
分隔指令与询问
函数要么做什么事,要么回答什么事,但二者不可得兼
函数应该修改某对象的状态,或是返回该对象的状态
使用异常代替返回错误码
通过抛出异常来代替debug.log
错误处理本身就是一件事,所以我们要从函数中抽离Try/Catch代码块,另外形成函数
别重复自己
不要书写重复的代码
直接调用更小层级的函数来代替重复
关于结构化编程
结构化编程要求每个函数都应该有一个入口,一个出口,这使得每个函数中只应有一个return,循环中不能有break,continue,且永远也不能有goto
结构化编程的规范和目标只对于大函数有明显的好处
只要函数保持短小,偶尔出现的return,break,continue没有坏处,甚至比单出单入原则更有表达力
依然要避免使用goto
注释
注释总是一种失败
注释总是一种失败,我们总无法找到不用注释就能表达自我的方法,所以总要有注释,这不值得庆贺
注释存在的时间越久,就离其所描述的代码越远,越来越变得全然错误.原因很简单,程序员不能坚持维护注释
注释不能美化糟糕的代码
但总要有注释,面对问题,读者的思考没有我们这么深入,我们也当然需要用某种方法让读者快速理解代码而不费脑力
好注释
- 法律信息
- 提供信息的注释
描述参数的作用,描述返回值的意义,描述变量的含义
- 对意图的解释
如果你不得不用一种反逻辑的方式写代码,写个注释解释一下
警示
TODO注释
坏注释
- 多余的注释
名称已经对功能做了很好的解释,不需要注释
- 误导性注释
程序员很久没有维护注释了,经过了几次代码修改,注释越来越错误
- 循规式注释
不是每个函数,变量或是别的东西都要有注释
- 日志式注释
- 废话注释
- 位置标记
- 归属与署名
- 注释掉的代码
- HTML注释
- 非本地信息
注释应该描述近几行代码的信息
- 信息过多
- 不明显的联系
注释应该和其描述的代码有明显的联系
- 如果注释本身还需要解释,那就太残念了
格式
垂直格式
一个脚本的长度不要太长,段文件通常比长文件易于理解(吐槽萌石科技那个一万五千行的gamemanager)
垂直方向上的概念间要有区分,每个空白行都是一条线索,标识出新的独立概念.往下读代码时,你的目光总会停留于空白之后的那行
如果抽掉这些空白行,代码可读性会减弱不少
同样,如果空白行隔开了概念,靠近的代码行则暗示了它们之间的紧密关系
除非有很少的理由,否则不要把有密切关系的概念放到不同的文件
变量声明应该尽可能靠近其使用的位置
因为函数很短,局部变量应该在函数的顶部出现,
实体变量应该在类的顶部声明
横向格式
应该尽力保持代码行短小,遵循无需拖动滚动条到右边的原则
在赋值操作符周围加上空格,表示强调
将参数列表中的参数隔开,表示互相分离
乘法因子之间没有空格,表示较高优先级,加法因子间没有空格,表示较低优先级
对象和数据结构
过程式代码难以添加新数据结构,因为必须修改所有函数.面向对象代码难以添加新函数,因为必须修改所有类
得墨忒耳律:对象隐藏数据,暴露操作
数据传送对象(DTO):最为精炼的数据结构,是一个只有公共变量,没有函数的类
仅仅是对DTO添加属性访问器(get-set对),会让oo纯化者感觉舒服些,但通常没有其他好处
为DTO塞进业务规则方法,把这类数据结构当成对象来用是不明智的行为,它导致了数据结构和对象的混杂体
错误处理
使用异常而非返回码
先写try-catch
使用不可控异常
当我们在应用程序中定义异常类时,最重要的考虑应该是它们如何被捕获
减少返回null,别传递null
本质上是减少判空的次数
关于使用第三方代码
通过代码中少数几处引用第三方边界接口的位置来管理第三方边界
类
放松封装总是下策
单一职责原则
SRP是OO设计中最重要但也最难遵守的概念,如果你可以记住SRP,你就可以把曾经写过的许多臃肿的类切分成只有单一职责的去耦式单元
大量短小的类不会造成逻辑复杂,如果造成了,那么把它们合成一个庞大的类要更加逻辑复杂
内聚
通常而言,方法操作的变量越多,就越黏聚到类上.如果一个类中的每一个变量都被每一个方法所使用,则该类具有最大的内聚性.
当然,创建这种极大化内聚类是既不可取也不可行的,但我们依然希望内聚性保持在较高位置
内聚性高,意味着类中的方法和变量相互依赖,互相结合成一个逻辑整体
保持一个函数和参数列表短小有时会导致为一组方法所用的实体变量数量增加,此时往往意味着至少有一个类要从大类中挣扎出来,你可以将这些方法和变量放到新的类中,使新的类更加内聚
系统
将系统的构造与使用分开
工厂
依赖注入
END
在写代码时,我用余光瞟见它.它一直提醒我,我做了写出整洁代码的承诺











