从“告诉机器怎么做”到“告诉AI做什么”:编程抽象简史

见闻感悟 Sep 3, 2026

编程的历史,讲到底,是一段人类不断把“如何计算”从自己脑子里搬出去的历史。每一次新的编程语言和编程范式出现,都不只是为了让代码看起来更优雅,或者让程序员拥有新的炫技工具,而是在试图解决同一个问题:如何让人少跟机器较劲,把更多精力放到问题本身。从早期盯着硬件、手动输入指令,到今天用自然语言描述意图,让 AI 生成、修改甚至维护代码,这条路上几乎每隔二三十年,就会发生一次关键的抽象升级。

从“告诉机器怎么做”到“告诉AI做什么”:编程抽象简史

回头看会发现,编程的发展并不是简单地从一种语言替代另一种语言,而更像是一层层向上搭建抽象。机器依然在那里,指令依然在那里,代码最终仍然要被执行,但程序员需要直接面对的东西越来越少。过去,人必须关心寄存器;后来,只需要关心变量和函数;再后来,开始关心对象、模块、状态和系统边界;而今天,越来越多的工程师开始直接讨论需求、规格、约束和验收标准。人类与计算机之间的距离越来越远,人类与问题本身之间的距离却越来越近。

机器码与汇编:命令式编程的起点

最早的计算机只认二进制。程序员必须精确写出每一条机器指令和内存地址,稍有不慎,整个程序就可能崩溃,而且换一个型号的机器,原来的程序往往几乎需要全部重写。后来,汇编语言用助记符代替了那串难以阅读的 0 和 1,把类似“10110000”这样的机器指令写成“MOV”,总算让人类能够看懂一点自己到底在告诉机器什么。但汇编依然紧贴硬件,程序员脑子里仍然必须装着寄存器、内存地址、指令集和执行顺序这些概念。

这个阶段的编程,本质上是在直接命令机器:先做这个,再做那个,读取这里的数据,然后跳转到那里执行。程序员不仅需要理解问题本身,还必须理解机器究竟如何工作。所谓“写程序”,很大程度上就是把人的意图翻译成机器能够逐条执行的命令。人类负责几乎所有细节,机器只负责忠实执行,没有抽象,也没有体贴,更没有“你大概是这个意思吧”的智能。

高级语言诞生:两条道路开始分岔

1957 年,FORTRAN 出现,事情开始发生变化。它是第一批获得广泛成功的高级编译型语言之一,语法更接近数学公式,写科学计算的人终于不必时时刻刻关注底层硬件,而可以直接表达计算逻辑。程序员开始能够告诉计算机“我要计算这个公式”,而不再需要亲自安排每一个寄存器和指令。这是一次巨大的抽象跃迁:机器仍然在执行机器码,但人已经不需要直接面对机器码了。

几乎与此同时,另一条完全不同的道路也开始出现。1958 年,LISP 诞生,它的思想根植于更早的 λ 演算,把计算理解为函数之间的套用、组合和变换,而不是简单执行一连串命令。LISP 带来了递归、高阶函数、垃圾回收以及“代码即数据”等今天看起来依然十分现代的思想。它关心的不是“下一步机器应该执行什么”,而是“一个表达式如何被计算,一个函数如何作用于数据”。

于是,编程世界开始形成两条极其重要的路线。一条走向过程式和命令式编程,核心是明确描述程序应该按照什么顺序执行;另一条走向函数式编程,更关心数据如何经过一系列规则发生变换。前者强调过程,后者强调关系;前者更接近人类组织行动的方式,后者则更接近数学描述计算的方式。这两条路线此后几十年不断竞争、融合、互相借鉴,最终几乎共同塑造了整个现代编程世界。

结构化编程:先把程序里的“乱跳”管住

到了 1960 年代,程序开始越来越大,问题也随之出现。早期程序大量依赖 goto 语句,控制流可以从一个位置随时跳到另一个位置,条件不满足又跳回来,多个逻辑分支交错之后,程序逐渐变成一团难以理解的网。后来人们给这种代码起了一个非常形象的名字:“意大利面条式代码”,因为程序逻辑像一盘意大利面,线全缠在一起,你很难知道从哪里开始,也很难预测最终会走向哪里。

于是,结构化编程出现了。它的核心主张其实并不复杂:程序应该尽可能建立在清晰、有限的控制结构之上,例如顺序、分支和循环,而不是允许程序员随意跳来跳去。结构化编程并没有让计算机变得更强,却让程序变得更容易理解、验证和维护。它第一次明确地告诉程序员:代码不仅要让机器能够执行,也必须让人类能够读懂。

Pascal 以及后来的 C 等语言,都深受结构化编程思想影响。尤其是 C,它处在一个非常特殊的位置:既足够接近机器,又提供了足够的抽象能力,可以组织相对复杂的软件系统。此后几十年,操作系统、编译器、数据库以及各种基础软件都深受 C 的影响,它也成为现代软件世界最重要的底层语言之一。

与此同时,还有一件当时看起来并不起眼的事情正在发生。1960 年代初,Simula 引入了类和对象等概念,开始探索一种新的程序组织方式:能不能把数据,以及操作这些数据的行为,组织在一起?当时很少有人意识到,这个看似边缘的思想,未来会掀起一场持续几十年的编程革命。

面向对象:用对象组织复杂世界

面向对象真正成为主流,要等到 1980 年代和 1990 年代。原因很简单:软件开始变得太大了。几十万行代码、上百万行代码,以及数百甚至上千名工程师共同维护一个系统,单纯依靠过程式编程开始越来越难以控制复杂度。函数和数据散落在各处,模块之间彼此调用,状态可能被不同地方随意修改,一个人改了某个全局变量,另一个完全无关的模块可能几天之后才莫名其妙地崩溃。

面向对象给出的解决方案是:用对象来组织复杂系统。对象拥有自己的数据,也负责操作这些数据的行为;内部细节尽量隐藏,对外通过明确的接口协作。Smalltalk 是最早进行系统性实践的语言之一,它甚至提出了“一切皆对象”这样极具感染力的理念。后来,C++ 把面向对象带进了 C 的世界,而 Java 则凭借“一次编写,到处运行”以及成熟的生态,把面向对象推成了工业软件开发的重要默认范式。

OOP 真正解决的核心问题,从来不是“怎么写代码更快”,而是“如何让一大群人共同维护一个庞大的系统,而不至于互相踩死”。它本质上是一种复杂性管理工具,通过封装、继承、接口和模块边界,把一个巨大的软件系统切分成相对独立的部分。程序员开始不再只思考“下一步执行什么”,而开始思考“这个系统应该由哪些实体组成,它们之间应该如何协作”。

函数式编程:另一条路线在学术圈慢慢成熟

与此同时,函数式编程并没有消失,它只是长期待在学术界和少数专业领域中,慢慢打磨自己的思想体系。1973 年,ML 将函数式编程与强大的静态类型系统结合;Scheme 在 1970 年代进一步简化和提炼了 λ 演算相关思想,使词法作用域、高阶函数和尾调用等概念得到更加清晰的表达;1990 年,Haskell 出现,把纯函数、不可变数据和惰性求值推向了近乎极致。

函数式编程有一个非常核心的信念:尽量减少可变状态和副作用。理想情况下,同样的输入永远得到同样的输出,一个函数不会偷偷修改外部世界,也不会依赖难以追踪的隐藏状态。这样做的好处是程序更容易推理,因为你不需要时时担心某个地方是否在背后改变了数据。尤其在并发环境下,如果多个任务都尽量避免修改共享状态,那么大量复杂的问题甚至可以直接消失。

函数式编程最有意思的地方在于,它并不总是试图通过增加更多规则来解决复杂性。很多时候,它选择的是另一条路:减少状态,减少副作用,减少可以发生意外的地方。然而在很长一段时间里,函数式编程仍然被认为“太难”“太抽象”“太学院派”,似乎更适合数学家和编程语言研究者,而不适合承担大型工业项目。事实证明,这种判断后来并不完全正确。

多范式融合:函数式思想开始反向渗透

真正的转折发生在 2000 年代之后。硬件世界变了,过去提高计算性能主要依靠不断提升 CPU 主频,但单核性能提升越来越困难,多核处理器逐渐成为主流。与此同时,互联网服务开始面对海量并发请求,分布式系统和云计算逐渐成为基础设施。人们突然发现,函数式编程中那些曾经被认为“过于学院派”的思想,在这个新时代里竟然极其有用。

不可变数据、纯函数、减少共享状态,这些理念天然适合并发和分布式环境。于是,主流语言开始悄悄吸收函数式编程的特性:Java 8 引入 Lambda 和 Stream;JavaScript、Python、C#、Swift 等语言大量支持高阶函数、闭包和函数式风格;Rust 则通过所有权、借用和生命周期模型,试图在系统级编程中更严格地管理状态与内存安全。

到了这个阶段,纯正的 OOP 或纯正的 FP 都已经越来越少见。真正成熟的工业语言大多是多范式混合体:用对象或模块划分系统边界,用函数处理数据变换,用不可变性减少副作用,用类型系统提前发现错误。编程范式开始不再像宗教,而更像一个工具箱。重要的已经不是“你到底属于哪一派”,而是面对具体问题时,知道什么工具最适合解决它。

走到这里,编程已经完成了三次重要的抽象跃迁:第一次,是从机器指令到高级语言,程序员不再直接管理每一个寄存器和二进制指令;第二次,是从单纯的过程组织走向更复杂的模块、对象和系统结构;第三次,则是从可变状态主导,逐渐转向吸收函数式编程中关于不可变性、纯函数和类型安全的思想。每一次跃迁,都把一部分原本必须由人脑承担的细节交给语言、编译器或运行时去处理,让人类能够把注意力移向更高层的问题。

2025:面向 AI 编程成为新的主线

第四次跃迁,不再主要发生在语法层面,而是发生在一个更根本的问题上:到底是谁来写代码?2021 年到 2023 年,GitHub Copilot 和 ChatGPT 已经让“AI 帮你写几行代码”逐渐成为日常,但那个阶段的 AI 更像副驾驶。人仍然是那个真正驾驶汽车的人:你负责写代码,AI 帮你补全;你遇到问题,AI 帮你解释;你负责整个开发过程,AI 只是提高效率。

真正的变化出现在 2025 年前后。2025 年初,Andrej Karpathy 提出了一个迅速传播开来的词:vibe coding。它描述了一种完全不同的编程体验:你不再从函数开始,不再从 API 开始,甚至暂时不从代码开始,而是直接告诉 AI 你想做什么,让模型生成实现,然后运行、观察、调整,甚至在某些场景里暂时不去关心代码本身。这个词迅速火遍全球,并在同一年被 Collins Dictionary 选为年度词汇。

但真正重要的并不是一个新词,而是工具能力开始跨过某个临界点。模型不再只能“帮你写一个函数”,而开始能够读取整个代码仓库、理解多个文件之间的关系、修改多个模块、运行终端命令、安装依赖、执行测试、修复错误并持续迭代。Cursor、Claude Code、Devin、Replit Agent 等工具,把“对话写代码”进一步推进到了“让代理去完成工作”。

这是一种本质上的变化。过去,你必须亲自把想法一步步翻译成代码;现在,你越来越可以把问题描述给一个能够理解代码、调用工具并执行操作的 Agent,然后让它完成相当大比例的实现工作。程序员开始第一次真正面对一个新的分工关系:人不再负责所有细节,AI 也不只是一个自动补全工具,而开始成为能够执行任务的数字劳动力。

从写代码,到管理意图

当然,很快人们也发现,纯粹的 vibe coding 非常适合快速验证想法,却不一定适合直接构建复杂的生产系统。AI 可以非常快地生成代码,也可以非常快地生成一座漂亮的技术债垃圾场。速度从来不是唯一的问题,当代码库越来越复杂、团队越来越庞大、系统需要长期维护时,架构、边界、测试、安全和可维护性依然不会因为 AI 的出现而自动解决。

于是,实践开始逐渐转向一种更有纪律的方式:人负责定义问题、编写规格、设计约束、明确架构、提供上下文、设定验收标准并审查结果;AI 则负责具体实现、样板代码、代码搜索、重构、调试和大量重复性工作。这种模式可以被理解为 AI-native programming,也可以更直白地称为“面向 AI 编程”或“规格驱动的 AI 开发”。

它并不是“以后不用懂代码了”,恰恰相反,它意味着工程师的角色正在发生迁移。过去,你的大量时间花在逐行实现、记忆 API、编写样板代码、查找语法错误和手动重构;未来,你越来越多的时间可能会花在把模糊的想法变成清晰的规格,把意图转化为可执行的约束,设计 AI 所需要的上下文,审查 AI 的计划和改动,并建立可靠的验证机制。

过去,一个优秀工程师的重要能力是“把代码写出来”;未来,一个优秀工程师越来越重要的能力,可能是“让正确的代码被可靠地生产出来”。这两者看似相近,实际上差别很大。前者关注实现本身,后者关注整个生产过程;前者强调个人编码能力,后者更强调问题定义、系统设计、上下文组织和结果验证。

这其实是历史上的第四次抽象升级

如果把整个编程历史连起来,会发现一条非常清晰的主线。汇编时代,人管理寄存器;高级语言时代,人管理算法和程序结构;OOP 与 FP 逐渐成熟之后,人开始管理系统模型、模块边界和状态;而到了 AI 时代,人开始越来越多地管理意图、约束与验证。

机器接管的东西越来越多。过去是编译器替人生成机器指令,后来是运行时、垃圾回收、框架和类型系统替人处理各种基础细节,现在则进一步变成模型加 Agent,开始接管大量“怎么写”的工作。每一次技术升级都不是让人类变得不重要,而是迫使人类把注意力转移到更高层的问题上。

于是,人必须更牢牢地抓住那些真正困难的问题:写对了吗?为什么要写?需求本身是否合理?架构能否长期演化?安全边界在哪里?系统出了问题谁负责?这个功能是否真的值得存在?这些问题,比“这个函数怎么写”困难得多,也更接近工程本身。

为什么 OOP 和 FP 并没有过时

值得注意的是,面向 AI 编程并不意味着 OOP 和 FP 失去意义。恰恰相反,它们可能变得更加重要。AI 生成的代码同样需要活在良好的结构里,仍然需要清晰的模块边界、合理的抽象、类型约束、不可变数据、纯函数、自动化测试以及明确的接口。没有这些结构,AI 并不会自动消灭混乱,只会以更快的速度生产更多混乱。

过去,那些看起来有些繁琐的工程原则,是为了防止人类程序员把代码库写成一锅粥;现在,它们又有了新的使命:防止 AI 以十倍甚至百倍的速度,把代码库写成一锅更大的粥。好的架构不会因为 AI 而消失,反而会成为 AI 能否真正参与大型工程的基础条件。没有边界和约束,Agent 就没有稳定的行动空间;没有测试和验证,AI 的“完成”也很难证明是真的完成。

因此,AI 时代真正淘汰的,可能不是工程原则,而是那些只能依赖人工逐行堆砌代码、缺乏系统化约束和验证机制的开发方式。未来的软件工程,很可能不是更少工程,而是更高层次的工程。

一条贯穿八十年的线

回头看这八十多年,编程一直在做同一件事:把人脑里“如何计算”的负担不断向外转移。编译器搬走了机器指令,结构化编程减少了控制流的混乱,模块和对象组织了复杂系统,函数式思想减少了部分可变状态,运行时和框架搬走了大量基础设施细节,而今天的 AI Agent,则正在进一步搬走样板实现、机械重构、初版探索、重复调试以及大量代码搜索与修改工作。

被搬走的,并不是工程师的价值,而是那些不应该由人类反复支付的认知税。真正留下来的,反而是工程里最困难的部分:问题定义、系统设计、架构判断、质量验证、安全边界、长期演化与责任承担。这些事情,从来都比写代码本身更难。

八十年前,人必须告诉机器每一个比特;后来,人告诉机器应该按照什么算法计算;再后来,人开始告诉机器系统应该由哪些对象和模块组成;今天,人开始告诉 AI:问题是什么,边界在哪里,哪些事情绝对不能做,以及怎样才算真正完成。

语言还在,范式还在,代码也不会消失。但代码在整个工程中的位置,正在发生变化。它越来越像一种由意图、规格、约束和工具共同“编译”出来的中间产物。未来最优秀的工程师,未必是写代码最快的人,更可能是那个最能看清问题、定义问题、拆解问题、描述意图、设计约束、构建上下文并验证结果的人。

因为当机器越来越擅长回答“怎么做”,人类真正稀缺的能力,将越来越集中在另一个问题上:到底应该做什么,以及怎样判断它是否真的做对了。

从命令机器,到描述问题;从编写实现,到治理意图;从“告诉计算机每一步怎么做”,到“定义什么才算正确”。八十多年的编程史,最终似乎绕回了一个非常古老的问题:

当机器越来越会思考,人类究竟应该思考什么?

Tags

轩帅

轩帅,字琼璞,逍遥自在轩城主,晚晴幽草轩轩主,静轩之别苑阁主,悠然宜想亭主持。

Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.