【七日打卡】重构几次代码后,我总结了一些前端代码优化实践

6,247 阅读11分钟

本文已授权掘金开发者社区公众号独家使用,包括但不限于编辑、标注原创等权益。

前言

得益于React的帮助,在近半年也是恶补了一些原生JavaScript的一些知识点,学习的同时也慢慢的思考当前项目中的一些合理性,复盘后总结了一些项目上必须优化的一个点,希望和大家进行共勉,也是本次在面基时和@苏yun小姐姐探讨后的一篇收获文,如果对大家有帮助,不妨点个赞支持一下作者吧。

什么样的代码算是整洁

很长一段时间,大部分前端都在抱怨一个事情前人栽树,后人就真的凉了的一个事实,意思就是一个项目中的代码,除了开发者本人,其他人接手会有一定的难度。因此,如果开发的人员离职了,那么这一份代码就难逃重构的命运了,长久下去,那么项目很容易形成一个高危项目,哪天新来的同事加了一个需求后,突然就出现一些奇奇怪怪的BUG

所以,你的代码可能看起来是这样的,

那么,怎么样才算是清晰整洁的代码呢?从字面意思上来看,在代码中整洁清晰呢?当我们进行大部分的开发规范的时候,比如Eslint,我们貌似只能做到当前如下图,整个寝室(团队)大体上的一个规划完整度,但事实上,每个人写的代码真就如代码风格一般,真就整洁清晰了?

事实证明,并不是的。Eslint给予的强约束只能让代码表面看起来不是那么缭乱,这部分和代码清晰没有任何关系,因此清晰代码大多数是由开发者产生,在不停的编码发现问题 -> 解决问题 -> 总结问题

那么下面进入主题,分享一些基本的小思路。

函数注释 和 TypeScript

为什么单独将注释排在第一梯队?

我个人认为好的代码注释一定是清晰的,它就如同商品的简介,你可以在第一眼知道它当前的一些信息,如作用,传入的参数,返回了什么。

你知道当前这个常量所指向什么,你知道声明这个变量是用来干什么的。推荐在2021年,如果你们的团队正在使用TypeScript,别抱怨麻烦,它对自己的代码质量提升是非常直观的。

没有注释的代码,在code review大概率是会被刮目相看的一件事情

变量&常量

TS =>

JSDOC =>

函数(方法)

TS =>

JSDOC =>

以上使用了变量和函数方法的示例来进行一些基本的演示。JsDOC是在团队并没有使用TypeScript时的备选方案。

你真的知道函数方法吗

在写业务的时,小伙伴们很少关注一个函数方法的复杂度,这个复杂度的大小决定了他(她)人理解你代码的一个效率度,不论是React,还是Vue,甚至于写NodeLibray上面大多数都是函数在支撑着,因此函数会占据着WEB开发很大的一环。

那么来看下函数上,如何能使当前的代码调理更加的清晰。

函数SRP

对于单一原则来说,函数其实算是其中具有魄力的一员了,在大多数情况下,函数始终只用做一件事情,一段逻辑,这样的话,在结合基本的注释就能让小伙伴瞬间明白你这个方法主要是用来干什么的,而不必思考是不是还做了其他的一件事情。

但是单一原则的颗粒度又是一个问题,在写React组件的时候,如果我们采用函数单一原则,那么一个组件中的函数是海量的,所以这个时候我们就需要权衡当前逻辑的层次了,在适当的范围内,事的大小其实也能套用在函数中,我的这个函数可能是多个函数的BFF(聚合层),或者说我这个函数本身就是用来处理一个聚合任务的。

示例:

如下函数其实就是典型的一个函数处理了两个行为,但是你说它并不单一其实也不是的。如果给它的作用升级,它其实也只是处理一件事情,也只是处理Storage罢了。因此,SRP的局限在于开发者本身,你希望它处理的范围是在哪一层,那么就决定了你的函数SRP做的事情够不够大。

那么,我们也可以写成下面这样,将设置获取拆分成为两个不同的函数。

主动return函数(主动停止)

对于业务的开发,往往一个函数中可能需要通过一些前置条件才能流向我们业务的一些核心逻辑。这一类的前置条件往往是一些条件判断,因此,在无法满足于这类条件的时候,后面的代码执行与否都没有任何意义的,就像面试时,简历不满足筛选条件,已读未回是一个概念。

如下代码:当姓名(name)年龄(age)满足的时候,进行个人信息的提交,不满足时提示。那么像下面写,好像是没有什么问题。但是一层层的if else看上去并不是非常的清晰。

那么不妨试试下面这个方法吧。虽然两个方法的复杂数都是5,但其实阅读质量是有很大不同的。方案二的实现将其拆分成三个步骤,当步骤执行到误区时,那么这个步骤中的处理因素return就会执行掉。

函数合并

函数合并的作用就是(减少重复代码),大家都知道,开发者都是善于解决重复工作的小能手,喜欢一劳永逸。所以往往在写代码中,能够合并的逻辑都会被独立出来管理,如下代码:两个方法都调用了相同的判断语句。

因此,如下图,我们将相同的逻辑提取成为一个函数,将公共代码做一层剥离后,返回对应的状态,随后调用进行状态的判断。

