人工智能辅助程序员的三种类型 [译]

关键在于不仅要用,更要会用。

文章封面图片
文章封面图片

图片来源:Alexandra Francis

2023 年初,人们发现像 ChatGPT 这样的大语言模型 (LLM) 能够编写高质量的代码片段,这在 LinkedIn 上引发了不少热议,许多人误以为这意味着再也不需要那些技术娴熟、态度挑剔、薪水高昂的资深开发者了,只要有互联网,任何人都可以让 AI 模型来编写下一个热门社交媒体应用,还得用 JavaScript 编写,顺便加上一些区块链技术。

但是,那些承诺中完全由 AI 打造的应用程序大潮并没有真正涌现。对于这个结果,虽然在某种程度上证实了我的看法,但我尽量不去表现出幸灾乐祸的态度。

尽管如此,将 AI 作为编程工具仍具有吸引力。代码本质上是面向计算机的语言,它有限且明确的词汇和严格的语法规则,以模式和重复为基础。正是这种可预测性,让计算机(以及像我这样的一些人)与之相容。如果说有谁能写出好代码,那非计算机莫属。如果生成式 AI 最擅长的是模拟和仿制这些模式,从而构建人机之间的流畅接口——正如我此前所述——那么编程无疑是它的理想应用场景。

话虽如此,AI 驱动的编程工具已在编程领域引起了不小的轰动,并且看起来它们不会很快消失。然而,不论是对于初级、中级、高级工程师,还是那些连结构体和墙洞都分不清的人,AI 带来的风险与收益完全取决于个人的经验水平。AI 可能是你职业生涯的助推器,也可能成为你事业道路上的绊脚石。关键在于不仅要用,更要会用。

让我们一起探索 AI 对于各个阶段的开发者(以及非开发者)意味着什么。

无代码创业新潮流

今年,很多人通过与 ChatGPT 的互动,初次体验到编程的魅力。这种体验极具吸引力:你可以让 ChatGPT 用任何主流编程语言为你编写应用程序,它能够输出足够编写一个标准教程应用程序的代码量。在此基础上,你还可以要求它进行修改和除错,直到你对成品感到满意。当你将这些代码粘贴进集成开发环境(IDE),看到它们竟然能够运行,这种感觉就像你揭开了整个行业的神秘面纱。

这种乐观的初体验背后,其实隐藏着一些问题。AI 工具是基于成千上万个不同质量和完整性的真实项目代码训练而成的,这意味着这些代码通常能运行,大多数情况下也能完成任务,但偶尔才会真正可靠、易于维护、安全或无错误。

研究显示,ChatGPT、GitHub Copilot 和 Amazon CodeWhisperer 这类工具输出的代码在“运行无误”方面的表现约为 90%,在单元测试的通过率大约在 30% 到 65%,而在“安全性”方面的表现约为 60%。值得一提的是,这些研究是基于经验丰富的工程师编写的精确提示进行的。提示中细微的措辞变化就可能导致代码输出的巨大差异。而且,这些测试只涉及 AI 输出的简单代码“片段”。至于 AI 编写像平均遗留应用程序那样复杂的应用程序的能力,目前还没有相关数据。事实上,就像 ChatGPT 难以撰写一部完整连贯的小说一样,AI 在这方面可能也无能为力。

那么,对于那些不懂编程的人,AI 可以扮演什么角色呢?

有些人可能认为 AI 在编程领域的应用并不实际。AI 依赖编程的概念在软件界引发了广泛讨论。一名程序员本质上应该掌握编程技巧。如果连基本的 if 语句都写不出,还能自称程序员吗?但这种观点忽略了一个重点:像 if 语句这样的编程逻辑,并非优势,而是一种负担。理想的代码是完全没有代码的状态,其次才是能解决用户问题的最简代码。如果有可能不编写任何代码就能构建高品质的应用,那自然没有问题。

但遗憾的是,这目前还不可能,而且可能永远不会实现。代码,本质上,就是对需求的精确描述。如果你的 AI 提示足够精准以生成正确的代码,那么你实际上已经在编程了。但 AI 存在不确定性;它不总是对同一输入产生相同的输出,这里涉及到一定的随机性。因此,即便是符合编码标准的提示,也可能是不可预测的代码。在花费大量时间细化流程后,最不希望遇到的就是不可预测性。长期依赖 AI 提示进行编程的人最终会渴望更直接、更有结构、更稳定的编程方式——他们会渴望使用编程语言和编译器。

