Tag Archives: programming

miss.G

乌托邦

很久没有安静完整听完一张专辑了。

刚刚完整听完具岛直子miss.G,没有暂停打断。这不是我第一次听这张专辑,对里面的歌谈不上很熟悉,但几乎都能哼上几句(只是节奏,毕竟我不会日语)。不同于以往的是,这次听的时候是晚上,在房间关上灯,拿出十年前买的头戴式耳机完整听完。买这副耳机的时候想不到它能用那么久,头套的皮已经掉得十分粗糙。

尽管如此,它的声音还是非常通透清晰。也是因为晚上很安静的原因,这次听出了很多之前没听到的细节。比如 Melody 在右声道的贝斯,在嘈杂的地铁即便开主动降噪也很难听到,给予了左右声道非对称的享受。如《花束般的恋爱》里,麦和娟在咖啡厅里说的,「看起来是在听同一首歌,其实两个人听到的是不一样的」。我之前听到的 miss.G 和今晚听到的确实是不同的音乐。

但并不是每天都有时间,或者心情,能有一片完整的时间,戴上耳机在安静的环境里。不看屏幕,不做其他事情,只做听音乐这一件事。

站在创作者的角度,这样自然是最理想的。完成一项作品需要投入大量的时间精力,也是与消费者的对话。有意添加的部分巧思,在嘈杂的环境中,作为隔绝外界噪音的背景音因为不够突出而消失。这显然是创作者们不希望发生的。

但当然不能苛责消费者,每个人对待音乐的看法总归不同,在不同的场合、时间点也不一样。但是好的音乐在认真听的时候确实能给人带来惊喜,而这些惊喜同样与人的经历有关。比如《モノクローム》的结尾就让我想起当年的港乐也是这种熟悉的,逐渐淡出的退场方式。于是想起当年和父亲在国贸友谊城买宝丽金的黑胶,现在想想也是颇具仪式感的方式。

但是快节奏的生活还是逐渐把这种仪式感消磨了,与之一起的,还有总体的,音乐的质量。

类似的变化也发生在其他方面。比如,十年前买的PS4曾经利用率很高,有空就玩。而买了新的PS5后,却反而很少开机,不是新游戏不好玩,也并非没时间,而是再难有当年的心情了。

与之伴随的也是,创作的心情和表达欲同样降低了。回想起来学生时代,思想虽然匮乏(现在看来自然如此),但总归有热情。而如今想法自然相比过往成熟了不少,却也丢失了创作欲。工作确实会消磨精力,毕竟如果每天高强度写代码,甚至更夸张的,从早上开到晚上不停的连续几个会议。

但是在写代码这一块,最近 AI 的发展一方面让我更焦虑,另一方面也让我很惊喜。

这里应该需要给一些非职业程序员讲一下工作中一般代码的组织方式。由于代码是人写出来的,因此很多时候为了代码的「可维护性」,会对代码做一层「抽象」 —— 所谓的「抽象」,我的理解就是为了让后期维护项目的人能更容易「看懂」代码的功能。

举个例子,集装箱就是一个「抽象」。早期的货物运输没有标准,直到 1956 年集装箱的诞生,才确定了运输货物的标准单位。在这之后,卡车司机只需要将这个箱子从 A 点运输到 B 点即可。

很大程度上,初级程序员做的和卡车司机没有太大差别。同样是使用各种「抽象」的函数或者集装箱。而高级也有相当长的时间花在设计这些「抽象」上。用集装箱的思路来看,就是怎么调整集装箱货物内的布局更好地利用空间。

那为什么说修改「抽象」会花费很多时间?因为很多时候在初始设计的时候总会有很多点没考虑到 —— 很大程度上,经验就是能考虑到多一些点。而有些时候早期的设计不好就会导致做到了 A 却难以做到 B —— 按下葫芦浮起瓢。

