代码审查是软件开发过程中至关重要的一环,它像一块基石,保证了代码的质量和可靠性。我们通过代码审查分享知识、及早发现错误,并确保代码符合最高的行业标准。
然而,传统的代码审查方式往往耗时且效率低下,有时甚至会忽略一些关键问题。如今,AI代码审查的出现,正在彻底改变这一现状,它能够有效地解决传统代码审查的痛点,并将代码质量提升到一个全新的高度。让我们一起探索AI如何赋能代码审查,让开发流程更加高效和智能。
本文将从开发人员和审查人员两个主要角度,深入探讨AI在软件开发生命周期(SDLC)不同阶段的应用和影响。我们将重点讨论AI在代码审查中的具体应用,以及如何有效地实施它。同时,我还会分享一些在不同阶段可以使用的工具示例,包括Github Copilot、SonarQube、Qodo和IntelliJ等。
AI代码助手生成代码
人工智能代码助手能够根据您的输入自动生成代码,这无疑是AI强大功能的又一体现。它可以极大地减少编写代码所需的时间和精力,尤其是在处理重复性或样板任务时。你可以想象一下,以后写代码,大部分重复性的代码,都可以让AI自动完成,这会节省多少时间和精力。
此外,代码生成助手还能帮助你在开始编码之前探索不同的设计方案并识别潜在的问题。借助这些工具,开发人员可以专注于软件开发的创意和战略性方面,而将繁琐和机械的任务交给AI处理。这简直是解放生产力的一大利器。
人工智能采用
市面上涌现出了许多AI代码助手,它们功能各异,根据不同的分类标准有着不同的排名。下图展示了一些AI代码助手的功能排名:
虽然这些工具功能强大且丰富,但它们通常依赖于托管在云端的模型,并且某些高级功能可能需要付费。那么,是否存在本地、免费且开源的解决方案呢?答案是肯定的!
实际上,还有一些完全开源的选项可供选择。这些方案允许你在本地或网络中托管模型来生成代码。你可以利用大量免费且开源的模型,并通过在你的网络或本地机器上安装免费工具Ollama来提供这些模型。
我个人尝试过IntelliJ插件“Continue”、Ollama以及模型“codellama”和“deepseek-coder”,体验相当不错。使用这种方案,你还可以确保你的代码和提示数据不会泄露到外部。
但是,任何技术都有其局限性。虽然生成式AI前景广阔,但也并非完美无缺。一个主要问题是它可能会将错误和漏洞引入代码中。AI模型是在大量数据上训练的,如果这些数据包含错误或恶意代码,那么生成的代码也可能会继承这些缺陷。这就需要我们开发者在使用AI生成代码时,保持警惕,进行必要的审查和测试。
AI生成代码正确性
此外,生成式AI系统可能无法完全理解其生成的代码库上下文或意图,导致输出的代码没有实际意义,甚至存在潜在的风险。因此,开发人员需要仔细审查和测试AI生成的代码,并采取强有力的安全措施来降低这些风险。记住,AI只是辅助工具,最终的把关人仍然是人类。
从上面的分析可以看出,使用AI生成代码既有积极的影响,也会对整个SDLC产生负面影响,尤其是在代码审查过程中。因此,我们需要对AI代码助手持谨慎态度,并在充分了解其局限性的前提下合理使用。
传统代码审查之争:熟悉的痛点
我们都经历过这样的情况:传统的代码审查虽然必不可少,但也常常伴随着一些问题:
- 耗时:手动审查每一行代码需要投入大量的时间和精力,尤其是在大型项目中。
- 主观性:“好代码”的评判标准带有一定的主观性,可能导致反馈不一致和潜在的冲突。
- 遗漏问题:即使是最有经验的人工审查人员也可能会遗漏一些隐藏的错误、安全漏洞或性能瓶颈。
此外,还有一些其他因素也会影响代码审查的效率:
- 风格偏执:过分强调细微的风格问题会分散对更关键问题的注意力。
- 背景不足:审查人员可能缺乏对代码更改的完整背景信息,这使得他们难以提供有效的反馈。
- 认知负担:审查包含数百行代码的大型拉取请求会让审查人员感到不知所措。
- 反馈延迟:代码审查可能会减慢开发流程,影响项目进度。
- 团队摩擦:由于缺乏背景信息、反馈过于严苛或功能测试不充分,代码审查可能会导致团队摩擦,甚至升级为争吵。
AI:增强代码审查
AI工具正在通过自动执行复杂的任务、提供精准的反馈并发现隐藏的问题来改变代码审查的方式。现在让我们来看看这些工具如何在整个开发生命周期中提供帮助:
开发阶段(IDE集成)
我们已经看到了许多代码助手插件和集成到IDE中的工具,它们可以帮助我们生成代码。一些基准测试(例如huggingface、stackeval、Mike Ravkine的测试)可以帮助我们选择在这些助手中使用的模型。
虽然我们拥有强大的自动完成和代码生成工具,但如何验证生成的代码是否会引入与代码库上下文不兼容的语言版本、漏洞或解决方案呢?这确实是一个值得关注的问题。
为了解决这个问题,我们可以使用以IDE代码检查器形式存在的静态分析器,例如集成到IDE中的SonarQube。它可以为你编写的代码提供即时反馈。此外,还可以使用CI/CD代码分析器,例如SonarQube Server/Cloud,它将对你的代码进行全面分析,并防止不合格的代码被合并。
想象一下,在代码审查开始之前,潜在的错误和不符合最佳实践的地方就已经被发现了,这无疑将极大地提高代码审查的效率和质量。
这些linter使用静态分析和其他技术,直接在你的IDE中检测代码异味、错误和安全漏洞,从而使你能够从一开始就编写更清晰、更安全的代码。
但这不仅仅包括错误和漏洞,还包括使用某些框架或语言版本的最佳实践。AI代码助手有时无法很好地理解你在代码库中使用的语言版本(例如Java 21),它们推荐的解决方案可能没有考虑到语言的最新改进,而只是采用了最简单和最常用的方法。
以下是一些具体的例子:
Github Copilot并没有建议使用Java 12中引入的Teeing Collector功能,而是采用了手动方法来迭代集合并计算平均值。
由 Github Copilot 生成
public double calculateAverage(Collection collection) { int sum = 0;
for (Integer num : collection) { sum += num;
}
return (double) sum / collection.size();
}
而使用Java 12中引入的Teeing Collector可以更加简洁和高效地实现相同的功能:
public double calculateAverageManual(Collection collection) { return collection.stream().collect(
Collectors.teeing(
Collectors.summingDouble(i -> i), Collectors.counting(),
(sum, count) -> sum / count)
);
}
另一个例子是,Github Copilot在使用线程时,并没有采用Java 21中引入的虚拟线程,而是使用了传统的平台线程。虚拟线程可以极大地提高阻塞操作的性能。
Github Copilot 使用平台线程生成的代码
new Thread(() -> {
var url = new URI("http://localhost:4000").toURL();
var connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET");
int responseCode = connection.getResponseCode();
}).start();
而使用虚拟线程的代码如下:
Thread.ofVirtual().start(() -> {
var url = new URI("http://localhost:4000").toURL();
var connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET");
int responseCode = connection.getResponseCode();
}).start();
幸运的是,这些linter可以在我们的编码和CI完整分析期间警告我们缺乏最佳实践的使用,从而帮助我们及时发现并纠正这些问题。
某些linter(例如SonarQube IDE)的一个特别优势是它们可以在同一个项目中同时分析多种类型的文件。这不仅包括Java、Python、JScript、Kotlin等编程语言,还包括Docker、Kubernetes、Ansible、Terraform、CloudFormation等云部署文件,甚至可以检测Secrets漏洞。
测试生成阶段
AI可以分析当前代码,尝试理解其用途,并生成可能生成测试代码的测试方法,从而保证高覆盖率。这有助于保证你的代码在发布之前经过彻底的测试。有了AI的加持,以后写单元测试再也不是难事了。
在这个领域,我们可以找到Qodo Gen等专门用于测试生成的工具。
我已经将它安装在我的IntelliJ IDE中,并在我的AI项目中试用它。它可以为快乐路径或边缘情况生成多个测试示例,结果令人印象深刻。与大多数代码助手一样,我们选择使用远程托管模型。
像Qodo这样的工具将采用类方法并创建其测试。我们将有一个仪表板来查看测试和执行情况,以及Qodo插件中的测试生成计划:
创建拉取请求
创建拉取请求的过程也很重要,它能够便于审核人员了解PR的目标,并提供适当的背景和详细信息。典型的工作流程通常意味着:
- 遵循加入/登录团队的总体流程
- 阅读贡献指南
- 按照惯例进行提交
- 签署等待所有提交(请!)
- 创建具有完整描述的草稿拉取请求(有时遵循模板,例如JKube项目)
- 通过所有检查
- 将PR状态更改为准备审核。
虽然有很多指南(GitHub、pull request)可以帮助你编写良好的PR描述,但我们可以利用AI来进一步提升PR描述的质量。例如,可以使用Github Copilot来分析PR中的代码,并自动生成更详细的描述。
在上图中,我们可以看到如何要求Github Copilot为PR生成摘要。
我们还可以根据需要,添加更多的背景信息和细节,以帮助审阅者更好地理解PR的内容。
预代码审查(自动分析)
静态分析器(例如SonarQube)会对你的代码库进行深入的静态分析,识别出人工审阅者可能遗漏的问题。这超出了简单的样式检查,还将深入研究:
- 错误检测:识别潜在的NullPointerException、逻辑错误和其他错误。
- 安全漏洞:检测潜在的注入攻击、跨站点脚本(XSS)漏洞方法和其他安全风险。
- 代码异味:突出显示难以阅读、维护或理解的代码。例如,过于复杂的代码或重复的代码。
- 代码覆盖率:测量单元测试覆盖的代码总数,有助于确保全面测试。
这些分析器会清晰且可操作地呈现这些问题,并根据严重程度确定其优先级。这样,开发人员就可以首先关注最关键的问题,从而使审查过程更加高效和有效。
结合之前的PR工作流程,我们可以使用连接到代码仓库的工具,在任何人花时间审查代码之前,检查所有可能导致代码失败的情况,从而使代码审查人员可以将精力集中在需要深入审查的变更上。
Pull Request 变更说明
现在轮到审阅者了。他们应该首先阅读定义PR目标的草案。之后,仔细检查检查状态将使我们知道这些更改是否可以合并。就像医生看病一样,首先要了解病人的主诉,然后才能对症下药。
为此,我们可以使用多种工具。我尝试使用Github Copilot和Qodo PR-Agent(你可以通过以下链接找到它们):
Copilot为每个更改的文件提供了解释功能,而Qodo为整个PR描述。这将帮助审阅者了解创建评估文件的详细信息,并专注于需要更多关注的内容。局部PR处理所需的时间非常重要,而使用AI工具无疑可以帮助我们实现这一点。时间就是金钱,效率就是生命!
修改建议
在PR中,审阅者会提出改进或修复文档部分内容的建议。这是一些至关重要的一点,如果处理不当,可能会增加团队成员之间的焦虑和困难。良好的沟通和有效的反馈是保证代码审查顺利进行的关键。
为了确保作者和审阅者之间能够进行安全且有效的沟通,有一些指导方针可以参考。例如,审阅者应该尽量以客观和友好的语气提出建议,避免使用带有攻击性的言辞。同时,作者也应该虚心接受建议,并积极与审阅者沟通,共同解决问题。
一些AI工具,例如Qodo PR-Agent,还可以将AI代理建议的改进和更改直接从PR评审实现到代码中。这可以大大简化修改代码的过程,并减少人为错误。
与所有更改一样,它们需要使用SonarQube等工具进行分析和检查。如果有任何问题,这些工具就会失效,从而阻止这些更改合并到主分支中。这就像一道安全阀,保证了代码的质量和可靠性。
除了以上提到的工具,还有一些其他的AI代码审查工具也值得关注:
- watsonx Code Assistant:该方案使用生成式AI来加速开发,同时保持信任和安全原则。它可以帮助开发人员减少错误,缩短学习曲线,并通过代码生成、代码匹配和代码现代化来构建高质量的代码。
- Codacy:Codacy提供支持JavaScript和Python等语言的自动代码审查功能,帮助开发人员维护项目中的代码质量。它能够无缝集成到软件工作流程中,使团队能够尽早发现问题。
- DeepCode:DeepCode使用AI来实时分析代码,从而为开源项目提供可操作的洞察信息。该工具可通过识别常见的陷阱以及推广软件工程的最佳实践来增强新开发人员的上手体验。
- Bito AI:Bito AI专注于通过其直观的界面以及人工智能驱动式代码审查功能来简化软件工程团队的上手流程。它可提供即时反馈以及可操作的建议,并帮助新团队成员快速适应公司的编码标准和最佳实践。
- PushRequest:PullRequest提供AI驱动的洞察分析和人类专业知识,从而促进软件工程团队顺利完成入职流程。该平台提倡协作和知识共享,以鼓励新的开发人员向经验丰富的审查者学习。
- Coderabbit:Coderabbit是一个AI代码审查平台,它使用AI工具来生成分析和清晰的反馈。它可提供类似人类的审查功能,并可进行自定义,因为它适用于所有编程语言。
利用人工智能应对挑战
总而言之,AI正在通过以下方式解决传统代码审查的挑战:
- 减少时间:自动化可以提高代码审查的效率,使开发人员能够专注于更复杂、更具创造性的任务。同时,它也有助于减少了解所有变更范围所需的认知负担。
- 一致性:静态分析可以根据预定义的规则和最佳实践提供一致且可靠的反馈。
- 关注关键问题:优先级排序功能可以帮助审阅者将注意力集中在最重要的问题上。
- 增强上下文:AI可以读取代码变更,并生成详细的PR描述以及对变更的详细解释,从而为审阅者提供更多的背景信息。
AI 代码审查总结
人工智能不会取代人类审阅者,而是会增强他们的能力。通过自动执行繁琐的任务并提供有价值的意见,人工智能工具将提高生成代码的速度和理解力。简而言之,AI是代码审查的得力助手,但最终的决策权仍然掌握在人类手中。
静态分析器等工具将自动检查代码的合规性并保证整个SDLC的代码质量,使开发人员能够专注于他们最擅长的领域:设计、构建和创新。有了AI的加持,开发人员可以更加专注于创造性的工作,而不是被繁琐的重复性任务所困扰。
通过利用人工智能工具,我们可以将重点从简单地查找错误转移到构建高质量、可维护和安全的软件。这才是AI代码审查的最终目标!