ChatGPT 正在殺死編程里的樂趣
多年以來,編程一直是我生命最重要的快樂來源之一,我從沒細想過這份快樂能伴隨我多久。但就在幾天前,在觀摩了 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:
- bytes 和 str 類型兼容性問題
- 用 'a' 模式(追加)打開了文件,無法讀取內容
- 在循環內調用了 .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 寫代碼沒啥樂趣,那么你不用不就完了,廢話這么多干啥?”關于這點,請你考慮以下這個場景。
你在編寫一個函數,試圖將某個嵌套數據類型進行扁平化展開,現在有兩種做法擺在你的面前:
- 完全靠自己手工完成函數和對應的單測代碼,花費 20 分鐘
- 梳理思緒,描述需求,發給 ChatGPT,將它寫的代碼(以及測試用例)略作調整,直接使用,花費 5 分鐘
你會選哪一種?不知道你的選擇是啥,但我目前正處于一種懷疑第一種做法的必要性的狀態中。
寫在最后
親愛的讀者朋友,我承認,本文標題里的“殺死編程里的樂趣”實在有些危言聳聽。ChatGPT 當然無法抹殺編程中的所有樂趣。但是,在你看過我使用 ChatGPT 的經歷后,我希望你能停下敲打鍵盤的手,思考一下:在這個 AI 迅猛發展的大浪潮中,編程這項只有幾十年歷史的智力行為究竟會如何變化,而這些變化會將我們帶向何處?
最后,雖然 ChatGPT 給了我一份質量可比肩(部分)人類的 Python 代碼,但我并不認為它會在短時間內消滅編程,讓程序員這個職業成為歷史。里面的核心原因在于:“規劃與設計”部分短期內無法由機器代勞。
但不會消滅編程,并不等同于 ChatGPT 不會改變人們的編程習慣。我認為它已經開始在調整人們從編程中獲取樂趣的方式了——如果不是直接抹除的話。
也許,那份以經營與策略為核心,完全去除了動作要素的《Hades》游戲已經在路上了。祝我們未來玩得開心。
我的博客: https://www.piglei.com/