ChatGPT 正在杀死编程里的乐趣

本文完成于 2022 年末,我在其中分享了自己第一次使用 ChatGPT 编写一个 Python 程序的经历。写作时,我选择从“编程中的乐趣”切入,判断 ChatGPT 未来将改变人们从编程中获取乐趣的方式——天平将缓慢由“解决小谜题”向“规划与设计”倾斜。

如今过去了一年多,ChatGPT 等 AI 工具已成为越来越多人的日常(包括我)。我并不怀念 ChatGPT 出现前的编程,这就像我不会丢掉 IDE,回去使用纯文本编辑器一样。你开始使用这类工具了吗,体验如何?欢迎通过文章留言告诉我。

——piglei 2024.3.11

多年以来,编程一直是我生命最重要的快乐来源之一,我从没细想过这份快乐能伴随我多久。但就在几天前,在观摩了 ChatGPT 替我编写一个 Python 程序的全过程后,我突然有种强烈的感觉:不远的将来,人们能从编程中获得的乐趣可能会逐渐消失。

换句话说,ChatGPT 正在缓慢地“杀死”编程里的乐趣。在解释这个观点之前,让我先带你简单回顾一下:ChatGPT 到底帮我写了个什么程序。

用 ChatGPT 编写程序

先简单介绍一下 ChatGPT。ChatGPT 是人工智能公司 OpenAI 在 2022 年 11 月份推出的基于 GPT 自然语言生成模型的聊天机器人。它功能强大,能轻松完成许多在人类眼中非常复杂的任务,比方说:根据你描述的需求写一个可运行的程序。

前天晚上十一点左右,我正坐在床上刷手机,突然想起一个给路由器用的工具脚本,已经拖延了几个月都没动工。既然自己不愿写,不如这次试试让 ChatGPT 来帮我完成。

这个工具的需求简述如下:

接收一个 URL 地址作为参数,将该 URL 里的域名,以及该 URL 所返回的页面里的所有域名,一并转换成 dnsmasq 服务的配置条目,写入到 /etc/dnsmasq.conf 文件中(需要考虑重复写入)。

为了让 ChatGPT 写代码,我需要用自然语言清楚描述程序的用途和大概的执行流程,这个过程花了我 5 分钟左右。

需求描述如下:

Write a Python program, it accepts an URL address url from command line input, the program extract the domain name from url and stores it in a variable called src_domain, then it starts to request the given URL address and parse the response as HTML, it should find out all valid domain names in the response and stores them in a set called secondary_domains. Now print the src_domain and secondary_domains to inform user.

Let's start to update dnsmasq's config file, combile src_domain and secondary_domains into a big set called domains. Iterate over domains...(之后的内容省略)

将它发给 ChatGPT 后,我瞬间就收到了回复:一长串 Python 代码。


图:ChatGPT 聊天界面

其中一部分摘录如下:

def main():
    # ...
    # Extract the source and secondary domains from the HTML response
    src_domains = {src_domain}
    secondary_domains = extract_domains(html)
    domains = src_domains | secondary_domains
    domains = sorted(list(domains))

    # Create the configuration entries for each domain
    domain_configs = create_domain_configs(domains)

    # Write the configuration entries to the dnsmasq config file
    dnsmasq_conf_path = '/etc/dnsmasq.conf'
    write_config_to_file(domain_configs, dnsmasq_conf_path)
    # ...

客观来说,ChatGPT 给我的代码结构清晰、注释准确、函数和变量命名恰当,整体有模有样。我将其保存在本地,准备执行。不过令人意外的是,第一次执行失败了。

一阵排查后,我发现代码中至少存在 3 个 Bug:

  1. bytes 和 str 类型兼容性问题
  2. 用 'a' 模式(追加)打开了文件,无法读取内容
  3. 在循环内调用了 .read() 方法读取文件,但文件游标不会重置,因此只有第一次才读到了完整内容

这些 bug 在 Python 中很常见,因此改起来并不麻烦。将它们通通搞定后,程序终于可以正常运行了。经过简单的测试和验证,我发现它完美实现了我要的功能。

之后我算了一笔时间账。从开始描述需求到调通整个程序,我一共花了 10 分钟左右。也就是说,在不到半个番茄钟的时间内,我成功借助 ChatGPT 把脑海中的想法变成了 88 行可运行的 Python 代码。

不夸张的说,当晚我失眠了。半夜四点,我从床上坐起来,脑海中一直重复着一些问题:“我以后应该如何编程?向计算机描述需求,由计算机完成,还是自己打开 IDE 直接上手?在许多年以后,人们还需要编程吗?我们现在到底是为何在编程?”

