不少时候,咱们看见一些不太优雅的代码、不太整洁的代码,也很容易能够推断出这段代码是怎么来的,甚至是能够推断出写这个代码的人当时的心理状态和那时候的背景。在前端迅速发展的时代,一份一年多两年以上的代码,极可能带着历史的色彩地成为了历史包袱css
若是某一天,你忽然看见相似下面这些的代码:html
function f() {
if (a) {
return
}
if (b) {
return
}
if (c) {
return
}
// ...many codes
}
复制代码
推测当事人心理:需求要作这个功能,须要加一个条件。好的,就在最前面加一下
function f(a, b, c, d, config, isAdmin, isEdit, isAdd) {
// ...many codes
}
复制代码
推测当事人心理:后面这个函数功能更复杂了,须要加多一个参数作配置。啊,还要再加一些功能,再多一个参数
if (a === 1 || a === 2 || a === 3 || a === 4) {
}
复制代码
推测当事人心理:状态4也要走这个逻辑,那我加多一个&&便可
return (
<> { isXXX && <div>abc</div> } {/* 可能中间有不少其余代码 */} { !isXXX && <div>123</div> } </> ) 复制代码
推测当事人心理:兜底状况展现123,直接加一下,ok
const data = res[0].some_data || {}
if (!data) {
return
}
// other code
// =================================
const SOME_FLAG1 = 'xxxx1'
const SOME_FLAG2 = 'xxxx2'
const SOME_FLAG3 = 'xxxx3'
const arr = [SOME_FLAG1]
if (xxx) {
// arr
}
// 对arr一顿操做
if (!arr) {
// 怕出错?加了这个
}
复制代码
推测当事人心理1:可能arr为假值,防止报错
推测当事人心理2:只是改了前面,后面!arr压根没看见
import { func } from 'prop-types';
function a(){
return 1
}
复制代码
推测当事人情况:压根不知道,只是输入了func按了回车,觉得是function的补全
又好比想要一个request,发现有3个以上的提示。而后一看,团队统一的request一个,某我的写了一个缓存版本又一个,另外一我的又本身写了一个袖珍版,最后还有一我的写了一个预处理参数的...前端
推测当事人情况1:压根不知道有团队统一的request,本身写还写得很挫
推测当事人情况2:知道有request,但不敢改,因此本身封装多一层,但名字仍是取了同样的
本人屡次代码优化重构的经验,一个没有lint的项目,开了lint后90%的错误均可以经过autofix解决。例如9000个错误,跑一下便可变成800多个,能够修复那些换行、缩进、函数单参数无括号的问题。这些修复不须要测试介入。剩下的那些错误须要人工解决node
最多见的须要人工解决的lint错误合集:
错误 | 解决方法 | 紧急程度 | 风险 |
---|---|---|---|
下划线命名 | 全局搜索,一个我的工修 | 中 | 低 |
解构赋值 | 通常是warning,遇到一个修一个 | 低 | 低 |
无状态class组件 | 改为PureComponent或者函数组件 | 高 | 中 |
willreciveprops | 改为getderivedstatefromprops | 高 | 高 |
componentwillmount/update | 初始state & didmount | 高 | 低 |
== | 肯定类型再转化,最后=== | 高 | 高 |
做用域下重复命名 | 看见就修,但仍是有必要性 | 中 | 低 |
ts类型报错 | 不影响代码的执行,但也不能长期无论 | 低 | 低 |
html标签缺乏属性 | 如img的alt、button的type,看见就修 | 低 | 低 |
promise的rejcet不是error | reject(Error(xxx)) | 高 | 低 |
中等风险以上的修复,须要自测或者测试,过一遍主流程。不管哪种人工修复,量达到几百个,都须要测试介入react
好比上面的多个if-return、很长的相似的判断,均可以精简为||
、&&
,进一步精简就是数组操做: [1, 2, 3, 4].includes(a)
,在另外一篇文章里面有讲到更多的if简化git
上面提到的一些状况,多是最开始的时候设计是没什么问题的,但随着需求迭代,就不同了。好比多个if-return、明显走不到的逻辑、重复写了一些常见的工具函数,这些问题都是由于不完整地看上下文致使的json
export default class extend
、export default function() {}
,不然调试工具不显示名字本人有屡次历史大项目重构经历,常见的case和套路已经在上文提过,接下来是操做步骤的总结数组
传统旧项目,一般没有lint,须要本身装。而后找一下团队如今的lint规范(若是没有就找业界出名的如airbnb),接着跑一波lint自动修复,此时能够把缩进换行所有解决,剩下的须要本身手动去修。具体怎么手动修,前面已经提到了promise
为何重构?那必然有一个触发点,或是某个需求,或是发现了不少bug致使没法正常运行。或是开始有大力维护的计划。因此先从触发点开始,在保证功能正常的状况下,顺便把模块一块儿重构了,这里也有几个要领:缓存
if status === 1
、 type === 0
这种代码,这个让人懵逼的数字就是magic number。此时要看上下文,了解这个数字是什么意思,再使用大写常量来维护(如const NORMAL = 1;
,并加上注释:// 【xx模块】状态正常:1
) 。若是多个文件用到,须要提取到更上层if a == b
,从代码中没法知道a、b是什么类型,且业务路径很长很差复现,先妥协一下,等有时间再改修改范围怎么肯定?
有一个这样的文件目录:
- components
utils.ts
constant.ts
-- Home
index.tsx
Header.tsx
Footer.tsx
...
-- Input
index.tsx
index.scss
...
复制代码
Header.tsx
,Home目录不大,须要所有一块儿重构;若是Home目录很大,那就只改Header.tsx
和他的父组件index.tsx
功能已经作好了,也顺便重构了一波,此时还没完。考虑到将来继续维护和重构,因此如今要开始铺路,方便下次,让本身和其余同事更舒服
{ ...data }
,经历过的人天然懂这个痛虽然平时你们老是自黑,讲段子,发自黑、调侃的表情包,吐槽垃圾代码、历史代码、知道没用但不敢动.jpg。但我相信若是真的搁在头上了,你们都不会怂的,也不会轻易妥协,会认真的修好,完美完成重构
关注公众号《不同的前端》,以不同的视角学习前端,快速成长,一块儿把玩最新的技术、探索各类黑科技