在软件开发团队里,Code Review 是非常重要的一个质量保障环境。好的 Code Review 能促进团队成长,差的 Code Review 形同流水。而在有了 LLM 之后,事情又发生了一些微妙的变化:
过去,一个小规模(6 人)左右的开发团队,平均每天得花费 30 分钟在代码检视上(CodeReview)。所以,不管,从提效的角度来说,还是从未来需要更多的代码检视时间,改善 Code review 迫在眉睫。
TL;DR 版本:
首先,让我们来回顾一下:什么是好的技术实践 —— 诸如于如何写好提交信息?
在编写提交信息里,又或者在 DevOps 标准化初中,业内的最佳实践是:保持提交信息与用户故事、需求的关联。
诸如于,我们使用的是 JIRA 工具里,需要结合 JIRA ID 在提交信息里;使用的是 GitHub 时,则使用 # + issue id 的形式,如下所示: feat(devops): init first review command #8
。基于此,我们来将需求信息与代码变更保持一致,方便于回顾。
问题来了,如果开发人员不愿意写好提交信息怎么办?—— 自然是用 AIGC 来自动生成了。
了解完 AIGC 的基本原理之后,大部分人会关注 AIGC 生成代码的安全性问题。而对于代码的安全性问题,在没有 AIGC 之前,我们会采用 Sonarqube、JavaLint、ArchGuard、Feakin 等工具来监控、改进系统的代码、架构质量等等。
考虑到 AIGC 是受 prompt 影响结果的,并且在长 prompt 下如何失焦,所以在可靠性上不如静态代码分析来得稳定。
事实上,根据不同的 Code Review 形式,诸如于时间(每日、每周、每次发布)、节点(发布前),每个人会关注的内容是有非常大差异的。诸如于,当我处在团队的不同阶段时:
所以,从 review 的内容来看,主要会关注于业务和技术两部分。而不同的人所关注的是不一样的,该交由传统工具的部分,还是应该交由传统工具。
在使用 AIGC 辅助 Code Review 上,网上已经有各种五花八门的解决方案,我们也只是其中的一种方案。
回到先前我们在构建 AutoDev 的经验上,对于 Code Review 来时,难点并非在于 Review 点的设计,而在于如何处理上下文。与其他的领域不同的是,如果采用的不是小步提交的方式,那么在 review 时难点很大。
简单来说:如果代码提交实践做不好,那么 AIGC 的 Code review 会非常鸡肋。过于发散的意图,使得我们无法关注到每一个小点。
在设计我们的工具时,大致分析了网上的各类 prompt。为此,我们发现 prompt 并不是难点,结合 AIGC 进行 Code Review 的难点在于:如何模拟真实的 Code Review。只有了解、深入真正的 Code Review 实践,那么我们才能设计出好的工具。
在日常的 Code Review 中,首先,我们需要知道对应的业务背景;其次,忽略大量无关的非代码变更,诸如文档更新、测试数据更新等等;最后,如果变更复杂的场景,则跳过 patch,直接查看代码。
基于此,我们构建了 Code Review 的 Prompt 演进路线。第一个版本则比较简单,即围绕于优化 prompt 长度来包含更多的上下文:
即通过实践 + 配置化的方式,来突出重点、核心的内容,而忽略无关紧要的东西。
不论是在 IDE 端,还是在平台端,在当前的第一个版本里,两个处理逻辑都是相似的。主要过程如下(由 ChatGPT 生成):
比较大的差异是两个 Prompt 是针对不同场景下的,IDE 是针对于开发人员想知道业务变化,而平台端则是对语法等进行检查。
先看 Prompt 中的上下文(PS:更详细可以阅读代码中的 simple-review.open-ai.vm 模板文件)。
.....
Business Context: ${context.businessContext}
Commit Message: ${context.fullMessage}
Code Changes: ${context.changes}
简单来说:
需要注意的是:由于大部分编码大模型语料和数据中都是基于 patch 来进行训练的,所以它的效果会比较好。所以,需要根据不同的模型来选择,理想的 changes 形式。
如下是 Conventional
Commits
进行的提交格式示例:
从中解析出我们所需要的 type
、 references
等信息,作为过滤条件的一部分:
// 从配置文件中读取,并过滤掉不需要 review 的 commit,诸如 chore、ci, docs 等
// 如果没有配置,则全部需要 review
val filterCommits = parsedMsgs.filter {
if (it.meta.containsKey("type")) {
val type = it.meta["type"] as String
project.commitLog?.isIgnoreType(type) ?: true
} else {
true
}
}
进而只呈现关键的上下文,减少 prompt 长度。更详细的可以阅读 AutoDev 和 DevOps Genius 的代码和文档:https://devops.unitmesh.cc/code-review 。
在结合 IDE 的 Code Review 里,我们往往会选择自己的多次提交,来讲解对应的业务功能、实现等等。而这也意味着,在 IDE 的场景下,让 AI 来 summary 更容易超出上下文限制。所以,需要添加更多的 review 方式来支持。
而在平台上时,更适合结合单次提交或者 Pull Request 的方式来进行。尽管,如此,但是在基本的 patch 优化上都是相似的策略。
事实上,如果你参与到真正的团队 review 里,会发现哪怕是同一个部门下,不同团队的 Code Review 方式,以及其所关注的点是不一样的。如何有机结合关注点与 prompt 进行整合,是我们下一步需要考虑的。