背景
前端项目重构,旨在从代码质量、性能优化、体验优化等角度出发,提高代码的可读性、复用性、可维护性、健壮性、安全性等,提升网站性能和用户体验,同时也能提高开发效率。
重构目的
-
提高代码可读性:去除代码异味,合理设计封装。代码规范最佳实践。
-
提高代码复用性:抽离封装复用重复代码,降低代码重复率。
-
提高代码健壮性:加强异常处理和兜底
-
加强代码安全性:修补代码安全漏洞
-
提高可维护性
-
提高开发效率
-
提高网站性能
-
提升用户体验
重构原则
原则上规范相关的都已经通过eslint+prettier规范统一约束。
其它代码设计层面的重构原则,大家多阅读下相关设计原则的介绍,在项目中贯彻实施。
渐进式重构:注意评估影响范围,不要影响已有功能!
重构需要通过项目中的eslint+prettier检查!(commit会自动检查,原则上不允许-n跳过检查)
重构注意检查Sonarlint问题,保证0问题!(编辑器安装Sonarlint插件,查看problems)
参考:[Sanar规则信息及如何解决]
-
重复代码需要重构。原则上同样代码出现两次及以上就要重构
-
可读性差需要重构。难以理解,嵌套深,理解成本高,需要重构
-
遵循面向对象七大设计原则
- 开闭原则(Open Closed Principle,OCP)
- 单一职责原则(Single Responsibility Principle, SRP):可以理解,但是功能太多,考虑重构
- 里氏代换原则(Liskov Substitution Principle,LSP)
- 依赖倒转原则(Dependency Inversion Principle,DIP)
- 接口隔离原则(Interface Segregation Principle,ISP)
- 合成/聚合复用原则(Composite/Aggregate Reuse Principle,CARP)
- 最少知识原则(Least Knowledge Principle,LKP)或者迪米特法则(Law of Demeter,LOD)
-
封装规范
命名规范,命名明确和精简,最好看到名字就知道具体功能。需要特殊说明的,注释补充说明。
注释说明:组件和方法封装,必须说明用途,参数做好描述,并做好类型约束。常量类型,能枚举类型就枚举所有。
良好的拓展性:
不要过度封装:
不要无用的代理:
杜绝过度嵌套:
-
重构过程中不要出现坏味道!(参考下面的坏味道)
-
代码审查和单测覆盖
代码中的坏味道 - 规避!
常见坏味道罗列如下。
- Duplicated Code (重复代码)
2 .Long Method (过长函数):
-
Large Class (过大的类)
-
Long Parameter List (过长参数列)
-
Divergent Change (发散式变化)
-
Shotgun Surgery(散弹式修改)
-
Feature Envy (依恋情节)
-
Data Clumps(数据泥团)
-
Primitive Obsession (基本类型偏执)
-
Loops Statements (循环语句):避免重复的switch,复杂的用多态优化
11.Parallel Inheritance Hierarchies( 平行继承体系)
-
Lazy Element (冗赘元素):合并不必要的类
-
Speculative Generality(夸夸其谈未来性):不要过度封装,没用到就删除,需要再拓展。
-
Temporary Field(令人迷惑的临时字段)
-
Message Chains (过度耦合的消息链)
-
Middle Man (中间人):去掉不必要的中间人
-
Inappropriate Intimacy(狎昵关系)
-
Alternative Classes with Different Interfaces (异曲同工的类)
-
Incomplete Library Class (不完美的类库)
-
Data Class (纯数据类)
-
Refused Bequest (被拒绝的馈赠)
-
Comments (过多的注释)
-
神秘命名
-
神奇魔法数
-
混乱的代码层次调用
27.全局数据
如何重构
-
代码规范和格式化:规范和格式化会用eslint+prettier工具直接约束
- 命名规范:文件夹/文件、变量/函数/组件等。命名清晰精简。命名规范eslint已约束。
- 注释规范:添加必要注释。尤其是公共方法和公共组件。
- ts规范问题修复:基本type类型封装复用
-
删除冗余代码:删除无用js、css、静态资源等文件
-
提取重复代码:注意遵循设计原则
- 抽取公共方法
- 抽离封装公共组件
-
拆分功能太多、过长的函数:
-
简化条件逻辑:复杂的条件,封装成方法,方法名说明用处
-
以函数调用取代内联代码
// Bad
let hasApple = false
for (const fruit of fruits) {
if (fruit == 'apple') {
hasApple = truebreak
}
}
// Good
const hasApple = fruits.includes('apple')
7. 折分嵌套条件表达式
-
将查询函数和修改函数分离
-
样式文件重构
-
异常处理及兜底数据。参考异常捕获处理
-
array方法,确保为有效数组
-
对象方法,确保
-
正则
-
JSON
-
异步:await, Promise
-
Decimal
-
Default 赋值,默认不会走
-
杜绝魔数。常量需要抽离复用。比如跳转链接:抽离成常量或拼接方法,方便后续统一更改路由。
-
工具(强推!):
- 编辑器安装SonarLint插件,检查相关问题并修复。