日常开发为什么需要做Code Review

news2024/11/24 5:09:09

日常开发为什么需要做Code Review

在这里插入图片描述

一、背景

最近在开始一个新的项目,在查看项目中代码及具体细节时,发现这个项目真实一堆乱麻,没有规律可循,可总结下这个项目的缺陷

  • 没有规律可循,没有结构性设计
  • 不做公共封装,哪里方便哪里创建变量
  • 一个个文件大于300行,都是超大文件,组件中方法超大逻辑
  • class组件部分逻辑可继承封装,但是采取了复制粘贴相同代码的处理

看的我是一堆乱麻,不由得让我开始思考,程序员果真是懒,如果再勤快一些,可能会进行代码的封装和考虑这些公用方法及组件的抽取,同时也存在项目中Code Review 的缺失。

二、为什么需要Code Review 及优点

看这些奇奇怪怪的代码,不由得让我拍脑袋直言,当初多进行进行Code Review ,将这些问题屏蔽掉至少,那Code Review 有哪些优点呢

进行代码审查的原因可以归结为以下几点:

  • 提高代码质量: 可以帮助开发者更好地编写代码,减少错误和缺陷,提高代码的质量和可维护性。通过Code Review ,开发者可以识别并修复潜在的问题,从而提高代码的可靠性和稳定性。

  • 减少错误率:通过代码审查,开发人员可以发现之前可能没有注意到的错误或缺陷,从而减少错误的发生。

  • 促进团队协作: 可以帮助团队成员之间更好地协作,不仅仅是老员工之间的协作,而且更加有效的帮助新员工融入到团队中,确保代码的一致性和可重用性。通过 Code Review ,开发者可以更好地理解其他开发者的代码,并从中学习,从而提高自己的编程水平。

  • 提高开发效率: 可以帮助开发者更快地完成任务,减少代码编写的时间。通过 Code Review ,开发者可以更快地发现和解决问题,从而减少调试的时间和工作量。

  • 确保代码符合规范: 可以帮助开发者遵循团队的代码规范,确保代码的可读性和可维护性。这对于大型项目的开发非常重要,因为遵循规范可以帮助开发者更好地协作和理解代码。

综上所述,Code Review 对于前端开发的质量和效率都非常重要。通过 Code Review ,开发者可以更好地编写代码,提高代码的质量和可维护性,促进团队协作,提高开发效率和确保代码符合规范。

三、Code Review 都有哪些方式

总体来说可分为常规代码Code Review阻断式Code Review

  • 常规代码Code Review
    提出修改建议与检查,不阻断代码合并或者影响开发者其他进度的检查
    通常这种检查会是团队成员聚集在一起,听其他成员讲述自己最近的开发代码。
  • 阻断式Code Review
    需要合并进主分支等,需要必须要求复合规定时的检查,必须等待处理完所有建议或者不符合规定的点之后才能合并进主分支

四、Code Review 都会去注意哪些点