从这些问题开始一路发散,我突然想到:“乐趣”一直是驱动我们编程的一个重要推动力。具体来说,编程带给我们的乐趣可被大致分为两类,而目前的情况是:ChatGPT 正迅速吞噬其中很重要的那一类。

编程里的两类乐趣

“创造使人快乐”——这个特点可能数万年前就刻在了人类基因里。编程就是一种创造性工作。人们通过编写代码,一步一个脚印实现自己想要的东西,这个过程让人心情愉悦。这种愉悦和“建造一所房子”、“制作一件工具”所产生的愉悦类似,都是在人类创造事物时自然产生。

而藏在编程这件事里的乐趣,大致可分为两类,它们分别来自于编程中的两大环节,一个是“规划与设计”,另一个是“解决小谜题”。

1. “规划与设计”

在开发软件项目时,当我们从用户那接到一个需求后,第一件要做的事情就是“规划与设计”。在这个环节,我们需要先理解用户需求,随后在头脑中完成一些“大”的决策,比如:

  • 如何利用项目中的业务模型与术语,翻译这个用户需求。
  • 分析该需求将给项目中的每一层带来哪些改动。
  • 在实现时,哪些部分需要考虑扩展性,哪些部分不需要。
  • 如何处理与之相关的旧代码,合并、改写还是扩展?
  • ……

一言以蔽之,在“规划与设计”环节,我们考虑的核心问题是:“如何在满足用户需求的同时,让项目质量在长期维度上保持健康。” 个中要诀,在于将软件的整体复杂度维持在一个合理范围内,不要过度增长。

2. “解决小谜题”

完成“规划与设计”后,下个环节是“解决小谜题”。该环节的目标,是将“规划与设计”里的每个“大决策”,分解为一个又一个的“小谜题”,随后逐个击破。

举个例子,“给用户注册接口增加密码强度校验”这个需求,可能会被拆解为以下这些小谜题:

  • 如何从请求中读取用户输入的密码?
  • 如何校验密码必须包含至少 1 个特殊符号、1 个大写字母?
  • 如何获取用户之前的旧密码,并判断是否和新密码相等?
  • ……

一旦所有谜题被明确后,下一步就是编写代码解决它们。有许多技巧和工具能帮你能更流畅、更快速的解决每个谜题,比如说:实践 TDD(测试驱动开发)、查文档或求助于搜索引擎,等等。但它们之中没有一个能和 ChatGPT 相提并论。

ChatGPT 带来的变化

自人类发明计算机的第一天起,程序员就在完全依靠自己的头脑完成以上两个环节的工作。

但有了 ChatGPT 后,你会发现,一旦“规划与设计”部分已经被搞定,那么剩下的工作:解决一个又一个的小谜题,其实已不再需要人们亲自编写代码了——只要将需求丢给 ChatGPT 就行。

因为纵使某个需求复杂无比,一旦它被拆解为许多独立的小谜题后,每个谜题所涉及的抽象概念与逻辑关系都会大幅减少。这就意味着,你根本不需要花费多少工夫,就能将它清晰地描述给 ChatGPT,由它完成代码的编写。

第一眼看上去,你是不是觉得这对程序员有好处?因为这么做能极大提升我们的工作效率呀!但在认真思考过这件事后,我发现它在提升效率的同时,也可能会带来另一个严重的问题:当每个人不再需要亲自动手解决那些小谜题后,编程的乐趣会消失一大半。

为什么这么说?让我用一个我很喜欢的电子游戏《Hades》来做个类比。

以《Hades》来类比编程

《Hades》是由 Supergiant Games 开发的一款以希腊神话为背景的动作游戏。在游戏中,你操作冥界王子扎格列欧斯逃离冥界。


图:Hades 游戏封面

《Hades》的核心游戏体验由两部分构成:“实时战斗”与“能力构建”。

“实时战斗”部分很好解释,游戏包含多种可供选择的武器,比如:冥府之刃(单手剑)、永恒之矛、索心弓等。每次游玩前,玩家可以选择其中一把。为了获得最好的奖励,你需要熟练使用各种武器、躲避每一次攻击,用精湛的操作击败每一个敌人。

“能力构建”则是《Hades》的另一个极具特色的游戏机制。《Hades》是一款 Rogue-like 游戏,玩家每次游玩的所有关卡都是随机生成,每开始一次新游戏,主角的能力值都会被重置。当你操作角色,闯过一个小关卡后,地图上会随机出现两道通往下一个关卡的门,每道门上标注着你能拿到的奖励。你需要在这两道门之间做出选择。


