专栏名称: 前端大全
分享 Web 前端相关的技术文章、工具资源、精选课程、热点资讯
目录
相关文章推荐
启四说  ·  启四VIP策略网站,有哪些功能?如何使用? ·  14 小时前  
启四说  ·  启四VIP策略网站,有哪些功能?如何使用? ·  14 小时前  
前端早读课  ·  【第3451期】前端 TypeError ... ·  昨天  
江苏司法行政在线  ·  宿迁司法行政人、江苏监狱戒毒民警,给您拜年啦! ·  3 天前  
江苏司法行政在线  ·  宿迁司法行政人、江苏监狱戒毒民警,给您拜年啦! ·  3 天前  
51好读  ›  专栏  ›  前端大全

现在前端组长都是这样做 Code Review

前端大全  · 公众号  · 前端  · 2024-10-23 11:50

主要观点总结

本文介绍了Code Review的重要性及借助AI工具进行CR的方法,同时给出了多个优化案例,包括判断逻辑优化、函数传参优化、命名注释优化、分支逻辑优化、对象赋值优化及隐式耦合优化等。

关键观点总结

关键观点1: Code Review的重要性

CR不仅有助于个人技能成长,也对升职加薪、面试有帮助。

关键观点2: 借助AI工具进行CR

AI工具可以简化CR流程,提高效率。

关键观点3: 判断逻辑优化

将深层判断逻辑前置,前置校验逻辑,后置正常逻辑。

关键观点4: 函数传参优化

将形参封装成对象,对象函数内部解构,使代码更清爽。

关键观点5: 命名注释优化

避免魔法数字,使用常量代替;写有效注释,写业务逻辑what&why;合理利用命名空间缩短属性前缀。

关键观点6: 分支逻辑优化

使用映射代替分支逻辑。

关键观点7: 对象赋值优化

采用展开运算符进行对象赋值,确保原属性不会丢失。

关键观点8: 隐式耦合优化

将隐式耦合的常数抽离成常量,便于修改和维护。


正文

前言

Code Review 是什么?

Code Review 通常也简称 CR ,中文意思就是 代码审查

一般来说 CR 只关心代码规范和代码逻辑,不关心业务

但是,如果 CR 的人是组长,建议有时间还是看下与自己组内相关业务,能避免一些生产事故的发生

作为前端组长做 Code Review 有必要吗?

主要还是看公司业务情况吧,如果前端组长需求不多的情况,是可以做下 CR ,能避免一些生产事故

  • 锻炼自己的 CR 能力
  • 看看别人的代码哪方面写的更好,学习总结
  • 和同事交流,加深联系
  • 你做了 CR ,晋升和面试,不就有东西吹了不是

那要怎么去做 Code Review 呢?

可以从几个方面入手

  • 项目架构规范
  • 代码编写规范
  • 代码逻辑、代码优化
  • 业务需求

具体要怎么做呢?

传统的做法是 PR 时查看,对于不合理的地方,打回并在 PR 中备注原因或优化方案

每隔一段时间,和组员开一个简短的 CR 分享会,把一些平时 CR 过程中遇到的问题做下总结

当然,不要直接指出是谁写出的代码有问题,毕竟这不是目的,分享会的目的是交流学习

人工 CR 需要很大的时间精力,与心智负担

随着 AI 的发展,我们可以借助一些 AI 来帮我们完成 CR

接下来,我们来看下, vscode 中是怎么借助 AI 工具来 CR

安装插件 CodeGeex

新建一个项目

mkdir code-reviewcd code-review

创建 test.js 并用 vscode 打开

cd .>test.jscode ./

编写下 test.js

function checkStatus() {  if (isLogin()) {    if (isVip()) {      if (isDoubleCheck()) {        done();      } else {        throw new Error("不要重复点击");      }    } else {      throw new Error("不是会员");    }  } else {    throw new Error("未登录");  }}

这是连续嵌套的判断逻辑,要怎么优化呢?

侧边栏选择这个 AI 插件,选择我们需要 CR 的代码

输入 codeRiview ,回车


我们来看下 AI 给出的建议


AI 给出的建议还是很不错的,我们可以通过更多的提示词,优化它给出的修改建议,这里就不过多赘述了

通常我们优化这种类型的代码,基本优化思路也是,前置校验逻辑,正常逻辑后置

除了 CodeGeex 外,还有一些比较专业的 codeRiview 的 AI 工具

比如:CodeRabbit

那既然都有 AI 工具了,我们还需要自己去 CR 吗?

还是有必要的,借助 AI 工具我们可以减少一些阅读大量代码环节,提高效率,减少 CR 的时间

但是仍然需要我们根据 AI 工具的建议进行改进,并且总结,有利于拓宽我们见识,从而写出更优质的代码

具体 CR 实践

判断逻辑优化

1. 深层对象判空

// 深层对象if (store.getters &&  store.getters.userInfo &&  store.getters.userInfo.menus) {}
// 可以使用 可选链进行优化if (store?.getters?.userInfo?.menus) {}

2. 空函数判断

优化之前

props.onChange && props.onChange(e)

支持 ES11 可选链写法,可这样优化,js 中需要这样,ts 因为有属性校验,可以不需要判断,当然也特殊情况

props?.onChange?.(e)

老项目,不支持 ES11 可以这样写

