ARTICLE · 959069
从 01 到 AI Coding,软件工程师的第一性原理
从 01 到 AI Coding,软件工程师的第一性原理如果把计算机七十多年的历史摊开来看,会发现一个很有意思的现象: 技术一直在变,但方向几乎没变。 从 01 二进制,到汇编,到 C、Java,再到面向对象、设计模式、DDD、微服务,直到今天的 AI Coding—— 人类一直在做同一件事:不断把自己从机器的细节里解放出来,让程序越来越接近人的意图。 这可能就是理解软件工程师这个职业最好的起点。
最早写程序,面对的不是 Java,也不是 Python,而是 0 和 1。 今天看来,这几乎不像编程。 但对机器来说,这才是它真正能够理解的语言。 那个时代的程序员,必须知道寄存器、内存地址、机器指令,甚至需要直接面对硬件。 程序员思考的是: 问题很快就出现了。 机器可以理解,人理解不了。 于是有了汇编语言。 本质上机器还是执行 01,只是我们开始给这些 01 起名字。 这是计算机历史上极其重要的一步。 因为从这里开始,人类第一次意识到: 这个思想,后来贯穿了整个软件行业。
再后来出现了 FORTRAN、C、C++、Java。 程序员不需要再关心某个数应该放在哪个寄存器。 我们可以直接写: 这背后的变化,看似只是语法简单了。 其实完全不是。 它意味着程序员思考问题的层级发生了变化。 以前考虑的是: 现在考虑的是: 程序员开始从“机器怎么执行”,转向“我想让机器做什么”。 编译器接过了大量脏活累活。 于是程序员可以驾驭更复杂的软件。 这也是计算机发展的一个基本规律:
软件越来越大以后,新的问题出现了。 几十行程序不难。 几十万行代码就完全是另外一回事。 这时候,真正让人头疼的已经不是 CPU,而是: 人写出来的软件自己变得越来越复杂。 于是出现了模块化、面向对象、设计模式。 我们开始谈: 封装; 继承; 多态; 依赖倒置; 工厂模式; 观察者模式。 很多年轻工程师第一次学设计模式时,很容易觉得这些东西是在“炫技”。 其实它们背后的问题非常朴素: 答案仍然是两个字: 抽象。 不要让一个人同时理解十万个细节。 把变化封装起来,把稳定的部分抽出来,把不同职责分开。 设计模式真正想解决的,从来不是“怎么把代码写得更高级”。 而是:
软件继续发展以后,人们又发现一个更麻烦的问题。 代码组织得再漂亮,如果对业务理解错了,系统依然会烂掉。 比如做一个订单系统。 真正困难的从来不是写: 真正困难的是: 订单什么时候成立? 支付和订单是什么关系? 退款是不是订单状态的一部分? 履约失败以后订单怎么办? 优惠、支付、退款、库存到底应该属于哪个边界? 这些问题,Java 不会告诉你答案。 数据库也不会。 因为答案存在于现实业务里。 这也是 DDD 最有价值的地方。 DDD 真正重要的不是 Aggregate、Entity、Value Object 这些术语。 它真正推动软件工程向前的一步,是: 过去我们问: DDD 更关心: 软件工程从这里开始越来越接近它真正的本质: 把现实世界抽象成软件世界。
后来互联网规模越来越大。 几百个人同时修改一个巨大系统,很快就会失控。 于是 SOA、微服务开始流行。 今天大家很容易把微服务理解成: Spring Cloud、RPC、注册中心、消息队列。 其实这些都只是实现。 微服务真正想解决的问题依然是: 而怎么拆? 最终还是绕回 DDD: 按业务边界拆。 订单是一个领域。 支付是一个领域。 履约是另一个领域。 好的微服务边界,本质上往往是业务边界在软件中的投影。 所以从设计模式、DDD 到微服务,看起来出现了越来越多的新概念。 实际上,主线一直没变: 程序员解决的问题,正在不断向上移动。
然后 AI 来了。 过去,我们已经可以写: 今天,你甚至可以直接告诉 AI: 以前程序员需要把人的意图,一层一层翻译成代码。 现在 AI 开始接手中间大量翻译工作。 于是软件开发正在发生一次很像“汇编到高级语言”的变化。 过去: 未来越来越可能变成: Coding 并不会消失。 就像汇编今天仍然存在。 但越来越多的人,不再需要亲自处理每一层细节。 这时候,一个更重要的问题就出现了: 答案其实已经写在过去七十年的历史里。
从 01 到汇编,我们封装机器复杂度。 从汇编到高级语言,我们封装指令复杂度。 从高级语言到面向对象、设计模式,我们封装代码复杂度。 从 DDD 到微服务,我们开始封装业务和组织复杂度。 现在 AI Coding 又开始封装一部分实现复杂度。 所以如果一定要给软件工程师找一个第一性原理,我认为不是“写程序”。 而是: 这也是为什么技术不断变化,真正优秀的工程师却总有一些共同特征: 他能看见表象背后的结构; 能从几十个需求中找到稳定的业务概念; 能知道什么应该抽象,什么不应该抽象; 能在复杂系统里找到真正的边界。 语言会过时。 框架会过时。 今天流行微服务,明天可能又回到模块化单体。 甚至今天非常重要的 Coding 能力,未来也可能发生巨大变化。 但有一种能力很难过时:
回头看计算机历史,会发现我们一直在远离 01。 但这不是因为 01 不重要。 恰恰是因为一代又一代工程师,把底层复杂度封装了起来,让后来的人可以站到更高的地方。 汇编让我们不用面对 01。 高级语言让我们不用面对寄存器。 框架让我们不用重复造轮子。 DDD 让我们开始真正面对业务。 而 AI,很可能又会把大量编码细节推到下一层。 于是软件工程师终于可以把更多精力放回那个最古老的问题: 现实世界真正的问题是什么? 我们应该如何抽象它? 怎样设计一个能够长期演进的软件世界? 所以,从 01 到 AI Coding,技术看起来走了很远。 但软件工程师真正做的事情,也许从来没有变过: 计算机七十年的发展史,本质上就是一场不断向上的抽象革命。
一、最早的程序员,真的是在“操作机器”
10110000 01100001机器下一步应该做什么?
MOV AX, BXADD AX, 1
解决复杂问题,不一定要让人变得越来越像机器,也可以在机器之上建立一个新的抽象层。
二、高级语言出现:程序员第一次开始远离机器
total = price * quantity;数据怎么从 A 地址搬到 B 地址?
我要计算订单金额。
每当底层复杂度被封装起来,人类就可以开始解决更上一层的问题。
三、面向对象和设计模式:复杂的已经不再是机器,而是软件本身
如何让一个人能够理解几十万行,甚至几百万行代码?
如何控制复杂度。
四、DDD:软件工程开始真正面对“现实世界”
createOrder()把程序员的注意力,从代码结构进一步推向业务世界本身。
这个类应该怎么设计?
这个业务世界到底应该怎么被理解?
五、微服务:技术边界,本质上开始追随业务边界
如何把一个过于复杂的系统,拆成若干人能够独立理解和演进的部分?
控制代码复杂度↓控制系统复杂度↓控制业务复杂度
六、AI Coding:抽象层又一次发生跃迁
calculate_discount(user, order)“给会员系统增加一个支持等级权益和过期续费的能力,并补齐测试。”
人的意图↓设计↓代码↓编译器↓机器
人的意图↓领域模型 / 约束↓AI↓代码↓机器
如果 AI 越来越擅长实现,那么软件工程师还负责什么?
七、软件工程师的第一性原理:不是写代码,而是管理复杂度
不断建立更好的抽象,管理越来越大的复杂度,并最终解决现实世界的问题。
面对一个混乱的世界,建立一个足够简单、又足够准确的模型。
写在最后
理解复杂世界,建立抽象,然后让机器替我们解决问题。