乐于分享
好东西不私藏

从 01 到 AI Coding,软件工程师的第一性原理

从 01 到 AI Coding,软件工程师的第一性原理
如果把计算机七十多年的历史摊开来看,会发现一个很有意思的现象:
技术一直在变,但方向几乎没变。
从 01 二进制,到汇编,到 C、Java,再到面向对象、设计模式、DDD、微服务,直到今天的 AI Coding——
人类一直在做同一件事:不断把自己从机器的细节里解放出来,让程序越来越接近人的意图。
这可能就是理解软件工程师这个职业最好的起点。

一、最早的程序员,真的是在“操作机器”

最早写程序,面对的不是 Java,也不是 Python,而是 0 和 1。
10110000 01100001
今天看来,这几乎不像编程。
但对机器来说,这才是它真正能够理解的语言。
那个时代的程序员,必须知道寄存器、内存地址、机器指令,甚至需要直接面对硬件。
程序员思考的是:

机器下一步应该做什么?

问题很快就出现了。
机器可以理解,人理解不了。
于是有了汇编语言。
MOV AX, BXADD AX, 1
本质上机器还是执行 01,只是我们开始给这些 01 起名字。
这是计算机历史上极其重要的一步。
因为从这里开始,人类第一次意识到:

解决复杂问题,不一定要让人变得越来越像机器,也可以在机器之上建立一个新的抽象层。

这个思想,后来贯穿了整个软件行业。

二、高级语言出现:程序员第一次开始远离机器

再后来出现了 FORTRAN、C、C++、Java。
程序员不需要再关心某个数应该放在哪个寄存器。
我们可以直接写:
total = price * quantity;
这背后的变化,看似只是语法简单了。
其实完全不是。
它意味着程序员思考问题的层级发生了变化。
以前考虑的是:

数据怎么从 A 地址搬到 B 地址?

现在考虑的是:

我要计算订单金额。

程序员开始从“机器怎么执行”,转向“我想让机器做什么”。
编译器接过了大量脏活累活。
于是程序员可以驾驭更复杂的软件。
这也是计算机发展的一个基本规律:

每当底层复杂度被封装起来,人类就可以开始解决更上一层的问题。


三、面向对象和设计模式:复杂的已经不再是机器,而是软件本身

软件越来越大以后,新的问题出现了。
几十行程序不难。
几十万行代码就完全是另外一回事。
这时候,真正让人头疼的已经不是 CPU,而是:
人写出来的软件自己变得越来越复杂。
于是出现了模块化、面向对象、设计模式。
我们开始谈:
封装;
继承;
多态;
依赖倒置;
工厂模式;
观察者模式。
很多年轻工程师第一次学设计模式时,很容易觉得这些东西是在“炫技”。
其实它们背后的问题非常朴素:

如何让一个人能够理解几十万行,甚至几百万行代码?

答案仍然是两个字:
抽象。
不要让一个人同时理解十万个细节。
把变化封装起来,把稳定的部分抽出来,把不同职责分开。
设计模式真正想解决的,从来不是“怎么把代码写得更高级”。
而是:

如何控制复杂度。


四、DDD:软件工程开始真正面对“现实世界”

软件继续发展以后,人们又发现一个更麻烦的问题。
代码组织得再漂亮,如果对业务理解错了,系统依然会烂掉。
比如做一个订单系统。
真正困难的从来不是写:
createOrder()
真正困难的是:
订单什么时候成立?
支付和订单是什么关系?
退款是不是订单状态的一部分?
履约失败以后订单怎么办?
优惠、支付、退款、库存到底应该属于哪个边界?
这些问题,Java 不会告诉你答案。
数据库也不会。
因为答案存在于现实业务里。
这也是 DDD 最有价值的地方。
DDD 真正重要的不是 Aggregate、Entity、Value Object 这些术语。
它真正推动软件工程向前的一步,是:

把程序员的注意力,从代码结构进一步推向业务世界本身。

过去我们问:

这个类应该怎么设计?

DDD 更关心:

这个业务世界到底应该怎么被理解?

软件工程从这里开始越来越接近它真正的本质:
把现实世界抽象成软件世界。

五、微服务:技术边界,本质上开始追随业务边界

后来互联网规模越来越大。
几百个人同时修改一个巨大系统,很快就会失控。
于是 SOA、微服务开始流行。
今天大家很容易把微服务理解成:
Spring Cloud、RPC、注册中心、消息队列。
其实这些都只是实现。
微服务真正想解决的问题依然是:

如何把一个过于复杂的系统,拆成若干人能够独立理解和演进的部分?

而怎么拆?
最终还是绕回 DDD:
按业务边界拆。
订单是一个领域。
支付是一个领域。
履约是另一个领域。
好的微服务边界,本质上往往是业务边界在软件中的投影。
所以从设计模式、DDD 到微服务,看起来出现了越来越多的新概念。
实际上,主线一直没变:
控制代码复杂度        ↓控制系统复杂度        ↓控制业务复杂度
程序员解决的问题,正在不断向上移动。

六、AI Coding:抽象层又一次发生跃迁

然后 AI 来了。
过去,我们已经可以写:
calculate_discount(userorder)
今天,你甚至可以直接告诉 AI:

“给会员系统增加一个支持等级权益和过期续费的能力,并补齐测试。”

以前程序员需要把人的意图,一层一层翻译成代码。
现在 AI 开始接手中间大量翻译工作。
于是软件开发正在发生一次很像“汇编到高级语言”的变化。
过去:
人的意图  ↓设计  ↓代码  ↓编译器  ↓机器
未来越来越可能变成:
人的意图  ↓领域模型 / 约束  ↓AI  ↓代码  ↓机器
Coding 并不会消失。
就像汇编今天仍然存在。
但越来越多的人,不再需要亲自处理每一层细节。
这时候,一个更重要的问题就出现了:

如果 AI 越来越擅长实现,那么软件工程师还负责什么?

答案其实已经写在过去七十年的历史里。

七、软件工程师的第一性原理:不是写代码,而是管理复杂度

从 01 到汇编,我们封装机器复杂度。
从汇编到高级语言,我们封装指令复杂度。
从高级语言到面向对象、设计模式,我们封装代码复杂度。
从 DDD 到微服务,我们开始封装业务和组织复杂度。
现在 AI Coding 又开始封装一部分实现复杂度。
所以如果一定要给软件工程师找一个第一性原理,我认为不是“写程序”。
而是:

不断建立更好的抽象,管理越来越大的复杂度,并最终解决现实世界的问题。

这也是为什么技术不断变化,真正优秀的工程师却总有一些共同特征:
他能看见表象背后的结构;
能从几十个需求中找到稳定的业务概念;
能知道什么应该抽象,什么不应该抽象;
能在复杂系统里找到真正的边界。
语言会过时。
框架会过时。
今天流行微服务,明天可能又回到模块化单体。
甚至今天非常重要的 Coding 能力,未来也可能发生巨大变化。
但有一种能力很难过时:

面对一个混乱的世界,建立一个足够简单、又足够准确的模型。


写在最后

回头看计算机历史,会发现我们一直在远离 01。
但这不是因为 01 不重要。
恰恰是因为一代又一代工程师,把底层复杂度封装了起来,让后来的人可以站到更高的地方。
汇编让我们不用面对 01。
高级语言让我们不用面对寄存器。
框架让我们不用重复造轮子。
DDD 让我们开始真正面对业务。
而 AI,很可能又会把大量编码细节推到下一层。
于是软件工程师终于可以把更多精力放回那个最古老的问题:
现实世界真正的问题是什么?
我们应该如何抽象它?
怎样设计一个能够长期演进的软件世界?
所以,从 01 到 AI Coding,技术看起来走了很远。
但软件工程师真正做的事情,也许从来没有变过:

理解复杂世界,建立抽象,然后让机器替我们解决问题。

计算机七十年的发展史,本质上就是一场不断向上的抽象革命。