最近看了一本 《代码整洁之道》
基本跟我们平时的编码代码规范有点类似吧。里面的一些设计思想是挺好的。这里记录一下一些个人感觉好像挺有用的点。
部分内容可能存在争议,请不要在意,以自己团队规范为准。
常量
用命名常量替代魔术数(泛指任何不能自我描述的符号)
命名采用描述性名称,确认名称具有描述性
语句
封装条件要抽离解释了条件意图函数,比如 shouldBeDelete(timer) 要优于 (timer.hasExpired && !timer.isRecurrent())
避免否定条件 if(shouldDo) 要好于 if (!shouldNotDo)
函数
为较大作用范围选用较长名称
名称应该说明函数、变量或类的一切信息,不要用名称掩蔽副作用。
每个函数只做一件事情
函数参数应该越少越好
不要把输入的参数拿来输出
布尔值参数宣告函数做了不止一件事情,违反了单一职责原则,应该消灭掉
用布尔、枚举、整数等参数用于判断流程来决定函数行为是不好的,使用多个函数,通常优于向单个函数传递某些代码来选择函数行为
使用异常替代返回错误码
抽离Try/Catch代码块
把重复代码抽离出来
通常应该倾向于选用非静态方法。如果的确需要静态函数,确保没机会打算让他有多态行为。
函数名称应该表达其行为
如果多个函数的调用有时序性,比如必须先调用A才能调用B,要显式声明时序性,比如调用B函数的时候把A函数作为参数传进去,这样子就保证别人不会误把B函数放在A函数前调用
格式
顶部给出高层次概念和算法。细节应该往下渐次展开,直至找到原文件中最底层的函数和细节
如果某个函数调用了另外一个,就应该把它们放在一起,而且调用者应该尽可能放在被调用者上面,
概念相关的代码应该放到一起,相关性越强,彼此之间的距离就该越短
对象
过程式代码(使用数据结构的代码)便于在不改动既有数据结构的前提下添加新函数
面向对象代码便于在不改动既有函数的前提下添加新类
过程式代码难以添加新数据结构,因为必须修改所有函数。
面向对象代码难以添加新函数,因为必须修改所有类。
迪米特法则:模块不应了解它所操作对象的内部情形。
隐藏结构:let a = b.c().e().f()
拆分成
1 | let c = b.c() |
应该改成let a = b.func()
在方法中,不应该调用其他对象的方法
1 | func test(let obj) { |
类C的方法f只能调用以下对象的方法
- C
- 由f创建的对象
- 作为参数传递给f的对象
- 由C的实体变量持有的对象
用多态替代if/else 或 switch/case
错误处理
不要使用错误码,用try-catch代替
不要返回null值,用空对象替代,或者抛出异常
不要传入null值作为参数,除非API要求你这么做
边界
使用泛型限制输入
单元测试
单元测试应当简单、精悍、足具表达力。
测试代码和生产代码一样重要
TDD三定律:
- 在编写不能通过的单元测试前,不可编写生产代码
- 只可编写刚好无法通过的单元测试,不能编译也不算通过
- 只可编写刚好足以通过当前失败测试的生产代码
每一个测试一个断言
- 每一个测试一个概念
- 一个概念可以多个断言
简洁的测试应该遵循5条规则
(FIRST: FAST、Independent、Repeatable、Self-Validating、Timely)
- 快速:测试应该够快
- 独立:测试应该互相独立,某个测试不应为下一个测试设定条件
- 可重复:测试应当可在任何环境中重复通过
- 自足验证:测试应该有布尔值输出
- 及时:测试应及时编写
类
类应该短小,遵循单一职责原则(类或模块应有且只有一条加以修改的理由)
类应该只有少量实体变量
当类丧失了内聚性,就拆分它
类的方法只应对其所属类中的变量和函数感兴趣,不应该垂青其他类中的变量和函数