还是用集装箱举例子:一开始决定用 40 英尺,开始几年用起来没问题,于是推广到全公司统一使用。后续集装箱内部货物摆放都会按照 40 英尺来分配。但是后面随着业务扩张,逐渐扩展了运输更多品类的货物。因此此前的货物摆放方式就需要作出变更。而由于以往都是按照 40 英尺的货柜来作为标准,因此非必要情况下不会增加别的尺寸货柜。

中高级程序员做的事情,就是在现有的标准下,调整内部布局,尽可能满足业务扩张的需要。而「架构师」的则需要论证现有的标准是否需要扩展,需要怎么拓展更合理。比如是增加 20 英尺的还是 40 英尺高立方的。

如前面所述,现代的代码是写给人看的。因此需要保持简洁及良好的代码风格和结构,所以会有大量的代码「复用」。而很多时候,使用「复用」的代码无法完全满足需求,因此需要修改被「复用」的代码。而如同集装箱内的布局一样,修改完一个地方会导致另一个地方出现问题。比如在集装箱里,为了放进一台电脑,可能需要把两台平板挪动一下位置。但这又会导致手机的位置被挤占…… 所以改动一个地方可能导致几十个地方需要变更。

这就是代码复用的代价 —— 和集装箱一样,为了标准需要妥协。

但假如,代码不需要人读懂,甚至不需要后人维护 —— 换言之,不需要集装箱来运输货物,可以吗?

在以往没集装箱的时代,同样也有货物运输,只是效率较低。同样,如果来一个需求就重头写一套代码,效率同样很低,因为代码是人写的,而很多逻辑其实是相同的。人在同一时刻的记忆是极度有限的,因此 Phil Karlton 才会将命名称为计算机科学最难的两件事之一

但是 AI 的出现改变了这个前提:假如我确实来一个需求就写一段完整的代码,不复用代码了。但由于 AI 的效率很高,甚至可以比大多数复用代码的人类程序员更高效完成工作,那我们还需要程序员吗?

而这件事情也正在发生。Anthropic 的 CEO Dario Amodei 最近就说到:「AI 可能在未来 5 年使一半的初级白领工作消失」。从我最近的工作体验来看,这确实很可能发生。既然需要的复杂的工程项目减少了(很难短时间内做到完全消失),只要需求明确,自然语言也可以完成自动化工作。

那么未来,很多人没有工作了该怎么办呢?

从这个角度看,杨安泽在竞选 2020 美国总统时作为其竞选纲领的的全民基本收入确实可能是一个方案 —— 我不是这方面的专家,无法评价。但现在的社会显然还没准备好这层冲击。

或许在某个平行宇宙,AI 普及后确实达到了社会的极度富足以至于人类不需要为了生计工作。所以可以享受很多安静的,没那么焦虑的时光。

但那显然是个理想的乌托邦,而《乌托邦》毕竟是中世纪的作品。

从写一个 WordPress 插件说起

之前博客的《目录》页面用的是 List category posts 这个插件生成。可这个插件虽然功能比较多,但是不支持(还是我不知道?)我要生成的页面。

再往前用的插件是 Dagon Design Sitemap Generator,它可以生成一个以「分类目录」为主题的文章页面列表(例子可以看文章存档 – 木遥的窗子)。但是这个插件很长时间没更新了,甚至它的官网都打不开了,没办法重新下载这个插件。

考虑到这个插件功能并不复杂,索性自己写好了。我的文章本身不多,因此也不用做分页或者其他的配置,用最简单的方式即可。这个插件应该符合以下功能:

  • 生成一个双层级的 bullet list
    • 以「分类目录」为第一层,排序方式按单词字母正序
    • 以该分类目录下属的文章为第二层,排序方式按文章创建时间倒序
  • 「分类目录」的展示需要加前缀 “Category”,且这个前缀需要加粗
  • 「分类目录」的内容为分类标题,该标题为该分类的 URL
  • 文章列表都是可点击的 URL
  • 文章标题后面增加文章创建的时间