既然要做Code Review,那应该去检查哪些细节,我举个我开发中遇到的一些例子,给大家打个样,开发层更多地涉及到React Native中的一些知识点,可以选择性的阅读。

  1. 代码是否按照lint规范提交,以及其他约定的一些规范提交

    至关重要的检查,lint可以省掉很多review内容,可能有时,一些比较着急的开发者会提交代码时使用-n命令忽略检查进行提交

  2. useSelector使用规则,优化页面性能
    使用redux的同学可能会知道,useSelector会导致页面重新渲染,这边也就成为了日常review的一项

    const kfo = useSelector((state) => state.AtReducer.kfo || {}); 
    
    

    不规范原因: useSelector 底层是使用 === 比较 此处|| {}代码逻辑上容易触发render更新;
    建议改为以下写法

    const kfo = useSelector( (state) => state.AtReducer.kfo ) || {}
    

    使用useSelector时也需要关注state的粒度,导出自己需要的变量,不要一下子导出state.userInfo整个变量,同时使用shallowEqual进行比对处理

      const { username, age } = useSelector(state => { 
        const { username, age } = state.userInfo;
        return { username, age }; 
      }), shallowEqual);
    
  3. 不要出现大文件,大文件增加分组进行拆分,按照业务模块分组或者extends继承机制处理

    超过1000行的文件出现bug,你会去看吗?你会很轻松的找到问题所在吗?答案肯定是不会,因为那么多行代码需要检查,而且也没有信息完全肯定能够修改正常,那肯定得避免出现这种文件,方便自己以及后面有其他同事接手这个项目时,能够不会有那么多的心理负担「🐶」

  4. 双map或forEach遍历时,可能需要考虑优化

    出现这种情况的常见算法一般都是先找出数组中固定的某一个值,然后在用这个值去做业务逻辑,这样可能得和业务人员确定是否存在更加优化的处理方案,比如下面是用了es6中结构赋值的方案去减少了一次检索的过程,这种双循环的,一般都仔细检查下看看是否有优化方案

      // 使用解构赋值的模型,减少map循环的使用
    (lists || []).map(({ person: name }) => {
     // 使用name在进行处理其他业务逻辑
     // name
    })
    
  5. 默认的空赋值[]或者{}

    正常来说,比如子组件的userList属性规定类型是数组,在父组件加工数据时提供数据默认值是非常好的习惯,于是我常常在组件内部或者mapStateToProps中看到类似的写法:

    const App = (props) => { 
      // 当存在时赋予空数组,保证下层数组类型的正确性 
      const userList = props.userList || []; 
      return (<Child userList={userList} />) 
    }; 
    

    当App多次渲染且props.userList为假值时,此时的userList也会被不断的赋予全新的空数组。还记得前文说的吗,当你结构没变化时,我们保证其引用不变不就好了,所以对于空数组都可以在全局赋予一个空数组,比如:

    const emptyArr = []; 
    const App = (props) => { 
      // 当存在时赋予空数组,保证下层数组类型的正确性 
      const userList = props.userList || emptyArr;
      return (<Child userList={userList} />)
    }; 
    

    这样不管App如何渲染,当userList被赋予为空数组时也能让前后引用相同。

  6. 使用 DeviceEventEmitter.addListener( ‘CHANGE’, function () {})注意依赖的项目可能不为最新值问题

    const ref = useRef();
     const listenerChange = () => {
       dispatch(FetchConfig({ jwtKey: userInfo?.jwtKey }, (dataList) => {
         setKols(dataList);
       }));
     }
     ref.current = listenerChange;
    
    
     useEffect((): function => {
       const listener = DeviceEventEmitter.addListener(
         'CHANGE',
         function () {
           ref.current?.();
         }
       )
       return () => {
         listener?.remove?.();
       };
     }, []);
    

    如果参数存在于延迟setTimeout,同时依赖于变量,也需要考虑通过以上方案处理,看看下面栗子🌰

    const [jwt] = useState('');
    
    
    setTimeout(() => {
      DeviceEventEmitter.emit('send',{ jwt: jwt })
    })
    
  7. addListener事件命名建议采用【模块_特性_名称】,采用全局较为统一的规范
    如:LOGIN_STATUS_CHANGE,LOGOUT_STATUS_CHANGE

  8. 使用useFocusEffect注意配合使用useCallback,否则会造成多次渲染

  9. 默块引入使用路径别名,抽取行内样式

  10. Platform.select 和 Platform.OS区分,针对平台比较复杂的逻辑,使用平台判断Platform.select的方案处理

  11. react-native元素标签逻辑判断问题
    isShow逻辑判断使用!!isShow转义后进行使用,否则会提示文本必须在Text元素中使用的提示信息

    <View style={styles.fastContainer}>
      {!!isShow && <View></View>}
    </View>
    
  12. 使用setTimeout、setInterval等伪代码时,需要在组件卸载时或关闭操作时将其清除掉
    ● setTimeout的销毁函数为clearTimeout
    ● setInterval的销毁函数为clearInterval
    对于多次打开的setTimeout,setInterval需要在再次开启时清空其值

    clearmyTime: () => void = () => {
      // eslint-disable-next-line
      if (!!this.myTimeout) {
        clearTimeout(this.myTimeout);
        this.myTimeout = null;
      }
    };
    
    onSelected = () => {
      // 每次开启新的延迟计时器时,都进行清空操作
      this.clearmyTime();
    
      this.myTimeout = setTimeout(() => {
        // 操作
      }, 1000)
    }
    
  13. 数组遍历需要考虑使用useMemo处理
    map,filter等方法,以及lodash中的遍历方法,都需要使用useMemo进行处理

  14. 数值类比较操作 receive < 0 ? 0 : receive,可以考虑使用数学方法

    const value = receive < 0 ? 0 : receive;
    // 等同于
    const value = Math.max(receive, 0);
    
  15. 保证key唯一,不要使用数组遍历产生的index,方便虚拟dom diff,提升性能