我预测,AI 将成为未来一些程序员的“启蒙工具”。但它还有一个更重要的用途,这点往往被忽视。

在很多情况下,我们不需要完整的软件,只需要一些代码。其他行业的专业人员已经在使用 AI 来编写一次性的 SQL 查询和 VBA 宏。AI 还可以用来创建应用原型、命令行上的概念验证工作流,或是一次性的数据抓取工具。如果你需要专业的软件解决方案,自然还是要找软件开发专家。但如果你只需要一些临时的代码,且能接受一些不完善之处,那么利用 AI 尝试一下也无妨。

最终,这将不可避免地增加程序员的工作负担。AI 在将创意转化为初步方案的过程中发挥着桥梁作用,这将促使更多处于早期阶段的软件公司涌现。当这些初创公司进入市场时,他们会发现(有时是在非常紧急的情况下)需要招募工程师加入团队。但值得注意的是,对于那些最初资源和资金较为匮乏的公司来说,能够达到这样的发展阶段本身就说明 AI 已经成功地完成了它的使命。

初级工程师的挑战与机遇

对于新手程序员来说,AI 工具既是一种挑战,也蕴藏着巨大的机遇。

每位初级开发者在首份工作中都难免感到手足无措,好比学了一年的多邻国后突然搬到西班牙生活,要花上几个月甚至更长时间才能适应。现实中的应用程序与大学最后一年编写的编译器或编程训练营中的展示项目截然不同,它们的深度和复杂度远远超出你的想象,而且要求也更为严格。要记住所有规则,通过资深开发人员的代码审查似乎是一个艰巨的任务。

在这种情况下,初级开发者可能会被诱惑去使用 ChatGPT 来减轻工作压力。在开始的时候,他们可能能够侥幸成功。正如之前讨论的,AI 工具在处理基础任务上表现良好,这总比一筹莫展要好。更重要的是,它们不会让你面对一片空白和闪烁的光标。

然而,依赖 AI 代码工具最终会有代价。最大的风险在于,过分依赖这些工具的开发者可能永远难以成为真正优秀的程序员。如果开发者习惯于使用代码生成器,并且只依靠外部反馈(如代码审查、集成测试、错误报告等)来发现问题,他们将很难真正理解自己的代码。这种做法最终会适得其反,甚至让人尴尬。每个生产应用中都存在关键错误、潜在的安全漏洞、技术债务等问题,只有真正理解代码的人才能解决。

对于初级开发人员来说,最安全的选择是远离 AI 工具。但这并不是唯一的出路。如果你用 AI 来增进理解,而不是简单规避问题,它不会成为你的阻碍。

比如,假设你刚写完一个函数,感到有些不确定。你反复阅读,修改了一些格式问题,但仍觉得它可能不够高效或不够地道。在联系同事或提交代码审查之前,你可以尝试用 AI 获得另一种视角:告诉 AI 你的目的,让它写出一个函数,并将其代码与你的进行比较。

要明白,生成式 AI (Generative AI) 本质上是尽可能平庸的,它的输出不可盲目信赖。这项练习的目的不在于直接为你提供更优的代码,而是在于促使你自我反思。有时候,AI 会用到你可能忘记的标准方法,这有助于更好地体现你的意图。比如,AI 可能只用一个循环就完成了你需要两个嵌套循环才能处理的数据集。当然,它也可能没提供什么新颖有趣的东西;如果是这样,那你大概没有遗漏什么重要的点。

此外,当你在某些语法或编程模式上遇到难题时,可以让 AI 生成一些例子帮助理解。比如,你对空合并运算符 (null-coalescing operators) 还不太清楚,就可以让 AI 展示一些具体的使用场景。虽然生成的代码质量可能不高,但大量的例子是学习的关键。例如,你在研究适配器模式 (adapter pattern)时,若找不到 Dart 语言的示例,可以要求 AI 展示一下。虽然结果可能只是中规中矩,但具体的示例本身就是一种珍贵的学习资源。

尽管如此,你还是应该尽可能地通过官方文档、亲手编写的代码、编程博客和 Stack Overflow 的回答来学习。毕竟,AI 提供的信息有可能完全错误。但如果一段次优的、定制化的代码片段能够帮助你进入下一个学习阶段,那么 AI 无疑是一个很好的辅助工具。

