宝,我今天CR了,C的什么R? 走过场的CR
原创:猿天地(微信公众号ID:cxytiandi),欢迎分享,转载请保留出处。
CodeReview我相信目前很多公司都会有这么一个流程,关键是这个流程有没有用就很难讲。主要还是取决于你对CR的理解以及有没有真正的去落地CR,去重视CR带来的隐藏价值点。
正好最近也是有人在问我CR相关的问题,他们也要开始做CR了,想了解下有没有最佳实践之类的。所以今天跟大家聊聊CR这个话题,我说的也不一定都是对的,仅供参考哈。
其实说实话,我觉得CR不存在什么最佳实践。因为每个公司或者说每个团队所进行的方式都会不一样,真正的想要做好CR只能先去做,在研发流程中去落地这个事情,然后慢慢的去提炼出符合你们团队的CR方式。
1.CR的目的
既然要做CR那肯定就有原因,CR的目的到底是什么?可以是走个流程,可以是提高代码能力,也可以是大家都在做,我也要做。我认为的目的有下面几个,请往下看。
1.1 稳定生产
大家想想,每个迭代开发完成后会进行测试,测试完成后就要发布到生产了。那么最有可能出现的问题就是你的新功能里面可能改到了老的逻辑,假设测试没有回归出来这个问题。那么一上线这个就影响到了生产的稳定性,所以CR最重要的目的就是稳定生产。
我们需要对代码进行CR,看看有没有改到老代码,会不会影响老的逻辑,有没有加开关呀,有没有兜底动作呀。因为一个团队里面总归会有新人进来,在不是很熟悉业务的情况下,很有可能就会改错,很有可能就会留下一个潜藏的Bug,这些都是需要CR去重点关注的。
上线可以,绝对不能影响到老版本,绝对不能出故障,否则你的绩效就凉凉了。你说你不想做CR,你的同事们会允许么,小伙子还是乖乖做CR吧!
1.2 间接培养backup
在管理团队的时候一定要注意培养backup,因为你也不知道下一个离开团队的人会是谁。互联网公司流动性还是挺大的,因为只有跳槽才能涨工资呀,我又说出了大家的心里话。
除了在明面上,可以指定谁作为某一块业务的owner,开发的时候由owner带着其他的人一起进行开发,这个过程中其实就有了backup,因为这一块业务知道的不在是某一个人了。
在台面下也要注意培养backup,此时CR就是一个很好的机会。CR的时候就可以让更多的人熟悉这些业务,但是方式一定要注意,不要光秃秃的只看代码,这样没参与开发的肯定是一个很懵的状态。可以在CR前让大家先大概的看下PRD,然后让CR的人讲解的时候不是一行行代码去Review, 先要讲自己这个迭代做的什么需求,有哪些功能,对应的代码就是现在CR的代码。这样才能让大家即了解业务又做了CR,一箭双雕。
当然,此时你会说,就算按照你说的方式进行CR,也不一定其他人就很熟悉了呀!这个是当然的,最熟悉的还是写代码的那个人嘛!但是我们让其他人有了一个大概的印象,假如后面写代码的那个人离职了,当有Bug要修的时候,其他人也是有映象当时这个功能的代码在哪里,我还记得CR过,我还提了一些建议。总比啥都不知道要强吧,你说对么?
1.3 提高代码质量
单纯从技术层面出发,CR的目的就是让大家来找茬,挑刺的。每个人的经验都不同,每个人的思路也不一样,往往你觉得这样写是最简单的方式,别人可能有更简单的方式去实现。
在CR的过程中,大家会提出自己的看法,实现的思路,代码是否写的够简洁,是否有开源框架能够直接实现某个功能,是否能否用设计模式进行优化,提高扩展性。领域建模是否合理,模块划分是否到位等等一系列的问题。
对于新人来说,能够得到很多有经验的同事在CR时给出的建议,对他的成长是很有帮助的。而且也会让你们的项目代码的质量一直维持在一个高的水平。这就是我们要做CR的目的,当然现实往往可能很残酷,很多项目到最后都会比较乱,代码也很臃肿,我想可能是当时被业务方倒排期,赶着要上线导致的吧!这种情况很常见,特别在创业型公司。
2.CR的方式
前面讲了几点我认为CR的目的,那么如何进行CR呢?常见的方式有哪些,来,接着往下看。
2.1 Gitlab
使用Gitlab做CR之前一般都是先提一个MR请求,然后针对这个请求做CR。这个MR请求里面所有的变动就是我们需要CR的点,如果有什么需要修改的可以在对应的代码处增加备注,CR结束之后各自根据当时的备注去修改。
2.2 开发工具
在我们的开发工具中直接进行CR也是非常的方便,好处在于可以看到整个功能的所有代码,就是你可以跟着业务的流程去讲解对应的代码。然后也可以很清楚的对比出哪些是你自己的改动,哪些是老的代码。
3.CR的时机
3.1 提测之前
在提测之前是最好的CR时机,这个时候我们有需要改进的再CR之后就直接改掉了。然后提测的时候就已经是我们改过之后的代码了,也许就减少了很多Bug,测起来也如丝般顺滑。
提测之前就CR影响的是什么?是我们的开发时间,本来开发完成之后就马上提测的,但是要在提测前进行CR,除非你的开发进度提前,否则还没开发完怎么做CR?
这个其实就是我们上面讲的流程了,将CR融入到研发流程中去,这样就可以在评估时间的时候给CR留出一天的buffer,比如11号要提测,那么10号就CR, 9号就是开发完成。
3.2 提测之后
提测之后做CR其实很不好,我们之前也有这样做过,做完之后立马改成了提测之前。因为在做的过程中会提出一些需要修改的点,然后这些点有可能测试已经测完了。然后你又改了,导致产生了新的Bug,增加了测试的工作量。
甚至还有一次是CR时候当场改的,然后没注意直接提交了,也没跟测试同步。第二天发生产环境直接出Bug了,所以一定不要在提测之后临近上线之前进行CR。
再举一个列子,之前有个团队老是喜欢在上线当天进行CR,测试已经再整体回归了,他们还在CR。当然有没有改动代码我不太清楚,因为不是一个团队,但是最严重的是回归的时候是有Bug的,需要及时修复。然后找不到人修,他们去CR了,也没人关注。导致的结果就是每次上线都要搞到好晚。
3.3 上线之后
上线之后就更不要CR了,你上线之后CR有什么意义呢?代码都发布了,这个时候CR出来的问题改还是不改呢?下个迭代改吗?下个迭代改完是不是又要回归一次,测试愿意么?
正所谓今日事今日毕,当前迭代的事情就在当前迭代解决,否则就是堆积如山了。
总结
对于CR我们还是要积极的拥抱,去落地,去实践。看上去会花费一部分时间,但带来的收益还是很不错的。项目的代码质量提高了,团队的技术氛围变好了,线上Bug明显变少了,大家对业务更熟悉了。
如果你们没有CR,请把这篇文章刷给你老板,就是这么任性。
如果对你有用,来个转发呗!
关于作者:尹吉欢,简单的技术爱好者,《Spring Cloud微服务-全栈技术与案例解析》, 《Spring Cloud微服务 入门 实战与进阶》作者, 公众号猿天地发起人。
宝,我今天CR了,C的什么R? 走过场的CR的更多相关文章
- LOJ 3055 「HNOI2019」JOJO—— kmp自动机+主席树
题目:https://loj.ac/problem/3055 先写了暴力.本来想的是 n<=300 的那个在树上暴力维护好整个字符串, x=1 的那个用主席树维护好字符串和 nxt 数组.但 x ...
- LOJ 2586 「APIO2018」选圆圈——KD树
题目:https://loj.ac/problem/2586 只会 19 分的暴力. y 都相等,仍然按直径从大到小做.如果当前圆没有被删除,那么用线段树把 [ x-r , x+r ] 都打上它的标记 ...
- 洛谷 4364 [九省联考2018]IIIDX——“预留”的思路
题目:https://www.luogu.org/problemnew/show/P4364 原来想了一个错误的思路,就是这样: solve( cr , l , r ) 表示 cr 为根的子树填 [ ...
- bzoj 2850 巧克力王国——KDtree
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2850 改一下估价即可.判断子树能否整个取或者是否整个不能取,时间好像就能行了? 因为有负数, ...
- bzoj 2716 [Violet 3]天使玩偶——KDtree
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2716 第三道KDtree!仍旧是模板.还有CDQ分治做法,见下面. 数组迷之开大?(开6e5 ...
- bzoj 1941 [Sdoi2010]Hide and Seek——KDtree
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1941 第二道KDtree! 枚举每个点,求出距离它的最远和最近距离.O( n * logn ...
- bzoj 2238 Mst——树链剖分
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2238 一条非树边可以对一条链的树边产生影响.注意是边,所以把边下放到点上,只要跳 top 时 ...
- [考试反思]1112csp-s模拟测试111:二重
还是AK场.考前信心赛? 而且T3的部分分还放反了所有80的都其实只有50. 总算在AK场真正AK了一次... 手感好,整场考试很顺利.要不是因为T3是原题可能就没这么好看了. 20minT1,50m ...
- Oracle中的CR块详解
1.概述 Cr块consistent read块也就是用来维护oracle的读一致性的数据块.当查询某些数据的时候,发现数据块的版本比我们要查询的新,例如session1执行了dml操作并没有提交,s ...
随机推荐
- 线程本地存储(动态TLS和静态TLS)
线程本地存储(TLS) 对于多线程应用程序,如果线程过于依赖全局变量和静态局部变量就会产生线程安全问题.也就是一个线程的使用全局变量可能会影响到其他也使用此全局变量的线程,有可能会造成一定的错误,这可 ...
- 【敏杰开发】Beta阶段项目展示
[敏杰开发]Beta阶段项目展示 项目相关地址汇总 线上地址:http://roadmap.imcoming.top 前端仓库:https://github.com/MinJieDev/Roadmap ...
- JAVA并发(1)-AQS(亿点细节)
AQS(AbstractQueuedSynchronizer), 可以说的夸张点,并发包中的几乎所有类都是基于AQS的. 一起揭开AQS的面纱 1. 介绍 为依赖 FIFO阻塞队列 的阻塞锁和相关同步 ...
- 变量覆盖-高级篇(动态覆盖,extract综合)
0x00 原理 变量覆盖漏洞可以让用户定义的变量值覆盖原有程序变量,可控制原程序逻辑. 0x01 代码 <?php highlight_file('index.php'); function ...
- Linux信号与golang中的捕获处理
什么是信号 在计算机科学中,信号是Unix.类Unix以及其他POSIX兼容的操作系统中进程间通讯的一种有限制的方式.它是一种异步的通知机制,用来提醒进程一个事件已经发生. 当一个信号发送给一个进程, ...
- micro 从cli的tag中获取配置
官方文档: https://micro.mu/docs/go-config.html https://github.com/micro/go-micro/tree/master/config/sour ...
- CentOS 7配置静态IP地址的两种方法 来自:互联网
CentOS 7配置静态IP地址的两种方法 来自:互联网 时间:2021-01-12 阅读:4 如果你想要为CentOS 7中的某个网络接口设置静态IP地址,有几种不同的方法,这取决于你是否想要使用网 ...
- 说明位图,矢量图,像素,分辨率,PPI,DPI?
说明位图,矢量图,像素,分辨率,PPI,DPI? 显示全部 关注者 28 被浏览 7,031 关注问题写回答 邀请回答 添加评论 分享 2 个回答 默认排序 刘凯 21 人赞同了 ...
- 010.Python字符串的格式化
字符串的格式化 顺序传参 索引传参 关键字传参 容器类型传参(列表和元组) {}相当于占位符 1 顺序传参 strvar = "他{}牺牲自己,{}出卖组织" res = strv ...
- 第14讲 | HTTP协议:看个新闻原来这么麻烦
第14讲 | HTTP协议:看个新闻原来这么麻烦 http://www.163.com 是个 URL,叫作统一资源定位符. 之所以叫统一,是因为它是有格式的.HTTP 称为协议,www.163.com ...