图:选择下一道门

游戏中的奖励五花八门,它们包括:增加生命值上限、增加大量金币以及最重要的一种角色能力增强——来自不同奥林匹斯神灵的“祝福”。这些“祝福”,有的会增强角色攻击力,有的会给普通攻击增加反弹效果,有的会提升你的冲刺距离,还有的则会直接升级你的武器,给其增加新的酷炫动作。


图:选择“祝福”

《Hades》这款游戏引人入胜的原因,在于它完美融合了“实时战斗”与“能力构建”两部分内容。游戏发售后,数以百万计的玩家(包括我)沉浸其中。我们潜心研究武器和“祝福”的每种组合,在选择下一个奖励时绞尽脑汁,沉迷于操作主角用极富技巧性的战斗将每位敌人轰杀至渣。

现在,请想象在另一个平行世界中,《Hades》的开发组发布了《Hades》游戏,但在这个时间线的《Hades》里,玩家不再需要亲手操作冥界王子解决每场战斗,而是只需要在每次游玩前负责以下这些事:

  • 挑选一把武器
  • 选择能力加成
  • 选择下一道门(奖励)
  • 选择众神的“祝福”
  • 选择每场战斗的策略,比如:优先投弹攻击还是莽进敌人堆

总而言之,在这个游戏中,玩家不再需要练习如何操作索心弓射出蓄力一击,如何使用永恒之矛的冲刺攻击高效击杀敌人。玩家要做的所有事情,就是在每个关键节点做出分析和指示,然后观察 AI 完成所有战斗,坐享最终的奖励。

你觉得这样的《Hades》游戏,还像之前一样那么有趣吗?

一款注重经营与策略,完全去除了动作要素的《Hades》游戏,这就是我认为 ChatGPT 可能会将“编程”最终变成的样子。

关于 ChatGPT 的一些疑问

假如到目前为止,你还没有真正使用过 ChatGPT,那么相信你一定会有一些疑问。

ChatGPT 写的代码真有那么好吗?

平心而论,ChatGPT 写的代码并没有那么完美,相比许多经验丰富的程序员仍有不小的差距。就像我在之前所描述的,ChatGPT 写的代码可能并不能直接运行,有着一些细小的 Bug。

但 ChatGPT 的另一个强大之处,在于你总是可以通过对话的方式,不断要求它改进代码。比如我在编写工具脚本时,就这样要求过它:

  • 请将代码按指责封装为不同的函数,主函数的名称为 main
  • 请不要使用任何第三库完成 HTTP 请求

从结果看来,ChatGPT 似乎已经可以完美理解我的请求,瞬间就给出了修正后的代码,这一点足以给我留下深刻的印象。

不用 ChatGPT 不就完事了?

读完前面的所有内容,也许你有句话一直在心里憋着,不吐不快:“既然作者你觉得用 ChatGPT 写代码没啥乐趣,那么你不用不就完了,废话这么多干啥?”关于这点,请你考虑以下这个场景。

你在编写一个函数,试图将某个嵌套数据类型进行扁平化展开,现在有两种做法摆在你的面前:

  1. 完全靠自己手工完成函数和对应的单测代码,花费 20 分钟
  2. 梳理思绪,描述需求,发给 ChatGPT,将它写的代码(以及测试用例)略作调整,直接使用,花费 5 分钟

你会选哪一种?不知道你的选择是啥,但我目前正处于一种怀疑第一种做法的必要性的状态中。

写在最后

亲爱的读者朋友,我承认,本文标题里的“杀死编程里的乐趣”实在有些危言耸听。ChatGPT 当然无法抹杀编程中的所有乐趣。但是,在你看过我使用 ChatGPT 的经历后,我希望你能停下敲打键盘的手,思考一下:在这个 AI 迅猛发展的大浪潮中,编程这项只有几十年历史的智力行为究竟会如何变化,而这些变化会将我们带向何处?

最后,虽然 ChatGPT 给了我一份质量可比肩(部分)人类的 Python 代码,但我并不认为它会在短时间内消灭编程,让程序员这个职业成为历史。里面的核心原因在于:“规划与设计”部分短期内无法由机器代劳。

但不会消灭编程,并不等同于 ChatGPT 不会改变人们的编程习惯。我认为它已经开始在调整人们从编程中获取乐趣的方式了——如果不是直接抹除的话。

也许,那份以经营与策略为核心,完全去除了动作要素的《Hades》游戏已经在路上了。祝我们未来玩得开心。