如何做好CodeReview
CR 看什么:看核心功能的实现、看关键问题的实现。
TODO
熟悉 ES 新特性
TS 特性
前端常用的设计模式
从需求和数据结构入手
参考散点图的案例
数据驱动渲染
围绕交互+数据结构进行
【交互】是【操纵】【结构化】的【数据】
数据结构决定了你程序的输入和输出,因此数据结构确定了,剩下的就是填空题,就很容易了
数据结构设计得好不好取决于你对于框架(ECharts)和需求的理解程度
字段和属性都是要根据这 2 者来的
框架理解程度:
比如状态管理的案例
比如禁用交互:series.silent = true;
需求理解程度:
比如 history 的数据结构的设计
AI CodeReview
思路:
上传待 Review 的代码文件给大模型
让 LLM 对代码的功能、执行流程、架构设计进行分析
按照分析框架,从不同维度进行分析,检查基本问题
让 LLM 逐个文件指出问题,针对问题进行追问,并给出优化后的程序设计源码
框架
1 | |
功能说明
1 | |
执行流程
1 | |
架构设计
1 | |
可读性
关于命名,可以看下这个:classnames
1 | |
可扩展性/可维护性
1 | |
健壮性
1 | |
逐文件、逐问题分析
1 | |
CR 要点
https://zhuanlan.zhihu.com/p/111848763
差的要提出,好的要鼓励。
CR 不是一味的找茬。
Good CodeReview 会给出建设性意见,而不是发表强硬措辞要求对方改正,或认为自己的意见是唯一正确的答案,因为这样的评论其实具有一定攻击性,激发对方的防御心理,产生敌对心态,这样会从内部瓦解一个团队。最好能给出建议,或者多个选择,给对方留有余地。
Better CodeReview 永远是考虑全面且正向积极的,会对写的好的地方进行鼓励,对写的不好的地方也体现出善解人意的关怀,考虑到对方可能花费了很多心血,以一种换位思考的鼓励心态进行评论。
好的 CR 应该是这样的:
更全面,从正确性到系统影响评估。
注意语气,从给出建设性意见到换位思考。
及时完成审阅,从充分讨论到随机应变。
加强交流,从面对面交流到灵活选择最高效的沟通方式。
区分重点,从添加标记到利用工程化工具自动解决。
对新人要更友好。
审核的内容和标准,应该从历史问题中提取。
用苛刻的标准去做 CodeReview,从长期来看,带来的回报是很大的。
CodeReview 千万不能流于形式,否则就是浪费大家时间。
一个正常的程序员,应该有大约一半的时间花在 debug 上。
当你觉得功能已经基本实现的时候,这个项目大约就完成了一半了。
要想 CR 别人,首先自己得形成编码肌肉记忆,将编码需要注意的内容自己去实践足够多的次数,这样后面你看别人的代码,马上就能识别出是否有问题了。
另外针对印象深刻的 CR,一定要做好案例记录,这样才不至于后面遗忘了。
(精)编程到底难在哪里?
作者:阿莱克西斯
链接:https://www.zhihu.com/question/22508677/answer/276595266
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
- 做出来容易, 做正确难,这里做出来指没 bug 且完成需要的功能,这是最基本要求,不多加讨论。这里正确,不是指功能正确,而是指程序可以很容易推理理解,理解意图, 理解如何做到的,理解为什么系统不会出错。理解为什么要这么做。正确是现在怎么写不会挖坑害将来的人,现在怎么写能让别人1 年后看你代码时候不可能理解错你现在的意图,现在怎么写能在别人将来犯错的时候提示他你错了。
- 编程是给未来的未知人讲故事,你无法知道将来这个人是谁,他都懂什么,他经历过什么,这个系统将来已经是什么样子了。我们需要在这种无知,缺乏信息的情况下做决定,从千万种把这件事做出来的方法里,选出你觉得最能把这个故事给讲好的那种方式,把故事写下来。编程是一种沟通,沟通是一种艺术,用程序跨越时空之沟通则是一门属于程序员的特有的艺术(就好比数学家用数学公式来沟通) coding is all about the art of communication(引用)。
- 坏的决定会导致坏的决定,甚至导致人们去扭曲一个好的决定去迎合坏的决定。垃圾会制造垃圾,一个放在系统里不经清理的额外复杂度,会导致更多的额外复杂度的生成。
- 每个人甚至同一个人的不同时刻都有自己的不同的制造额外复杂度的缺陷,比如我每年去看去年自己写的代码,觉得都是垃圾。
我们所在的部门,所在的组,公司,它们的文化,到底是关心作出了一个东西,还是关心做好了一个东西。一个总是给系统添加垃圾,留坑给后人,但是能很快做出能跑起来的系统的程序员,我们到底认为他是做了好事还是做了坏事?我们到底认为他很强,还是他很弱?用超过必要而为了突显技术实力(或者练手)的复杂工具,技术框架搭建系统,做完跑路,在一个组,一个部门,一个公司,那里的文化,到底应该是鼓励还是抑制这种行为?我们又应该如何在一个环境中,去倡导推崇什么样的文化,相遇什么样的人?
人与文化,决定了什么人留在这里,什么人离开,什么人吸引什么人,什么人成长成什么样子。而设计/技术这些枝末细节则必顺应此中的人与文化而自然变化,或自愈,或走向毁灭;哪怕在恶劣的环境中,向下引导,向上规谏,潜移默化,最终改天换日,此为编程之大道也!**
(精)程序员的能力差距体现在哪里?
1、设计程序/方案时,是否能看到全景,是否会一叶障目
2、思维,用程序设计的方式解决问题,而不是用搬砖,累代码的方式解决问题,做苦力活儿
3、用抽象思维解决业务问题,实际世界的问题
思维模式,建模!
什么是干净的代码(Clean Code)
The Top 10 Tips to Write Clean Code - Software
如何快速提升编程能力?
高频重构
每隔 2 个月重构一次核心项目的核心代码。
我就重构 SD 和 VISALL,这才是我该干的活儿。
原则
每次 CodeReview 都必须有一个主题
参与 CR 的人,应该提前针对这个主题做好准备,不管是看代码也好,补充所需的知识点也好,这样才能保证 CR 的目的性明确、效率高。
评审模型
看核心问题、关键功能的实现。
- 这个需求的难点是什么?
- 核心的问题是什么?关键的功能是什么?
- 如何从程序设计角度解决这个难点的?
确定维度以及每个维度的标准。
就像现在的 CR 扫描工具,也是分了不同维度的。
要想深入 CR,还得了解业务才行。
流程
0、看一下README文档
1、看package.json文件,了解技术栈和依赖的库
2、讲一下整个程序的执行流程
3、看一下路由
4、看一下 HTTP 请求的处理
5、关键问题是什么,如何解决的,说下方案
检查点
静态资源,包括大小、依赖的包是否有冗余
卷面分
基础下限就是代码的“卷面分”
整体的架构图(有哪些模块、关联关系)
核心功能/问题的主要流程(流程图),比如图表渲染流程
全局功能的设计(路由、存储、接口)
边界情况是否考虑
极限值、无值、else 等情况
路由
路由怎么设计的?常见错误有哪些,是否都避免了?
API 接口的请求
是否有集中管理?
是否超时处理?
是否有异常提示?异常提示的交互是否友好?
存储
是否封装了统一的本地存储?
文件目录结构(每个目录的职责)
职责是否清晰?组件的管理?
模块的实现描述(参考期货的例子)
是否有按照设计去编码
通信机制
异常处理
异常上报,关键节点是否有针对性处理?
提示信息是否友好,用户是否可理解?
是否都有空值校验?
性能
打包的静态资源拆分问题,单个文件不大于 200K
第三方库是否有冗余,是否可以去掉一些依赖
是否存在类似操作调用多次,比如 localStorage 的存取?应该用变量缓存
动画卡顿,用 transform 替代直接修改 top 等属性,或者用图的方式来实现
HTTP1.1 有 6 个请求并发的限制(thsi.cn),建议静态资源 combo 合并
离线包的使用(先去了解下)
复用
该函数方法是否可复用,是否应该抽取放到其他地方?
端技巧
移动端用 viewport 替代 rem.js,基金 19 年全部换成了 viewport;rem.js 官方不维护了,推荐大家换成 viewport
下限问题
名、净、硬、释、短
代码是否都符合排版规范,是否看起来很干净?
冗余代码、注释掉的代码、调试用的 console 等,是否都删掉了?
命名问题,是否见文知意?
硬编码(数字、英文、中文等)
注释是否加了?是否可理解?
长代码:应该抽取封装
Vue 钩子函数的逻辑:应该只进行流程控制
编码规范(下限问题)
我们精力不应该放在这部分内容上,因此这部分 CR 应该借助工具来处理掉。
接入 ESLint 和 SonarLint、Pettier 即可,我们要做的是保证大家都去遵循这些规范。
程序设计
可以让开发人员先展示方案设计文档,然后对着文档讲解程序实现。
审核人员需要确认的内容包括:
- 方案是否合理
- 代码实现是否是完全按照方案设计来写的
什么样才是好的方案设计?
可调试性
日志
状态码
异常捕获与处理
文件结构
模块化是否合理
性能
对象缓存复用
比如该做单例处理的,没有做处理。
业务特性
平台兼容性
封装特定业务逻辑
比如股市的开盘、收盘
代码的坏味道
重复代码
过长函数/方法/类
触发点:注释、条件表达式、循环、GUI 类的数据和行为
特别是注释,看到注释就应该考虑提取函数了;且提取的函数应该基于这个注释去命名
缺乏数据对象的设计
前端开发是基于数据驱动行为的,所以应该有个数据实体的设计过程在里面。
这样也能避免长参数的问题。
if/else 和 switch/case
如果只是一个函数内部用到一次,那不用重构
如果多个地方都用到类似的 if/else 和 switch/case,则应该考虑用多态来优化了。
用过多的注释掩盖糟糕的代码
编程技巧
对方法分类:流程控制方法和逻辑实现方法
比如 Vue 的生命周期方法(created、mounted)就属于流程控制方法,里面就只应该进行其他方法的调用
对属性分类:计算属性、静态属性
比如我给海外组画横条柱状图的例子,里面我要计算圆角相关的 3 个点的坐标,总共一个图形元素有四个这样的点。
我一开始是这样设计的:
1 | |
而整个图形总共由 3 个图形元素构成,实际上我会将这四个属性计算 3 次。那么这种情况,这四个属性就是计算属性,不应该作为类的属性,而是应该在具体方法内部中,通过局部变量赋值即可:
1 | |
GUI 类,将数据和行为提取出去
这是前端开发人员经常遇到的问题。
前端页面经常不复用,就只能做这样的抽取,保证结构清晰,方便维护。
JS 最佳实践
《JavaScript 语言精粹》
Vue 最佳实践
不同项目的 Review 侧重点
业务代码
组件库
模板
形成自己的模板,这样才能融入自己的思考。
不同框架的 Review 侧重点
Vue 框架
参考官方风格指南 — Vue.js
1、从 views 下面看起
2、分为 DOM、JS、CSS 三大块
2.1 DOM 中是否正确理解了 Vue 的设计,是否有按照官方推荐的最佳实践去写?
2.2 JS 中,重点看业务逻辑是否存在隐患,特别是数据请求的异常处理、数据存取等;可复用的内容是否有抽取为组件库
2.3 CSS 是否考虑主题风格
比如:
1 | |
React
组件抽象是否合适?是否该抽成纯组件的没抽取?
状态数据放得是否合适(state & Redux)
如何 Review 其他组的人的代码
前置准备
了解对方的业务信息、主管评价、解决的核心问题
让对方提供能体现程序设计、解决核心难题的代码的目录
给我开通内网 GitLab 权限
Review 重点
程序设计
解决核心难题
如何对陌生代码做 Review-找到一个切入点
找到一个功能的入口文件,跟着程序流程走。
记录
2024.01.31
虚拟人 DYL:
1 | |
2023.12.28
失败的 Review,在不了解其业务的情况下,只能找问题。
1 | |
2023.12.25
1 | |
1 | |
2021.09.06
1 | |
参考资料
尤雨溪关于计算机基础的看法:
https://www.zhihu.com/question/35703265/answer/64229731
How to Make Good Code Reviews Better:
https://stackoverflow.blog/2019/09/30/how-to-make-good-code-reviews-better/
腾讯前端 CodeReview:
https://mp.weixin.qq.com/s/yyqGipUGMbfcLmXcQ2QBcA
长期软件开发:
https://berthub.eu/articles/posts/on-long-term-software-development/
1 | |
make it run, make it fast, make it beautiful.