在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/489802.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

08_Uboot顶层Makefile分析_make过程

目录 make 过程 make 过程 配置好 uboot 以后就可以直接make 编译了,因为没有指明目标,所以会使用默认目标,主 Makefile 中的默认目标如下: 目标_all 又依赖于all,如下所示: 如果KBUILD_EXTMOD为空的话_all 依 赖 于all 。这 里 不 编 译 模 块,所 以KBUILD_EXTMOD肯定为空,_…

二分分类.

2.1 二分分类 在神经网络的计算中&#xff0c;通常先有一个叫做前向暂停(forward pause)或叫做前向传 播(foward propagation)的步骤&#xff0c;接着有一个叫做反向暂停(backward pause) 或叫做反向传播 (backward propagation)的步骤。 一张图片在计算机中是如何表示的&…

4。计算机组成原理(1)数据表示和运算

嵌入式软件开发&#xff0c;非科班专业必须掌握的基本计算机知识 核心知识点&#xff1a;数据表示和运算、存储系统、指令系统、总线系统、中央处理器、输入输出系统 一 进位计数法和不同进制数的相互转换 其他进制(b)&#xff0c;转十进制的计算公式 十进制数&#xff0c;转…

Linux系统编程——多线程[上]:线程概念和线程控制

目录 1.再谈页表 2.Linux线程概念 2.1pthread原生库的基本使用 2.2PID和LWP 2.3Linux线程的资源以及优缺点 2.4Linux线程健壮性问题 2.5可重入函数和线程独立栈 3.Linux线程控制 3.1Linux线程终止 3.2Linux线程等待 3.3线程取消 3.4线程分离 使用线程库的注意事项…

【Python入门】Python基础语法

前言 &#x1f4d5;作者简介&#xff1a;热爱跑步的恒川&#xff0c;致力于C/C、Java、Python等多编程语言&#xff0c;热爱跑步&#xff0c;喜爱音乐的一位博主。 &#x1f4d7;本文收录于Python零基础入门系列&#xff0c;本专栏主要内容为Python基础语法、判断、循环语句、函…

净利润同比增长48.9%,中国平安“一览众山小”

中国平安价值迸发的速度&#xff0c;或许超过了所有人的想象。 4月26日晚&#xff0c;中国平安发布2023年一季度业绩报告&#xff0c;许多自媒体用“炸裂”来形容其亮眼的财务数据。财报显示&#xff0c;第一季度&#xff0c;集团实现营收2537.78亿元&#xff0c;同比增长30.8…

农机电招平台~java

摘要 随着农机电招行业的不断发展&#xff0c;农机电招在现实生活中的使用和普及&#xff0c;农机电招行业成为近年内出现的一个新行业&#xff0c;并且能够成为大群众广为认可和接受的行为和选择。设计农机电招平台的目的就是借助计算机让复杂的销售操作变简单&#xff0c;变…

LeetCode:383. 赎金信

&#x1f34e;道阻且长&#xff0c;行则将至。&#x1f353; &#x1f33b;算法&#xff0c;不如说它是一种思考方式&#x1f340; 算法专栏&#xff1a; &#x1f449;&#x1f3fb;123 题解目录 一、&#x1f331;[383. 赎金信](https://leetcode.cn/problems/ransom-note/)…

DOM概述

DOM概述 什么是DOM对象树化的DOM模型DOM 节点 如何获取DOM元素如何更改我们的DOM模型常用属性修改控制样式属性 事件事件监听 事件类型鼠标事件键盘事件焦点事件文本框输入事件 事件对象回调函数DOM 节点插入节点插入节点删除节点查找节点父子关系兄弟关系 什么是DOM 当网页被…

SPSS如何进行因子分析和主成分分析之案例实训?

文章目录 0.引言1.因子分析2.主成分分析 0.引言 因科研等多场景需要进行绘图处理&#xff0c;笔者对SPSS进行了学习&#xff0c;本文通过《SPSS统计分析从入门到精通》及其配套素材结合网上相关资料进行学习笔记总结&#xff0c;本文对因子分析和主成分分析进行阐述。 1.因子分…

Android:LeakCanary原理的简单理解和使用

