clean code
参考
https://github.com/ryanmcdermott/clean-code-javascript
核心
一切都是为了「可读性」
code review 的时候设想一下,如果是别人第一次接触到这些代码会怎么想。
命名
取有意义的名字
变量的名字应有具体含义。 同时也应避免啰嗦,如在同一个类下就应该省略对类名的额外描述。(又或者说,在当前作用域/文件下已经可以标识出一些信息的情况下,略去这些信息)
⚠️ 在 map 等回调函数的使用时,对参数至少需要写到能理解的地步。(遍历地名 location,而非 l)
函数命名可以用一些通用动词+名词,以标识它的作用(get/set/update/delete/toggle/handle/has/do)等等
拒绝硬编码
对于常量使用对象/enum 的形式给一个可读性更好的标识,同时方便未来维护
灵活使用解构
对于数组中取值的情况,很难直接判断取的这个值是什么意思。使用解构就可以给它取一个更有语义的名字
避免否定命名
否定用!在逻辑层面标识,命名时保持肯定情况(!notxxx 的情况会引起困惑)
逻辑
并发
使用 promise 而非回调。async await 更简洁一些,不过都可以用
⚠️ 不要混用 promise 、async await
减少嵌套层数
在处理异步操作时,灵活使用 promise.then 的链式调用/async await 同步写法
使用?:、&&、??等操作符以减少 if 嵌套
DRY
不要重复自己原则
函数设计
原则
- 单一职责(SRP)
- 开闭原则(OCP)对扩展开放,对修改关闭
- 里氏替换原理 (LSP) 子类扩展的前提是需要在替换父类的时候不影响程序执行
- 接口隔离原则(ISP)不应该开放所有设置,只需要开放对用户有用的接口
- 依赖倒置原则(DIP)尽可能解耦
优化
-
涉及设计模式: 很多看起来啰嗦的代码都可以用现有的某种设计模式重新组织(例如,对于简单的策略模式:switch) 核心:抽离重复逻辑/重新判断需要的细粒度 但同时需要注意,要保持单一职责和可读性。(抽象的程度不能太深)
-
涉及函数式编程: 可以通过函数组合来实现一些复杂功能。设计链式调用函数以组合使用(return this) 优先选择组合而非继承 灵活使用 map、reduce、filter 等原生函数 尽量避免副作用,尽量避免全局变量,修改全局的原型对象等(替代方式:利用闭包维护自己的私有变量)
不应该把 flag 当作函数参数传递。
这意味着你应当拆散函数,并在外部进行队函数是否执行的逻辑判断
将判断逻辑抽离到一个函数一起处理
使用 should/is 的命名
错误处理
提前处理(判断错误条件),趁早返回 不要忽略捕获的错误,不对错误进行处理就不要捕获。否则程序出问题了甚至无法溯源 不要忽略 rejected promise
删除死代码
迭代之后确定不用的代码就删掉
使用 getter、setter
取值、赋值操作最好使用函数包装,用 getxxx,setxxx 的形式
使用 class
不要使用 es5 的模拟类方式,可读性太糟糕
tips
默认值
对于函数参数,在参数上使用 = 标识而非在函数内部赋初始值,这样可以更容易从函数声明的时候看到它发生了什么
对于对象,维护一个 default 对象,在初始化的时候采用 Object.assign 混入
函数参数
在函数参数有很多的时候,转成一个 options 对象以方便使用。这样就可以不用按照顺序传了,ts 定义好类型也可以获取代码提示
类型检查
如果用 js 写,避免类型检查(写了也没用,还会降低可读性) 考虑使用 ts 获取良好的类型检查
不要过度优化
浏览器/v8 已经在底层做了大量优化了,没必要在一些细枝末节的地方做优化
不要提前优化
一个编码的小 tip,吃过很多次亏了 先实现整个逻辑,跑起来之后再重构代码 如果可以的话,也可以写一些单测/小 demo 来指导代码的迭代
格式化
代码美学本就和个人审美相关,因人而异,好看就行
antfu 博客中有反对 prettier 的说法,我觉得非常有道理,并且在我的项目中实践。
⚠️ 保持统一和规范
注释
不要描述代码,而是讲述业务逻辑。好的代码有一定程度的「自文档」性,标注一些比较复杂的逻辑即可