以上功能其实不复杂,最后只用把它们拼成 HTML 语法的代码即可。

问题在于,我从来没写过 WordPress 插件,甚至我也不会 PHP。换在两年前,如果需要完成这项任务我应该需要:

  1. 用至少 2 天时间学习 PHP 的基本语法,其中可能包括:
    • 找到合适的上手文档/教材
    • 搜索无数次 StackOverflow 搭一套可运行环境
    • 学点基础语法,并且在写的过程中反复查文档
  2. 用至少 2 天时间学习 WordPress 的开发过程,其中可能包括:
    • 为了性能和效率,先在本地机器跑起一个 WordPress 页面
    • 从 WordPress 的文档看怎么写出一个 Hello World 插件
    • 搜索无数次 StackOverflow 看别人怎么解决各种意想不到的问题

但是自从有了生成式 AI 后,完成这么一项任务变得无比简单。以这次写插件为例,用的是 Anthropic 新发布的模型 Claude 3.5 Sonnet,前后只用了 30 分钟就完成了。我并没有学 PHP 的基础语法,也没有查过 WordPress 的文档。只需要通过合适的 Prompt 引导 AI 生成合适的代码,同时让 AI 告诉我怎么把插件安装到 WordPress 即可。

当然,初次生成的代码不是完美的,但是把需要改进的内容告诉 AI 即可慢慢引导到正确的结果。

这与程序员目前写代码是一样的过程:刚开始写好的大概率是不完善的,有错误或此前没考虑到的地方,一步步改好重新运行,通过不断的试错达到最终的效果。

这就是 Sam Altman 提到的完全使用自然语言编程。几十年前的程序员写的是汇编语言,而今天绝大多数的程序员都不再用,而是通过 Python 等高级语言(这里的高级并非褒义词,而是高度封装的意思,类似于预制菜和炒菜的区别)完成任务。而如今的 AI 是一个新的编译器,它可以让大多数人直接通过自然语言编程。

或者类比一下,coder 有点类似于国内较早学习英文的人,有能力将中英文互相翻译。而现在的 AI 可以充当一个翻译器,让人可以直接用自然语言和计算机交流。

但这并不意味着编程就成为一件无门槛的事—尽管门槛降低了些。我们依然要整理好需求和思路才能完成任务。以刚刚的 WordPress 插件为例,如果只是说「做一个插件支持以『分类目录』归类展示文章列表」,那么有可能会作出很多不同版本的插件。

事实上,这也是 software engineer 和 coder 的区别。前者更多的工作在于将一个较大的任务拆分成小任务,通过合适的方式组合起来完成;而后者更强调翻译这项工作。

这也让我想起,前段时间和朋友聊起,我们这行未来能做什么。我并没有想好这个问题,但是会让我想到如果要转行,什么能力是通用的?在我看来其中一个就是解决问题的思路。小的问题比如家里一颗灯泡坏了怎么修?大的问题类似如果要设计一套银行系统需要怎么完成(我现在自然还不能胜任这项工作)?

也正是因此,前段时间教两个朋友编程的时候,我并没有怎么注重语法,而是更关注解决问题的思路。通过自然语言把问题拆解出步骤,然后翻译成代码。回想起当年自己自学的时候那种无力感实在痛苦,已经忘记是怎么熬过来的了。幸运的是,现在的人不必如此。

前段时间去了趟大英博物馆,看到了镇馆之宝罗塞塔石碑。两百多年前,法国人商博良 (Jean-François Champollion) 以这块石碑为突破口,破译了古埃及圣书体,成为埃及学创始人。这块石碑上印有三种文字,分别是古埃及圣书体、世俗体及古希腊文。或许在未来,非自然语言的代码都会被人遗忘。而某一段写着自然语言注释的代码会成为新的罗塞塔石碑。