圈复杂度,函数衡量标准

我也是在今年了解到圈复杂度的概念,圈复杂度能够将函数的逻辑量化,用数据相对的标注当前函数有一个较为相对的衡量标准。

在软件测试的概念里,圈复杂度用来衡量一个模块判定结构的复杂程度,数量上表现为线性无关的路径条数,即合理的预防错误所需测试的最少路径条数。圈复杂度大说明程序代码可能质量低且难于测试和维护,根据经验,程序的可能错误和高的圈复杂度有着很大关系。【百度百科

那么,在我看来圈复杂度的一些标准化是怎么样的呢?

复杂度代码状态维护成本建议
1 ~ 10正常
10 ~ 20复杂优化逻辑,拆分子函数
> 29难以维护强烈建议重构

在这里,有一个插件推荐给大家,如下图,我清晰的知道我当前函数的一个复杂度状态,能够随时的思考函数的变化的优化方式。潜移默化下,能够提高开发者思考当前实现的优化方式是,这个插件名称叫做:CodeMetrics,我认为它是对开发者有帮助的。

复杂度高的函数,强烈建议进行重构,因为其中80%涉及到了脏代码,因此重新梳理逻辑重构是必不可免的。

点击前往VS code下载插件

状态备注维护

什么是状态?

信息状态

获取大家都经历过后端返回的一些字段,如status,但基本上值其实是不可读的,除了后端和对接人之外,其他前端往往不清楚这个状态表示了什么。甚至于久而久之,随着需求的增加,你会好奇status1是什么,2是什么?那么这样避免不了二次查阅文档。这期间花费的时间本身可以被节省掉。

后端的不可读字段其实都来自于实体类,但是其数据表中的字段备注非常详细。因此,后端是绝对是能够梳理起当前的一个状态的。

因此在进行状态操作的时候,在数据声明时加上备注注释。如下图,就是比较难以看懂的一个代表了:

随着grade变化,那么下一次去改变逻辑的时候,就需要重新对grade进行理解。

那么,我们可以做一些友好的注释来声明,对状态进行标注

PS.当状态可以被描述时,往往可以如下处理,定义一个状态对应的数组,返回一些对应的描述。

一般为状态对应某段中文的时候使用。

操作状态

上面是一些信息状态的处理方式,但是操作状态往往是前端抽象出来的,举个很简单的例子:一个表单的创建页面和编辑页面是不是可以复用,既然是复用那么必然涉及到了一个参数来进行判断。

如下代码,就是一个非常难理解的事情,1代表创建, 2表示编辑。这是非常不推荐的一个形式。

const action = 1

if (action === 1) {
// 创建
}

if (action === 2) {
// 编辑
}

比较好的形式是如下:那么一下子就知道这个参数的含义是什么了。

const action = 'create'

if (action === 'create') {
	// 创建
}

if (action === 'edit') {
	// 编辑
}

这类状态往往错在页面路径传值,页面组件复用中产生。

使用class聚合方法,而不是object

在上面提到过一个示例,localStorage往往是需要我们自身多封装一层的,因此这种多个不同的方法,但是他们在操作一个模型的行为,就可以进行一个简单的聚合分组。

在ES5时,class语法糖还没有出来,原型类又太麻烦,那个时候就有使用object来做方法的聚合,这其实是不友好的,如下图:

但是为了有更好的扩展能力,单个对象其实就没有class有优势了,其次class有更好的面向对象基础,而object只是将函数当成属性来管理的,如果要基于当前的集合做一个超集,那么object就不能胜任子集的任务了。

写在最后,为什么不推荐自动Prettier

本次内容算是一个小系列吧,后续可能还有其他的一些产出,本次文章中的内容大多数都是偏函数方面的问题。这部分文章应该算是脱离了业务框架的一个知识点。

在最后,我说下我对prettier的看法吧,工具本身是好的,但是看到很多文章中无不是在git hook中直接将代码刷一次。那么,这个插件对开发者意义价值在哪里呢?还是说为了项目代码好看故意而为之?

所以,在最后,我希望开发者们养成自己的一套eslint代码规范,可以是阿里腾讯...等大厂,也可以是eslint-plugin热门插件,我希望是开发者(尤其是新手开发者)坚持写下去,按照当前团队的规范,细心的写下去,写到后面,无非就是单引号双引号, 几个空格这样的规则都交给插件去打包,这些才是插件需要干的事情。而不是将能帮助开发者的功能交给插件做一个面子工程。

不能帮助开发者成长的面子工程工具链,如无必须,都不推荐轻易使用。

总结

七日打卡活动已经开始了,在这七天内,我会分享我项目的一些总结,学习到的知识。也有生活的点点滴滴,作为一名星巴克气氛组的新进成员,还是挺喜欢这一次的礼物的,刚好任务迭代也已经进入了一个比较后期的阶段了,可以给大家带来更多的优质文章啦。

第一次脱离框架写文章,也算是2021年的开门红了,希望能在接下来一年的时间,给大家带来更多VueReactTypeScript工程化相关的文章内容,如果本文对你有帮助,看完记得点个赞哦,有问题也可以在评论区指出哦。

2021年,希望大家都能成为更好的前端开发工程师。