日常开发为什么需要做Code Review
日常开发为什么需要做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中的一些知识点,可以选择性的阅读。
-
代码是否按照lint规范提交,以及其他约定的一些规范提交
至关重要的检查,lint可以省掉很多review内容,可能有时,一些比较着急的开发者会提交代码时使用
-n命令忽略检查进行提交 -
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); -
不要出现大文件,大文件增加分组进行拆分,按照业务模块分组或者extends继承机制处理
超过1000行的文件出现bug,你会去看吗?你会很轻松的找到问题所在吗?答案肯定是不会,因为那么多行代码需要检查,而且也没有信息完全肯定能够修改正常,那肯定得避免出现这种文件,方便自己以及后面有其他同事接手这个项目时,能够不会有那么多的心理负担「🐶」
-
双map或forEach遍历时,可能需要考虑优化
出现这种情况的常见算法一般都是先找出数组中固定的某一个值,然后在用这个值去做业务逻辑,这样可能得和业务人员确定是否存在更加优化的处理方案,比如下面是用了es6中结构赋值的方案去减少了一次检索的过程,这种双循环的,一般都仔细检查下看看是否有优化方案
// 使用解构赋值的模型,减少map循环的使用 (lists || []).map(({ person: name }) => {// 使用name在进行处理其他业务逻辑// name }) -
默认的空赋值[]或者{}
正常来说,比如子组件的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被赋予为空数组时也能让前后引用相同。
-
使用 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 }) }) -
addListener事件命名建议采用【模块_特性_名称】,采用全局较为统一的规范
如:LOGIN_STATUS_CHANGE,LOGOUT_STATUS_CHANGE -
使用useFocusEffect注意配合使用useCallback,否则会造成多次渲染
-
默块引入使用路径别名,抽取行内样式
-
Platform.select 和 Platform.OS区分,针对平台比较复杂的逻辑,使用平台判断Platform.select的方案处理
-
react-native元素标签逻辑判断问题
isShow逻辑判断使用!!isShow转义后进行使用,否则会提示文本必须在Text元素中使用的提示信息<View style={styles.fastContainer}>{!!isShow && <View></View>} </View> -
使用setTimeout、setInterval等伪代码时,需要在组件卸载时或关闭操作时将其清除掉
● setTimeout的销毁函数为clearTimeout
● setInterval的销毁函数为clearInterval
对于多次打开的setTimeout,setInterval需要在再次开启时清空其值clearmyTime: () => void = () => {// eslint-disable-next-lineif (!!this.myTimeout) {clearTimeout(this.myTimeout);this.myTimeout = null;} };onSelected = () => {// 每次开启新的延迟计时器时,都进行清空操作this.clearmyTime();this.myTimeout = setTimeout(() => {// 操作}, 1000) } -
数组遍历需要考虑使用useMemo处理
map,filter等方法,以及lodash中的遍历方法,都需要使用useMemo进行处理 -
数值类比较操作
receive < 0 ? 0 : receive,可以考虑使用数学方法const value = receive < 0 ? 0 : receive; // 等同于 const value = Math.max(receive, 0); -
保证key唯一,不要使用数组遍历产生的index,方便虚拟dom diff,提升性能

相关文章:
日常开发为什么需要做Code Review
日常开发为什么需要做Code Review 一、背景 最近在开始一个新的项目,在查看项目中代码及具体细节时,发现这个项目真实一堆乱麻,没有规律可循,可总结下这个项目的缺陷 没有规律可循,没有结构性设计不做公共封装&#…...
OSPF的优化
O_ASE --- 标志域外路由信息 --- 因为域外的路由信息不可控性较强,所以,信任程度较低,我们将其优先级设置为150。 LSA --- 链路状态通告 --- OSPF协议在不同网络环境下产生的用于携带和传递不同的信息。 LSDB --- 链路状态数据库 SPF --- 最短…...
C++项目中打破循环依赖的锁链:实用方法大全
C项目中打破循环依赖的锁链 一、简介(Introduction)1.1 循环依赖的定义(Definition of Circular Dependencies)1.2 循环依赖带来的问题(Problems Caused by Circular Dependencies)1.3 解决循环依赖的重要性…...
IDEA连接HBase
新建maven工程 打开pom.xml添加hbase需要的依赖 <dependency><groupId>org.apache.hbase</groupId><artifactId>hbase-client</artifactId><version>2.3.5</version> </dependency><dependency><groupId>org.apa…...
Mask2Former来了!用于通用图像分割的 Masked-attention Mask Transformer
原理https://blog.csdn.net/bikahuli/article/details/121991697 源码解析 论文地址:http://arxiv.org/abs/2112.01527 项目地址:https://bowenc0221.github.io/mask2former Mask2Former的整体架构由三个组件组成: 主干特征提取器ÿ…...
【量化课程】01_投资与量化投资
文章目录 1.1 什么是投资1.1.1 经济意义上的投资1.1.2 投资的分类1.1.3 金融投资1.1.4 个人投资者投资品种1.1.5 投资VS投机 1.2 股票投资的基本流程1.3 常见的股票投资分析流派1.3.1 投资者分析流派 1.4 什么是量化投资1.4.1 量化投资基本概念1.4.2 量化投资的优势1.4.3 量化投…...
SpringBoot实现导出Excel功能
1 问题背景 需求要做一个导出excel的功能 2 前言 本篇着重阐述后端怎么实现,前端实现的部分只会粗略阐述。该实现方案是经过生产环境考验的,不是那些拿来练手的小demo。本文阐述的方案可以借鉴用来做毕设或者加到自己玩的项目中去。再次声明,…...
NSSCTF之Misc篇刷题记录⑧
NSSCTF之Misc篇刷题记录 [MMACTF 2015]welcome[广东强网杯 2021 团队组]欢迎参加强网杯[虎符CTF 2022]Plain Text[SWPUCTF 2021 新生赛]原来你也玩原神[SWPUCTF 2021 新生赛]我flag呢?[鹤城杯 2021]New MISC NSSCTF平台:https://www.nssctf.cn/ PS&…...
从零开始学习Linux运维,成为IT领域翘楚(七)
文章目录 🔥Linux下常用软件安装_JDK和Tomcat安装🔥Linux下常用软件安装_MySQL安装🔥Linux下常用软件安装_MySQL卸载 🔥Linux下常用软件安装_JDK和Tomcat安装 Jdk 安装 解压jdk安装包 tar -zxvf jdk-8u201-linux-x64.tar.gz -C/…...
优漫动游设计APP的UI界面需要注意哪些问题?
一、加载 加载时间的长短,很大程度的决定了用户体验是否有所提升,虽然理想中的页面加载出来应该一秒就够了,但是设计师不要忽略网络问题!如果网速不够的话,页面加载三五秒都算是快的了,所以在用户等待的过程中&a…...
面试 004
什么是 Java 内存结构 Java 内存结构就是 JVM 的运行书数据区的内存结构: 里面有堆、虚拟机栈、本地方法栈、程序计数器; 虚拟机栈:里面的数据结构是栈帧,存放了方法名,局部变量等信息 方法区在 1.8 的时候…...
CCF-202206-2-寻宝!大冒险!
目录 题目背景 问题描述 一、思路: 二、实现方法(C) 2.1、方法一(int储存) 思路: C实现如下: 2.2、方法二(结构体储存) 思路: 注意:边界…...
二叉搜索树中的众数
1题目 给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。 如果树中有不止一个众数,可以按 任意顺序 返回。 假定 BST 满足如下定义&…...
认识JSP
什么是JSP? JSP(Java Server Pages)是一种类似于HTML的标记语言,用于创建动态Web页面。与HTML不同的是,JSP页面中可以嵌入Java代码,由Web服务器在动态页面中生成HTML代码,从而实现Web应用程序的前端交互效…...
MySQL数据管理
一、MySQL数据库管理 1、库和表 行(记录):用来描述一个对象的信息 列(字段):用来描述对象的一个属性 2、常用的数据类型 int :整型 float :单精度浮点 4字节32位 double &…...
第十九章 Unity 其他 API
本节介绍一些其他经常使用的Unity类。首先,我们回顾一下Vector3向量类,它既可以表示方向,也可以表示大小。它在游戏中可以用来表示角色的位置,物体的移动/旋转,设置两个游戏对象之间的距离。在我们之前的课程中&#x…...
sha256算法详解,用C语言模拟sha256算法
SHA-256是一种加密算法,它可以将任意长度的数据块计算出一个固定长度的输出值,通常是256位。SHA-256具有以下特点: 1. 固定输出长度:SHA-256的输出长度为256位,不受输入数据的长度限制。 2. 不可逆性:SHA-256采用单向哈希函数,即无法从输出值反向推出输入数据。 3. 抗…...
前端技术未来发展展望
前端技术在未来的发展中将继续保持快速、变化多样和创新性强的趋势。以下是我认为前端技术未来发展的几个方向: 框架和库的演进:框架和库的更新换代将继续加速。React、Vue、Angular等主流框架的更新周期将会缩短,同时各自的生态系统也将更加…...
第四十六天|dp
今天的题还是完全背包的题 139. Word Break 这道题其实用deque也能做,但是需要cache去记录之前尝试过的值,.相对简单的办法就是用完全背包了 这道题worddict就是物品.我们的dp[i]代表到i为止是不是能满足题意分成segmentation 处置化全为false,但是dp[0]True.这是因为为0时…...
汇编语言-复习自用
本文用于自我复习汇编语言,参考b站一位老师的讲解整理而成,感谢老师的无私付出视频链接链接 文章目录 1.第一章1.1计算机组成1.2读取1.3 寄存器及数据存储1.4 mov和and指令1.5 确定物理地址1.6 内存分段表示法1.7debug使用1.8CS:IP1.9jmp指令改变csip1.1…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