const NOOP = () => 8const { onChange = NOOP } = propsonChange(e)

3. 复杂判断逻辑抽离成单独函数

// 复杂判断逻辑function checkGameStatus() {  if (remaining === 0 ||    (remaining === 1 && remainingPlayers === 1) ||    remainingPlayers === 0) {      quitGame()  }}
// 复杂判断逻辑抽离成单独函数,更方便阅读function isGameOver() {  return (    remaining === 0 ||    (remaining === 1 && remainingPlayers === 1) ||    remainingPlayers === 0  );}
function checkGameStatus() { if (isGameOver()) { quitGame(); }}

4. 判断处理逻辑正确的梳理方式

// 判断逻辑不要嵌套太深function checkStatus() {  if (isLogin()) {    if (isVip()) {      if (isDoubleCheck()) {        done();      } else {        throw new Error('不要重复点击');      }    } else {      throw new Error('不是会员');    }  } else {    throw new Error('未登录');  }}

这个是不是很熟悉呀~

没错,这就是使用 AI 工具 CR 的代码片段

通常这种,为了处理特殊状况,所实现的判断逻辑,都可以采用 “异常逻辑前置,正常逻辑后置” 的方式进行梳理优化

// 将判断逻辑的异常逻辑提前,将正常逻辑后置function checkStatus() {  if (!isLogin()) {    throw new Error('未登录');  }
if (!isVip()) { throw new Error('不是会员'); }
if (!isDoubleCheck()) { throw new Error('不要重复点击'); }
done();}

函数传参优化

// 形参有非常多个const getMyInfo = (  name,  age,  gender,  address,  phone,  email,) => {  // ...}

有时,形参有非常多个,这会造成什么问题呢?

  • 传实参是的时候,不仅需要知道传入参数的个数,还得知道传入顺序
  • 有些参数非必传,还要注意添加默认值,且编写的时候只能从形参的后面添加,很不方便
  • 所以啊,那么多的形参,会有很大的心智负担

怎么优化呢?

// 行参封装成对象,对象函数内部解构const getMyInfo = (options) => {  const { name, age, gender, address, phone, email } = options;  // ...}
getMyInfo( { name: '张三', age: 18, gender: '男', address: '北京', phone: '123456789', email: '[email protected]' })

你看这样是不是就清爽了很多了

命名注释优化

1. 避免魔法数字

// 魔法数字if (state === 1 || state === 2) {  // ...} else if (state === 3) {  // ...}

咋一看,这 1、2、3 又是什么意思啊?这是判断啥的?

语义就很不明确,当然,你也可以在旁边写注释

更优雅的做法是,将魔法数字改用常量

这样,其他人一看到常量名大概就知道,判断的是啥了

// 魔法数字改用常量const UNPUBLISHED = 1;const PUBLISHED = 2;const DELETED = 3;
if (state === UNPUBLISHED || state === PUBLISHED) { // ...} else if (state === DELETED) { // ...}

2. 注释别写只表面意思

注释的作用:提供代码没有提供的额外信息

// 无效注释let id = 1 // id 赋值为 1
// 有效注释,写业务逻辑 what & whylet id = 1 // 赋值文章 id 为 1

3. 合理利用命名空间缩短属性前缀

// 过长命名前缀class User {  userName;  userAge;  userPwd;
userLogin() { }; userRegister() { };}

如果我们把前面的类里面,变量名、函数名前面的 user 去掉

似乎,也一样能理解变量和函数名称所代表的意思

代码却,清爽了不少

// 利用命名空间缩短属性前缀class User {  name;  age;  pwd;
login() {}; register() {};}

分支逻辑优化

什么是分支逻辑呢?

使用 if else、switch case ... ,这些都是分支逻辑

// switch caseconst statusMap = (status: string) => {    switch(status) {        case 'success':            return 'SuccessFully'        case 'fail':            return 'failed'        case 'danger'            return 'dangerous'        case 'info'            return 'information'        case 'text'            return 'texts'        default:            return status    }}
// if elseconst statusMap = (status: string) => {    if(status === 'success') return 'SuccessFully'    else if (status === 'fail') return 'failed'else if (status === 'danger') return 'dangerous'    else if (status === 'info') return 'information'    else if (status === 'text') return 'texts'    else return status}

这些处理逻辑,我们可以采用 映射代替分支逻辑

// 使用映射进行优化const STATUS_MAP = {    'success': 'Successfull',    'fail': 'failed',    'warn': 'warning',    'danger': 'dangerous',    'info': 'information',    'text': 'texts'}
return STATUS_MAP[status] ?? status

【扩展】

?? TypeScript 中的 “空值合并操作符”

当前面的值为 null 或者 undefined 时,取后面的值

对象赋值优化

// 多个对像属性赋值const setStyle = () => {    content.body.head_style.style.color = 'red'    content.body.head_style.style.background = 'yellow'  content.body.head_style.style.width = '100px'  content.body.head_style.style.height = '300px'  // ...}

这样一个个赋值太麻烦了,全部放一起赋值不就行了

可能,有些同学就这样写

const setStyle = () => {  content.body.head_style.style = {      color: 'red',      background: 'yellow',      width: '100px',      height: '300px'    }}

咋一看,好像没问题了呀?那 style 要是有其他属性呢,其他属性不就直接没了吗~







请到「今天看啥」查看全文