「实现代码」和「设计软件」之间,还有多少路需要走?

本文属于《我和苏Claw底的理想国》系列文章。该系列作品都是是作者和 OpenClaw 的对话,辩论,分析,甚至是对骂的的内容的整理。

最近有个话题很热:AI 已经能写出满足需求、跑通功能的代码了,所以 AI 完全可以当程序员来用,程序员这个职业要被替代了。

这个判断听起来有道理,但它预设了一件事:程序员的核心工作是写代码。如果这个前提是对的,那 AI 确实威胁很大。但如果这个前提本身就值得怀疑呢?

这让我想认真想一个问题:能实现功能的代码,和软件系统设计之间,到底差了什么?开发的工作,核心是在做什么?

想清楚这个问题之前,我一直觉得"写代码"和"软件系统设计"是同一件事的两个阶段——先设计,再实现,设计是代码的上游。但认真推敲一遍,发现这个前提本身就是错的。


三次争论和推翻:设计不是代码的上游

“软件设计和代码实现之间究竟有多远?”这个问题我们反复争吵辩论了很久,推翻了三次,才稍微能管中窥豹,聊聊我们应该怎么回答这个问题。

最开始,我试图用三个维度来描述设计和实现的差距:局部正确 vs 整体一致,当下可用 vs 未来可变,解决问题 vs 建立语言。但经过多轮争辩后,我发现这三个维度描述的是"好设计长什么样",不是"设计和实现到底有什么本质差别"。

于是我换了一个角度,试图论证“真正的鸿沟是认知差距”。写代码的人把代码当指令,做设计的人把代码当表达。这个说法稍微深了一点,至少在尝试区分「实现代码」和「设计软件」之间的差距,但还是在绕圈子。它在描述两种人的思维方式,没有说清楚设计这件事本身是什么,因此也说明不了“能实现功能的代码,和软件系统设计之间,到底差了什么?”

真正的转折是把对"软件设计"的定义重新建立起来:软件系统设计是面向计算机系统和数据结构的复杂体系,软件设计的核心是组织结构化的数据和编排计算逻辑,核心是决策和设计。除此之外,无论是代码、SQL、Excel 函数,甚至飞书多维表格,都只是软件设计的落地实现方案之一。

如果设计的对象不是代码结构,而是数据的组织方式和计算的编排,那"先设计再实现"这个顺序关系就不成立了——设计和实现根本不在同一个层面上,不存在谁是谁的上游。


MapReduce 和 Raft 说清楚了这件事

我想起曾经看过的几篇经典论文,如果你上过 MIT 的分布式系统课程,你应该对 MapReduce,Raft 这些论文都很熟悉。

MapReduce 的论文没有一行代码。它在描述的是一个计算模型:绝大多数大规模数据处理任务,都可以被分解成映射和聚合两个阶段。这个洞察一旦成立,计算就可以被拆分、分发、容错,整个过程对使用者透明。Google 用 C++ 实现了它,后来有人用 Java 实现了 Hadoop,再后来有人用 Scala 实现了 Spark。实现语言完全不同,但背后的计算组织方式是同一个。

Raft 论文同样没有代码。它在描述的是一个状态组织方式:只要所有节点的日志顺序一致,它们的状态就一致。问题从"怎么同步状态"变成了"怎么保证日志顺序",后者有清晰的数学性质可以利用。etcd、TiKV、CockroachDB 用不同语言实现了 Raft,但数据组织的本质是同一个。

这两个例子把事情说清楚了:设计在决策计算模型和数据组织方式,实现是把这个决策投影到具体的运行环境里。MapReduce 论文和它的 C++ 实现之间,不存在"从论文走到代码需要多远"这个问题。它们是两件事,不是一件事的两头。


那"还有多少路要走"这个问题呢

带着这个框架回头看原来的问题,答案变得很清楚:代码实现和软件系统设计之间,不是距离的问题。

写代码是在执行已经做出的决策——把确定的数据组织方式和计算逻辑翻译成机器能跑的东西。软件系统设计是在做出那些决策——数据应该长什么形状,计算应该在哪里发生,系统的各个部分应该怎么协作。

写更多代码不会自动让你更接近设计能力,因为你在另一个平面上移动。

但有一点是真的:设计的决策需要通过实现来验证。Raft 的日志模型,只有真正跑过网络分区、跑过节点崩溃,你才知道这个决策对不对,才能发现 Raft 仍然有在特定条件下脑裂的缺陷。所以实现不是设计的下游,而是设计的校验手段。只设计不实现,决策没有反馈,容易飘在空中。只实现不设计,执行没有方向,容易做无用功。

所以大多数程序员,其实从来没有打开过“软件设计”的那扇门,只是在写代码,和思考怎么写代码。


回到 AI 能不能替代程序员

现在可以回答开头的问题了。

AI 能写代码,而且越来越好。它在十分高效地执行决策,不是做出决策。你让 AI 实现一个功能,它能给你跑通的代码。但"这个功能的数据应该怎么组织、这个计算应该放在哪里发生、这个边界应该怎么划",这些问题你没有告诉它,它就会用训练数据里最常见的方式来填。填出来的东西能跑,但不一定是对的。

有人会说:那我把所有上下文都扔给 AI,让它先做决策再执行,不就行了?

但这里有一个循环:你怎么知道哪些上下文是相关的?你怎么知道问题的边界在哪里?

把上下文整理清楚、判断哪些信息是关键的、把问题表述准确 —— 这件事本身就已经是软件系统设计的一部分了。你能把上下文完整准确地喂给 AI 的前提,是你已经对问题有了足够深的认识,此时你已经完成了软件设计的地基,AI 在你眼里,只是一个工具和助手。

还有一个更重要的问题:上下文从哪里来?

Raft 解决的问题,是研究者花了十几年研究分布式一致性之后,才把问题本质搞清楚的。这个认识不是凭空产生的,是在真实的失败、真实的约束、真实的业务压力里磨出来的。这个过程产生的东西很难被完整地语言化,更难被完整地传递给 AI。

AI 很擅长在已知结构里填充内容,不擅长在未知里建立结构。


做软件设计时,我们本质是在做什么?

软件系统设计,是在模糊里建立结构的决策和思考。

这句话回答了最开始的问题:代码实现和软件系统设计之间的真正差距,就是有没有能力在模糊里建立结构。这个能力不是靠写更多代码积累出来的,而是靠不断思考真实困境下的问题,长期复盘自己的决策磨炼出来的。

所以 AI 替代的是执行决策的那部分工作,而不是做出决策的那部分。当所有的决策,推演,职责清晰的时候,代码实现反而是最容易完成的“最后一小步”。真正值得担心的不是 AI 取代程序员,而是:那些只会执行决策、从来没有做过设计决策的工程师,他们的位置确实会变得很尴尬。