资深工程师

作为一名资深工程师,你或许不会被使用人工智能代替基础技能的想法所吸引,因为你已经掌握了这些技能。可能你甚至不太愿意使用 AI,这是完全可以理解的——选择不使用某一工具并没有错。

很多人好奇,对于经验丰富的开发者而言,生成式 AI 究竟有什么作用。毕竟它有时候产出的是无用之物,有时虽然能写出可用的代码,但质量并不如你亲自编写的。为何要将工作交给一个表现更差的工具呢?解答这个疑问,我们需要明确自己与 AI 之间的分界。即便在最佳状态,AI 写出的代码正确执行的几率也只有五成左右,而且几乎无法精确地表达代码在整个应用程序中的作用。没错,AI 并不擅长编写代码,但它的优势在于速度极快。这就是你应该对它的期望。AI 负责迅速完成任务,而你的职责是确保质量。

编辑和重构代码通常比从头编写来得快速(虽然不总是如此)。我曾参与 GitHub Copilot 的测试,在个人电脑上进行合同工作时使用它,发现它显著提升了我的开发速度。当然,它对我的代码的准确性或可维护性并无帮助,毕竟那不是它的职责所在。但是通过提供我大约一半时间都能使用(尽管需要大幅修改)的代码,它在整体上节约了很多时间。按小时计费时,时间节省并不那么重要,但如果你是固定薪资,它可以使你少花时间在编写常规代码上,而将更多精力投入到开发流程、代码质量、文档编写等让软件更可持续的方面。

你需要避免的陷阱是使用 AI 来提高工作速度,即交付更多而不是更好的功能。即便是最优秀的团队,工作速度也是一个不切实际、不可靠的指标,人类的表现并不总是一致,AI 的表现则更加不稳定。如果你让周围人期待你能利用 AI 工具提升开发速度,你会发现它无法持续保持这样的速度。AI 在某些任务上表现出色,但在其他任务上却无能为力。虽然它通常能帮你提速,但很多时候你还是需要自己动脑筋解决问题。

我们再次面临一个界限问题。AI 的核心在于提速。如果你把 AI 节省下来的时间再投入到加速上,而非提升质量,那你就浪费了自己作为开发者的价值。AI 懂得怎样节约时间,而懂得如何打造和构建优秀的应用程序。

当你需要踏入不熟悉的编程领域时,AI 也能提供帮助。在我的日常工作中,我主要编写 SQL、C# 和 TypeScript,但有时也需要编写 Groovy、MDX 或 KQL 的代码片段。熟悉一个新语言至少需要几天时间,而这主要是语法上的问题。像大多数资深开发者一样,我能通过经验判断代码的好坏——语言不是主要的,结构才是关键——但要熟悉如何声明常量或正确迭代数组还是需要时间的。当你走出自己的舒适区时,AI 可以帮助你更快达到目的。一段快速生成的代码可能就是你所需,如果它只是临时性的。如果不是,稍作打磨后,你仍然可以处于领先位置。

AI 编程的未来展望

人们常说,生成式 AI 还处于初期阶段,并将随着时间的推移而大幅度进步。但这个观点需要强有力的证据支持。一位 OpenAI 工程师曾这样表示,大语言模型 (LLM) 不过是对它们数据集的一种近似。而对于这个数据集——整个互联网——我们最多只能希望它不会进一步恶化。考虑到当前网络的激励机制(SEO、内容营销、垃圾邮件和广告),它似乎不太可能变得更好。

我最喜欢的一种编程定义是“让计算机重复人类的错误”。在生成式 AI 中,这一点表现得尤为明显。它的训练几乎完全基于我们的错误。只要我们继续写开源代码让它学习,Copilot 和 CodeWhisperer 就会继续复制我们的错误,逐渐趋向于完美的、理想的平庸。AI 将成为宇宙中最普通的程序员,尽管它的打字速度可以达到每分钟一千字。

你们中的一些人可能无论如何都不会雇佣一个平庸的程序员。我对此表示理解。但如果你的流程中可以融入一大量中等质量的代码,并且你对可能的陷阱保持警惕,AI 就可以成为你团队工具箱中的一项强大工具。