代码整洁之道阅读笔记
代码整洁规范
减少重复代码
提高表达力
提早构建简单抽象
有意义的命名
名副其实
- 如果你需要注释来解释一个变量,那就说明它不是名副其实
- 一旦发现有更好的命名,就要换掉旧的,要记住换花的时间是值得的
避免误导
- 尽量少使用类型名,除非它真的是这个类型
- 不要使用过于相似的名字
命名规范
- 类名和对象是名词,方法是动词,注意get/set/is的前缀
- 即每个抽象概念选一个词,DeviceManager和Protocal-Controller是一样的
- 要保持前后术语规范。
- 用常量代替原始数字(魔术数)
- 不要在代码中重复写+1的边界条件,而是用变量进行封装
- 函数的长短与其作用范围息息相关,所以for循环可以用i,j因为它们作用域很小
函数
函数要做到自己理解,而不是通过测试用例,这需要改进和重构简洁。
尽量短小
- if/for/while中应该只有一行
- 函数只做一件事,抽象层上应该是同一级别!
- 函数的顺序,是自顶向下的规则,抽象到具体的顺序
- 函数要做什么事和函数要回答什么事区分。函数修改状态和返回状态区分
参数
- 参数最多不应该超过3个,如果参数多于3个的时候,就可以思考参数是否能构成一个类
- 参数不要传布尔值,应该将true/false分成两个函数,然后在布尔值的上一个抽象层直接做判断,而不是将其作为布尔值传递。(整数值,枚举元素等函数选择行为同理)
处理异常
- try/catch的每个功能都应该拆出成一个函数
- 如果你用枚举类型来表示异常,那将意味着你会很不情愿修改它,使用异常代替错误码,新异常就可以从异常类中派生出来.
重复
- 永远无法容忍重复代码,这意味着抽象的遗漏3
- 如果你发现死代码(永不执行的代码块),果断删除
- 多个switch/ifelse,考虑多态
判断
- if的条件如果过多,就要封一个函数,因为没有上下文是看不懂if的
- 避免否定条件,尽量保持一致,不要带!,可以直接把!函数封成函数
静态
- 如果一个函数不依赖其类的属性,都是依赖于参数,这时候该函数就应该声明为静态
- 静态导入(就是单纯导入),而不是用继承的方式,这样别人不知道函数的来源
注释
尽量少写注释
- 写注释意味着你的代码不够优雅,别人无法理解
- 能用函数和变量拆解的时候就拆解,而不是用注释去描述
- 你无法始终坚持维护你的注释,会出现各种问题
- 不要注释代码,我们有优秀的代码管理器,无用的代码就删掉就可以了,它会保留的。
好的注释
- 法律与版本信息
- 某个决定背后的意图解释,便于后续别人的修改
- TODO
如何写注释
- 一旦写注释就要花时间写好注释,注释的角度尽量从别人的角度出来来想会有什么疑惑,而不是解决自己的疑惑
- 不要尝试描述代码本身
格式
格式之所以重要是因为,你的功能可能会变,但是你代码的风格会一直保留
正确格式
- 封包声明,导入声明,每个函数,每个有区别的地方都应该用一行空白行分割。
- 垂直关系:关系紧密的就应该靠在一起,函数调用了也应该放在一起
- 水平关系:赋值符前后空格,参数前后空格
数据,对象的反对称性
抽象
- 隐藏实现并非在变量之间放上一层函数层,也不是单纯使用取值器和赋值器往外推,而是暴露抽象接口,以便于用户无需了解数据形式就可以操作数据。
- 过程式代码便于添加函数(switch实现);对象类代码便于添加数据类型(多态实现)
- DTO(data transfer object),豆结构,即只有赋值器和取值器操作的私有变量
错误处理
try-catch
- try-catch: 一开始可以用exception捕捉,捕捉到之后要缩小到对应范围。
- try的内容是一个原子事务,这一点要注意想清楚。
打包类
如果需要多次捕捉异常,则可以将其封装在一个类中成第三方API
NULL值处理
- 绝对不要返回Null值,否则别人检查null值会很麻烦,而且检查一多就会乱(可以内部直接抛出错误,也可以定义为空值就好)
- 禁止参数传入Null值,否则你总不可能每个变量一个个检查null(如果实在没有办法就只能用断言assert检查一下吧,用if有时会太乱混淆)
测试
- 测试代码和生产代码一样重要。如果你随便对待,将来将花费更多时间塞入新的测试和检查旧的测试
- 包括三个环节:BUILD-OPERATE-CHECK 构造测试数据-操作测试数据-检验操作
- F(Fast)I(Independent)R(repeatable)S(self-validating)T(timely)
- TDD的思想很重要,否则你无法保证你的任何修改是正确的
类
短小
- 类的名称要描述其权责而不能是一些模糊的词(Process,manger,super),而且描述该类职责的时候不应该出现if/and/or/but这些词语
- 类的权责应该是单一的,尽量拆成多个短小类吧
- 长的函数拆成小的函数的时候,参数是否要传,若是那为什么不把它们变成一个类,参数是它们的成员变量就好了。注意变的时候保持单一权责
- 注意职责的分隔。如果当你新增一个功能可能会影响其他时,说明耦合过强
好的代码示范
书的附录记录了好的代码示范