1. 单一职责原则
这是经常被违背的原则, 也是最难运用好的原则.
- 一个类只做一类相关的事情
- 一个函数/方法, 最好只做一件事情
2. 行为是否统一
1) 什么是行为统一? 例如:
- 错误处理是否统一
- 错误提示是否统一
- 弹出框是否统一
- ...
2) 同一逻辑/行为, 有没有执行同样的代码路径
低质量的代码一个特征是, 同一逻辑/行为, 在不同的地方或不同的方式触发时, 没有执行同样的代码路径(产生出不同的结果), 或者是各处copy一份实现, 导致非常难以维护.
3. 代码污染
代码有没有对其他模块强耦合
4. 重复代码
主要看有没有把公用组件, 可复用的代码、函数抽取出来
5. 开放-封闭原则
简单理解是, 看代码好不好扩展
6. 健壮性
- 核心数据有没有强制校验?
- 对业务有没有考虑完整, 逻辑是否健壮
- 有没有潜在的bug?
- 有没有内存泄露?有没有循环依赖?
7. 错误处理
有没有很好的Error Handling? 如网络出错, IO出错等.
8. 面向接口编程/面向对象接口编程
主要看有没有进行合适的抽象, 把一些行为抽象为接口
9. 效率/性能
- 客户端程序对频繁的消息和较大数据等耗时操作是否处理得当
- 关键算法的时间复杂度是多少? 有没有潜在的性能瓶颈?
10. 代码重构
- 新的改动是打补丁, 让代码质量继续恶化, 还是对代码质量提升有帮助?
低质量代码的常见特征
- 违反"单一职责"原则
- 同一逻辑/行为, 通过不同的方式触发时, 不会执行同样的代码路径
- 缺少注释
- 函数/类命名乱, 词不达意, 或"挂羊头卖狗肉", 例如
export function setDefaultImg(res) {
let imgUrl = getImagePrefixUrl()
let previewImgSrc = require('@/asserts/images/icon.png')
if(res.imgId) {
previewImgSrc = `${imgUrl}${res.imgId}.${res.type}?t=${+new Date()}`
}
return previewImgSrc
}
上例函数, 其实是想对传入的参数进行判断, 如果值无效, 取默认图片, 否则返回拼接地址好的img src相对地址. 从函数的实现来看, 有如下几个问题:
- 函数名setDefaultImg并不合适, 无任何对数据的更新/修改, 最终目的是想拿到img的拼接地址(或者默认图片)
- 形参
res是一个对象, 实际使用到的属性只有两个基本类型, 遵循最少知识原则, 应修改形参. let imgUrl, 其实是拼接url的前缀, 取名如imgPrefixUrl会比较合适.- let 使用不当, 如
let imgUrl, 因涉及不到变量再赋值, 使用const是比较合适的 res.imgId, 即异常情况的处理, 少了对res.type的处理- 变量命名, 如
previewImgSrc, 取此名也不太合适, 该src使用的目的并不确定, 建议使用有比较通用涵义的名字.
可考虑重构为:
export function getImgSrc(imgId, imgType) {
if(typeof imgId !== 'string' || typeof imgType !== 'string') {
return require('@/asserts/images/icon.png')
}
return `${getImagePrefixUrl()}${imgId}.${imgType}?t=${+new Date()}`
}
参考资料: