打开你手机里的任何一个 App,随便点一个按钮。比如外卖软件里那个「再来一单」。
这个按钮为什么长这样?为什么放在订单详情页的底部而不是顶部?为什么点了之后默认用上次的发票抬头?每一个「为什么」背后,都至少有过一场讨论:产品经理提的需求,设计师画的稿子,工程师写的判断语句,运营要求的文案,法务加的那行小字。这些人可能早就换项目组了,那几场会议也早就散了,但他们的结论留了下来,凝固在你屏幕上,变成了这个按钮。
这就是这本书的出发点:软件即沟通。软件不是一堆中性的指令,它是设计者、开发者、利益相关者之间无数次对话的沉淀物——一场场已经结束的会议,被压成了可以反复运行的形状。
代码是会说话的
工程师读到下面这段代码时,听到的不是逻辑,而是人声:
if (user.isVip && order.amount > 200 && !user.hasUsedCouponThisMonth)
这行代码在说话。它说的是:「某次会议上,市场部坚持优惠要设门槛,财务部怕亏钱加了金额下限,运营怕薅羊毛补了每月一次的限制。」三方博弈的结果,被压成了一个布尔表达式。改这行代码的人,实际上是在改写那场会议的结论——所以老工程师看到这种代码会下意识地去翻提交记录,想搞清楚「当年是谁、为什么定的 200」,而不是直接动手。
所以好的工程师读代码像考古:每一层都埋着某个时代的共识。技术债这个词,大白话讲就是过期的共识还在收利息——当年那个决定在当时是对的,但环境变了,决定没跟着变,于是后来的每一行代码都得绕着它走。
大白话:一份软件就是一份会议纪要的合集,只不过这份纪要能自己跑起来。你删一个功能、改一个文案,都是在替一群不在场的人重新开会。
沟通为什么要被「凝固」
既然软件是沟通,为什么不让它一直保持「沟通中」的状态?为什么非要凝固?
因为运行是要钱的,而且用户等不起。一个按钮背后那场会如果每次点击都要重开一次,这个 App 一秒都用不下去。所以软件工程的整个传统,就是把讨论的结果提前锁死:需求评审锁死「做什么」,设计稿锁死「长什么样」,代码锁死「怎么做」,测试锁死「什么叫对」。一层层锁下去,最后交付给你一个不需要再商量的东西。
这种锁死带来两个巨大的好处:
- 便宜。一百万个用户点同一个按钮,背后是同一个凝固的决定,不用重新讨论一百万次。软件的边际成本趋近于零,靠的就是这个。
- 可靠。同样的输入永远给同样的输出。银行转账不会因为柜员今天心情不好而换一套流程。
但锁死的代价也同样巨大:改起来极其昂贵。每一个已经凝固的决定,要改就得把当年那场会重新开一遍——哪怕参会的人已经不在了。这就是为什么改老系统比写新系统难,为什么「这个需求很简单啊」是所有工程师的噩梦句式。
沟通的链条,和它的断点
传统软件里,沟通的链条是这样的:用户想要什么 → 产品经理翻译 → 设计师翻译 → 工程师翻译 → 代码。每一次翻译都有损耗,而最终形态的软件,是这条链条上所有人认知的最大公约数。
注意链条的两个端点。起点是用户的真实意图,它往往是模糊的、自己都说不清的(「我想要一匹更快的马」)。终点是代码,它必须精确到每一个分支。整条软件工程史,某种程度上就是在修补这条链条上的断点:敏捷开发是想让链条转得快一点,用户故事是想让翻译失真少一点,原型工具是想让用户早点看到自己「其实不想要」的东西。
现在请盯住这个结构,因为全书的关键问题就从这里长出来:如果有一种技术,能让「意图」到「行为」之间不需要层层凝固——如果软件可以在被使用的那一刻才决定自己怎么表现——那这条链条上每一个环节的人,饭碗还端得稳吗?
这不是假设。这就是我们此刻正在经历的。下一章我们先看清楚:传统软件的「硬」到底硬在哪里,才好明白 AI 究竟松动了哪颗螺丝。