LeakCanary原理的简单理解和使用 1、背景2、LeakCanary2.1、LeakCanary 工作原理2.1.1、检测未被 GC 回收的对象2.1.2、转储堆2.1.3、分析堆2.1.4、对泄漏进行分类 2.2、LeakCanary 使用2.2.1、引入依赖2.2.1.1、原理 2.2.2、配置 LeakCanary2.2.3、检测内存泄漏 3、Fragment 和…

Hystrix断路器 (豪猪)-保险丝

一、概述 重点&#xff1a;能让服务的调用方&#xff0c;够快的知道被调方挂了&#xff01;不至于说让用户在等待。 Hystix 是 Netflix 开源的一个延迟和容错库&#xff0c;用于隔离访问远程服务、第三方库&#xff0c;防止出现级联失败&#xff08;雪崩&#xff09;。 雪崩&am…

自动驾驶行业观察之2023上海车展-----车企发展趋势(2)

自主品牌发展 比亚迪&#xff1a;展示3款新车&#xff0c;均于2023年年内上市 比亚迪在本次展会上推出了3款新车&#xff1a;宋L概念车&#xff08;王朝系列&#xff09;、驱逐舰07&#xff08;海洋系列&#xff09;、海鸥&#xff08;海洋系列&#xff09;。 • 宋L&#x…

FreeRTOS:任务的创建和删除

目录 一、函数xTaskCreate二、函数xTaskCreateStatic三、函数xTaskCreateRestricted四、函数vTaskDelete五、任务创建和删除&#xff08;动态&#xff09;代码5.1实验要求5.2程序代码 一、函数xTaskCreate 此函数用来创建一个任务&#xff0c;任务需要RAM来保存与任务有关的状…

Mysql数据库基本操作(增删改查)

目录 一、数据库的基本操作1.1 登录数据库1.2 创建数据库并进入数据库 二、查看数据库结构2.1 查看数据库信息2.2 查看数据库中包含的表及表结构2.3、常用的数据库类型 三、Mysql数据文件3.1 MYD文件3.2 MYI文件3.3 MyISAM存储引擎 四、SQL 语句1、 DDL数据定义语言1.1 删除指定…

〖Python网络爬虫实战㉒〗- 数据存储之数据库详解

订阅&#xff1a;新手可以订阅我的其他专栏。免费阶段订阅量1000 python项目实战 Python编程基础教程系列&#xff08;零基础小白搬砖逆袭) 说明&#xff1a;本专栏持续更新中&#xff0c;目前专栏免费订阅&#xff0c;在转为付费专栏前订阅本专栏的&#xff0c;可以免费订阅付…

Eureka、Zookeeper、Consul服务注册与发现

一、Eureka服务注册与发现 1.1 概念 Eureka 是 Netflix 公司开源的一个服务注册与发现的组件 。 Eureka 和其他 Netflix 公司的服务组件&#xff08;例如负载均衡、熔断器、网关等&#xff09; 一起&#xff0c;被 Spring Cloud 社区整合为Spring-Cloud-Netflix 模块。 Eure…

校招失败后,在小公司熬了 2 年终于进了百度,竭尽全力....

其实两年前校招的时候就往百度投了一次简历&#xff0c;结果很明显凉了&#xff0c;随后这个理想就被暂时放下了&#xff0c;但是这个种子一直埋在心里这两年除了工作以外&#xff0c;也会坚持写博客&#xff0c;也因此结识了很多优秀的小伙伴&#xff0c;从他们身上学到了特别…

【JavaEE】TCP协议的十大原理保姆讲解(Transmission Control Protocol)

博主简介&#xff1a;想进大厂的打工人博主主页&#xff1a;xyk:所属专栏: JavaEE初阶 上一篇文章讲了UDP协议&#xff0c;那么这篇文章我来讲讲TCP协议&#xff0c;TCP协议相对UDP协议难一些&#xff0c;内容相对更多。 TCP&#xff0c;即Transmission Control Protocol&…

AArch32 AArch64 Registers map详细解析与索引

1、AArch32 Registers AArch32 系统寄存器索引。 例如第一个寄存器ACTLR点击后解析如下&#xff1a; 2、AArch64 Registers AArch64 系统寄存器索引。 3、AArch32 Operations AArch32 系统指令索引。 例如第一个寄存器ACTLR_EL1点击后解析如下&#xff1a; 4、AArch…