当前位置: 首页 > 科技观察

干货分享:六招教你有效进行代码审查

时间:2023-03-14 22:58:08 科技观察

研发同学都知道代码审查的重要性,腾讯代码审查也越来越受到大家的关注。作为腾讯自有云平台研发的一员,我参与了很多代码审查,可见有效的代码审查不仅可以提升代码质量,还可以促进团队沟通协作,建立更高的工程质量标准,对个人和团队都具有重要价值。这篇文章分享了我个人对为什么要进行代码审查以及如何有效地进行代码审查的看法。为什么要做codereview为什么需要codereview,相信大家心中都有一个比较一致的答案,google一下也能搜到不少文章。这里有几点简单总结一下:1)提高代码质量这是codereview的初衷,也是codereview最直接的价值所在。审阅者根据自己的经验、思维方式、看待问题的角度,对代码提出各种可能的改进建议,以形成更好的代码和产品质量。我们知道,越晚提出产品问题,解决它的成本就越高,参与的人也会越来越多,流程也会越来越多。代码审查可以说是早期解决问题最有效的方法之一。解决codereview中哪怕是一个小问题,也能避免很多后续的麻烦。2)形成团队统一的高质量标准有效的codereview最终会在团队内部建立统一的质量标准,并随着团队成员的相互学习和相互促进形成更高的标准。在代码审查过程中,参与者会根据具体问题,从不同角度提出改进建议,最终做出最佳选择,形成共识。随着代码审查的有效进行,团队成员会自觉地关注代码质量,从而形成越来越高的事实上的质量标准。3)快速的个人成长通过有效的代码审查,作者和审查者都会成长。在评审过程中,参与者针对具体问题进行深入讨论,无论是如何写出干净的代码,还是如何更好更全面地思考问题,如何最好地解决问题,参与者都可以互相学习和借鉴互相提高。通过具体的代码实现进行讨论往往是最深入和有效的,代码审查是开发人员提高代码能力的最重要途径之一。有人认为代码审查就是Reviewer帮助发现代码中的bug。事实上,codereview不应该是一个单向的过程,而应该是一个双向沟通的过程。学习过程。我们都知道提高代码能力的有效途径就是阅读优秀的项目代码,但是阅读项目代码难度不小,这也是为什么大部分人不去实现的原因,而Review前辈同事的代码,我们是阅读代码同时,能够直接有效地进行交流是一种快速有效的学习方式,尤其是对于开发经验还不丰富的开发者来说。如何做好代码审查2.1.第一招:什么时候发起review在codereview上,Author需要意识到reviewer的时间是昂贵的。因此,作者在正式邀请Reviewer发起codereview之前,有几点需要注意,可以提高codereview的效率,节省Reviewer的时间。2.1.1.MR(MergeRequest)也称为PR(PullRequest)。MR是我们进行代码审查的地方。它记录了代码的具体变化和参与者的具体讨论过程。一个好的MR应该做到以下几点:Single:一个MR应该只解决一个单一的问题,无论是修复一个bug还是实现一个新特性。作者应该避免包含具有不同意图的代码更改的MR。单个MR可以帮助Reviewer快速了解代码变更的动机并进行有针对性的审查。短:MR应尽可能小。比如一个特性引入了很多变化,需要考虑是否可以拆分成几个独立的实现,MR应该单独分开,比如接口定义,接口实现,逻辑对接等。详解:详解这里的意思是MR应该尽可能详细地描述它的背景和动机,这些可以在MR的描述中详细体现,或者联系到一个具体的issue或tapd列表。需要达到的目标是其他人在打开MR时可以知道进行此更改的背景和动机。2.1.2.CommitMessage之前翻了很多已有的项目代码,看到很多CommitMessage写的比较简单,比如一系列的“update”和“fix”。有什么变化,想好以后要定位以前的变化从哪里入手。目前CommitMessage规范与Angular团队的规范比较通用,ConventionalCommitsSpecification是从中衍生出来的。您可以参考本规范,就CommitMessage格式规范达成一致。():

大致分为三行:【标题行】需要描述主要修改类型和内容。[Subjectcontent]描述为什么修改,做了什么样的修改,以及这样做的想法等。[FooterNotes]PutBreakingChangesorClosedIssues其中type是Commit的类型,可以有如下值:feat:newfeaturefix:bugmodificationrefactor:coderefactoringdocs:documentupdatestyle:codeformatmodificationtest:testcaseModifychore:其他修改,比如构建过程,依赖管理,其中scope表示Commit影响的范围,比如如ui、utils、build等,是可选内容。其中,subject是对Commit的概述,body是Commit的具体内容。例如:fix:correctminortyposincodeseetheissuefordetailsontyposfixed.Refs#133CommitMessage可以在git中配置模板,这样模板就可以在vim中显示出来,有工具可以帮助我们生成和约束CommitMessages,比如commitizen/cz-cli,这些不会在这里指定。2.1.3.CI通过CI(ContinuousIntegration),持续集成可以帮助我们自动发现代码中的很多基本问题。在适当的静态代码检查(lint)配置和良好的单元测试覆盖率下,CI可以有效提高代码的质量。许多人低估了静态代码检查的能力。事实上,常用语言的静态代码检查可以帮助发现很多bug和隐患。对于Go语言,可以配置golangci-lint做代码检查。单元测试可以根据实际情况制定相应的标准,比如覆盖率达到60%,关键代码逻辑要尽可能全覆盖。在提交代码审核之前,需要确保CI执行通过。这也是为了节省Reviewer的时间。可以自动解决的事情不应该由Reviewer来完成。如果Reviewer发现CI没有通过MR,也可以要求Author先解决CI问题。2.1.4.自我审查我们通常会要求其他人审查代码。事实上,一个负责任的Author在邀请他人审查代码之前,也需要自己进行一次简单的审查,即Self-Review。Self-Review的目的包括:发现那些明显的疏忽,比如代码调试过程中留下不必要的痕迹,比如fmt.Println(...),不小心把代码注释掉了。以前reviewer问过很多次的问题。Commit是否正常,多人协作时是否将不相关的Commit带入MR。CommitMessage是否合适。自我审查是一个非常快速的过程。从我个人的经验来看,一般需要1-2分钟就可以完成,所以建议大家养成Self-Review的习惯。2.2.第二招:应该找谁Review?从Review的目的出发,可以从以下几个方面考虑Reviewer:提高代码质量。因此,首先应该找与代码变更密切相关的开发人员参与评审,比如共同开发某个功能或项目,或者参与设计讨论并提出宝贵意见。征求意见。找有相关经验的资深开发人员帮忙评审,比如Java语言的资深开发人员,或者写过相同或相似系统/功能的开发人员。形成共识。如果涉及到不同团队或模块之间的接口变更,或者其他会影响到其他人的变更,可以邀请相关团队或模块的接口参与Review,形成对变更的共识。质量控制。对于重要的代码库,可能会实施更严格的质量控制。如果设置了必要的审稿人,这些审稿人也将参与。变更通知。在许多情况下,一个代码库可能只由一个人维护。如果做了一些特别的改动,别人是很难发现的。所以在做一些重要但又不是那么直白易懂的事情的时候,最好告知相关的研发,让他们大概了解是怎么回事。2.3.第三招:复习一切。经常有审稿人拿到了MR,不知道要审什么。其实无论你在对应的项目中有多深,都可以review代码。鼓励不同的人从不同的深度、角度来帮助Review。CodeReview没有固定的形式,它更像是一门艺术,真正提高它的唯一方法就是实际参与其中。评审的时候,可以从以下几个方面入手:1)如果简单的评审通过CI,最简单的评审方式可能只需要这样:Reviewer:有没有在实际环境中验证过?作者:当然,已验证审稿人:LGTM这是一个提醒审稿。确认句:是否已经在环境中验证过,或者进一步提出可以想到的重要验收点进行确认。即使是最简单的评论实际上也很有价值。我们很难保证所有的研发在提交MR前都会对我们在环境中所做的修改进行实际验证,也很难保证单元测试和e2e测试能够覆盖所有,在这种情况下,基本不可能审稿人自己去环境。要求作者确认,其实就是提醒作者,至少要保证改动是真实有效的,尤其是发布版本中的一些bugfix,一定要提醒自己实际自测才能通过。类似的提示还包括:相关文档(外部)是否相应更新,这个改动是否会造成兼容性问题,性能是否会受到影响。他们的本质是提醒作者思考他们可能遗漏的问题。2)ConventionalReviewCodeReview一般从代码风格、变量命名、语法统一等方面入手。当然,这些应该通过CI等更加自动化的手段来保证,但是在相关流程不完善的前提下还是有必要Follow。另外,代码的可读性、代码的健壮性、代码的可扩展性,都是Review时关注的点。每个关注点都取决于reviewer的实际经验。这里仅举几个例子:{codereadability}代码是写给人看的,因为没有代码是不需要维护的,无论是作者自己后续维护的代码,还是别人接手的代码,能够快速理解代码逻辑是非常有必要的。在审查代码时,可以注意以下几点:变量和方法的名称是否恰当,是否真实反映了它们的用途。您可以在Internet上找到很多关于此的信息。实现的逻辑是否有可以替换的现有库。如果有成熟的库可用,尽量不要自己实现,因为可能会引入不必要的bug。从我个人的角度来看,简洁(白话代码更少)是可读性的一个非常重要的指标。关于注解。代码注释不求多,但求实效。我也经历过代码注释至少需要30%以上的时代。现在看来,过分依赖注释,其实是对代码质量缺乏信心。好的代码应该尽量做到不言自明。偶尔在实际过程中,看到代码的逻辑其实很清晰,但是我用英文注释了一句不是很清楚。最后,我只有看懂代码才能看懂评论说的是什么。因此,在审稿时,可以建议删除不必要的评论。对不易理解的地方应作适当的注释。如果代码中有特殊处理、特殊常量或不符合一般用法的逻辑,则需要特殊注释。代码的组织。好的代码应该有更好的封装和层次,让代码看起来清晰,比如DAO层和Service层。{CodeRobustness}代码更改是否会影响其他功能。用户参数是否经过仔细验证。是否有恐慌的可能性(对于Go)。它会破坏API兼容性吗?{Scalability}目前的实现是否兼容未来类似的扩展需求。比如在解决某个问题时增加新的接口、API,或者调整参数,可以考虑以后是否还会出现其他类似的情况。举几个例子:假设我们需要定义一个API接口来获取用户的某些信息,比如联系方式等,我们定义的API不应该只返回这些信息,而是应该返回所有与用户相关的信息。假设我要定义一个参数,虽然目前定义为单个元素,比如string,int,但是以后是否会涉及到多个元素,最好定义为[]stirng,[]int。这里只是一些有限的例子。在实际审稿过程中,Reviewer可以根据自己的经验,从多个角度提出优化建议。通常,您需要关注:您不了解或有疑问的地方。一个打破常规的地方。复杂的地方。2.4.第四招:如何鼓励Reviewer在审稿过程中大胆评论,不明白或觉得不合适的地方直接表达。TheAuthor也应该对MR的每条评论进行反馈,无论是发起讨论还是简单的给一个OK才是有效的反馈。审稿流程可以是:作者在所有确认任务完成后发起审稿。如果紧急,可以给重要审稿人发消息,寻求帮助审稿。审稿人看到MR后,首先要确认MR的背景和目的。如果信息不明确,无法从MR处获取,最好直接与Author沟通。审稿人直接在MR上提出自己的建议或问题。作者对每条评论提供反馈并发起必要的讨论。复杂的话题可以离线讨论,提高沟通效率。Author处理完所有的评论并修改代码后,需要在MR中@相关的Reviewer,告知所有的优化已经提交。如果时间紧迫,可以直接与Reviewer沟通。Reviewer确认没有问题,批准了MR。一般简单回复就是LGTM(LoodGoodToMe),作者的作品也可以欣赏,比如《GodJob》。Approve之后由谁来合并MR,由你选择。如果Reviewer提供了很多有用的建议来帮助优化代码,Author也可以礼貌地感谢Reviewer。2.5.第五招:关于CommentCodeReview很大程度是为了找代码中的错误,一般认为是挑的越多越好,但是代码是作者写的,很多时候会越多或更少地引起作者的不适。所以评论的时候需要注意措辞,尤其是一些主观的东西,一般都是以建议的形式给出。当然,原则性的问题,一定要坚持质量标准,甚至可以直接否定MR。此外,与会者不应吝啬你的美言。无论是Author还是Reviewer,如果在审稿中发现好的地方或者好的建议,请给予对方肯定和好评,这将有助于审稿的有效进行。2.6.第六招:参与者要有什么样的心态?2.6.1.Author首先要明确,Author是对代码质量负责的,所以要怀着感恩的心对待坚持帮你review代码的Reviewer,因为不是你加的Reviewer都有时间和精力帮助您提高代码质量。正是因为Author是自己代码的拥有者,所以不要依赖Reviewer来帮你把守代码质量的大门,比如“代码review的时候你怎么没看到”、“Didn'你不建议我这样做吗?”不要说这样的话。Reviewer只是为了帮你提高代码质量,所以该做的工作我们都要做。例如,一个详细的Reviewer在某些情况下可能会直接提出代码优化建议,将优化后的代码片段粘贴在Comment中,Author不能直接假设Itmustbeworking,应该充分验证。不要抗拒审稿人给出的评论。对于你认为不合理的建议,你可以委婉地拒绝,或者详细说明你的看法和理由。有时候一个你认为不合理的建议,可能代表了一种新的思考角度,也可能代表了Reviewer自身编码能力的不足。不管是哪一个,不管是Author还是Reviewer,最后提高了,应该都是好事。2.6.2.ReviewerReviewcode不仅仅是一个帮助提升代码质量的过程,更是Reviewer提升自身代码能力和沟通能力的过程。所以,在review的时候要保持一个学习者的心态,不仅要发现对方代码中的缺陷,还要努力去发现代码中的亮点。不要抱着吹毛求疵的心态简单的review代码。很多Reviewer在写Comments的时候犹豫不决,担心自己提出的问题或者建议是“愚蠢的”,于是抱着很多疑惑去读代码,最后什么都没留下。其实在codereview上大可不必有什么负担。大家有什么疑惑、不清楚的地方,或者有自己的想法,都可以直接提出来。有时一个简单的评论可能会引起作者和你的想法。评论无关的新想法。再者,就算你不帮Author改进代码,让Author帮你改进思路不是好事吗?审稿人不需要关注自己的“输出”。没有必要问一堆问题才能成为一个好的代码审查。Author代码写得好很正常。如果你觉得代码从你的角度来说没问题,就大胆地给LGTM甚至Approve。