前阵子看到 Peter Steinberger 发过一句话,短促,但格外扎心:
Duplicating logic is no longer painful. Abstractions still are.
翻译过来很直白:复制逻辑已经不再让人痛苦,抽象依然昂贵。
这句话之所以让人心里一咯噔,是因为它直接撞上了很多工程师长年累月练出来的肌肉记忆。
在传统软件工程的训练里,看到两段长得相似的代码,手就会发痒,忍不住想提个公共函数;看到三个业务有共通的步骤,脑子里就已经在琢磨通用框架了。抽完以后,重复代码消除了,目录结构整齐了,提交代码时甚至会产生一种审美上的愉悦。
但整洁和划算,往往是两码事。
更重要的是,这种手痒的习惯,绝不仅仅存在于写代码这一件事上。在过往的几乎所有脑力工作里,我们都共享着同一套隐秘的审美偏好:把手段上的优雅,当成了专业能力的最高体现。
为什么过去我们崇尚手段上的优雅?
回顾过去几十年的现代工作史,答案其实很简单:因为人肉执行实在是太贵了。
人类的大脑是一个极其精妙但吞吐量很窄的器官。短期工作记忆只有寥寥几个槽位,打字很慢,调试很烦,跨人、跨部门的沟通协同成本更是高到令人窒息。手写一遍代码要半天,人肉录入两遍数据是折磨,组织三个团队重复造轮子则是重大的管理失职。
因为人肉执行的成本高昂,我们才在手段层面构建了无数道精密的防御机制:
为了少写几遍逻辑,工程师发明了设计模式、继承体系和通用底层; 为了减少重复劳动,管理者发明了标准化 SOP、跨部门中台和庞大的审批流; 为了防止信息零散,知识工作者发明了宏大的 Wiki 分类树、标签体系和文档矩阵。
原本,解决业务问题、拿到现实结果才是真正的目标,代码、文档、流程都只是手段。但因为手段全靠人类血肉之躯在艰难维持,久而久之,在手段上做减法、搞提炼、抽共性,就成了最被推崇的能力。 谁能把千头万绪的事物抽成一套抽象模型,谁就被视作更高明的架构师与管理者。
我们在手段上追求优雅,本质上是人类在给自己的生理局限打补丁。
01 与十进制:当底座的物理定律改变了
这让人想起计算机早期的一段经典公案。
早年人类造计算机的时候,几乎所有先驱的第一直觉都是做十进制计算机。道理顺理成章:人有十根手指,人类社会的一切账目都是十进制的。如果让计算机算十进制,人看懂最舒服,转换最自然。
但工程实现却为此吃尽了苦头。为了表达十个离散的状态,早期的机械齿轮与真空管需要极其精密的电压控制,结构极其复杂,故障率居高不下。
直到冯·诺依曼、图灵和香农等人彻底掀翻了这个设定:转向二进制。
在人类眼里,二进制是一种近乎笨拙的倒退。一个简简单单的数字,在二进制里变成了冗长、粗粝、满眼重复的 0 和 1。但对于电子元器件而言,通电和断电、高电平与低电平,才是成本最低、最稳定、最抗干扰的物理现实。
十进制是为了迎合人类生理习惯而强加给机器的复杂度;二进制才是尊重物理规律的最优解。
今天,AI 的爆发正在给所有脑力工作带来一场同等量级的转向。
当大模型可以在几秒钟内重写一个模块、提炼一段录音、定制一份方案、生成一个独立脚本时,执行的边际成本已经断崖式下跌。它就像计算机底层的通电与断电一样,变成了一种近乎免费的充沛算力。
在充沛的执行力面前,人类过去为了节省肉身成本而精心搭建的那些抽象框架、万能 SOP 与大一统平台,突然全都变成了昂贵而别扭的十进制齿轮。
机器可以无限便宜地在局部处理粗粝具体的 0 和 1,而人类却还在拿着过去的肌肉记忆,强行要求所有事情必须在手段上合流。
省下的是重复,买下的是命运相依
一旦算清楚这笔账,就会发现旧审美的荒谬之处:消灭局部的重复,换来的往往是全局的脆弱。
举个最真实的工程例子。 你写了一个脚本整理个人阅读,又写了一个脚本汇总团队简报。两者都有拉取数据、过滤清洗、调用模型提炼正文、排版输出的环节。顺着旧习惯,你一定会手痒,把它们抽成一个通用的 Pipeline 框架,两个业务只传配置。
今天看,代码行数砍了一半,整洁漂亮。
但接下来的业务分岔会迅速击碎这份优雅:个人阅读允许宽松拉取,团队简报要求死线前必须发出且标红缺漏;个人阅读可以随意推倒重跑,团队简报重跑一次就会给整个群发骚扰通知。
工程上当然可以通过加开关、写策略、埋回调来兼容。但几轮演进之后,两个原本毫不相干的业务,被焊死在了同一个底座上。改动个人阅读的解析规则,你得提心吊胆看会不会碰坏团队简报;想给团队简报加个特性,又必须小心别给个人工具增加包袱。
一次不恰当的抽象,本质上是把逻辑上的偶合,强行升级成了维护上的命运相依。
跳出代码,业务管理中这种惨剧更是随处可见。 两个业务线原本各跑各的,动作轻快,反应敏捷。某天高层觉得大家都在做类似的事情,手一挥搞了大一统中台,立下了横跨两个部门的标准化 SOP。结果,A 业务想改一个字段,要找 B 业务开半天评审会,再排期给中台两个月;原本两个各自充满活力的业务,被一套手段上的优雅彻底拖死在了协同泥潭里。
在知识管理里同样如此。很多人花几周时间精心设计了一套包含七级目录的 Notion 或 Wiki 架构,最后却发现,每次记录一个闪念都要面临巨大的分类心理门槛,反而是最简陋的平铺碎记,配合今天的语义检索,能发挥出大得多的复利。
反过来想,如果当初让它们各自保留一套看似重复的逻辑: 两个脚本各自独立,代价无非是硬盘上多占了几十行代码; 两个业务各自探索,代价无非是局部有一些相同的动作。 但换回来的东西却极其奢侈:改动 A 的时候,脑子里完全不需要装入 B 的任何细节;切掉 B 的时候,整个系统的其他部分连眼皮都不眨一下。
上下文是有限资源,资产的半衰期正在变短
在维护了大量项目与团队工作流之后,我对所谓好架构、好系统的评价标准彻底变了。
以前看系统,看的是复用率有多高、体系有多宏大、接口有多完备。 现在看系统,我只看两件事:
第一,一次局部变动,需要把多少无关的上下文装进脑子? 平铺直叙、允许局部冗余的代码和流程,一眼就能看穿起止,改完即走,对人和 AI 都没有额外的心智负担。而一套层层封装的万能体系,表面上改动只需要动一个参数,背后却要求你必须把基类、策略注册表和整个上下游的依赖历史统统装进上下文。 在人脑带宽和模型窗口都极其昂贵的世界里,波及面才是最致命的技术负债。
第二,这套抽象结构,能不能活到它回本的那一天? 抽象是一笔远期投资:前期多花三倍精力提炼通用底座,指望未来复用五次来摊平开销。 但在今天,技术的半衰期缩短到了以月甚至以周来计算。 你上个月为了弥补旧模型缺陷精心设计的一套复杂切片编排,这个月新模型能力一翻倍,直接变成了该被切除的阑尾;你为了预防未来三年业务扩展而搭建的跨部门统一底座,半年后那个设想中的业务压根没来,真正的风口反而在完全没预留接口的荒原上爆发。
底座还在,当初支撑你追求优雅的前提,早已灰飞烟灭。
搭起来不费劲的幻觉,正在让无数人背负起根本无法收回成本的系统垃圾。以前我们怕以后不好加,所以习惯性过度设计;现在我们必须怕以后不好撤,所以要把每一块的解耦边界守死。
留扩展点是在押注未来沿着哪个方向来,而守住随时可替换的独立边界,是让自己在猜错未来时,有能力在几分钟内承认失败,拍拍屁股走人。
允许实现各过各的,守住事实的唯一版本
聊到这里,必须划清一道清晰的边界,防止滑向虚无主义。
容忍重复,绝不等于一切都可以随地大小便、全盘复制粘贴。否则系统很快会走向另一个极端:到处都是幽灵代码,漏洞修了甲处漏了乙处,业务口径各说各话。
核心的界限在于:分清你重复的是胶水实现,还是核心事实。
经典著作《程序员修炼之道》提出的 DRY 原则,核心原文其实非常克制:系统中的每一项知识,都必须有单一、明确、权威的表述。它强调的是知识与事实的唯一,从来没有说过长得像的代码和流程必须合体。
工作中的一切事物都可以切成两层:
第一层是易变的局部实现与胶水流程。 代码里怎么拼装参数、怎么输出排版;业务里各个小队怎么打动用户、怎么写周报;这些纯属局部实现。它们长得再像,也应该允许各自独立演进,野蛮生长,互不干扰。
第二层是不可动摇的事实基石与安全底线。 系统的鉴权规则、资产的计算公式、业务的核心口径、合规与责任的边界。这些属于系统的权威事实,必须有且仅有一处权威定义。
实现可以各自长,规则不能各自编。
与此同时,推倒重来的潇洒只适用于无状态的轻量层。一个瞬时处理的小脚本、一篇草稿、一段汇报文案,随时可以重写;但一个带着历史数据沉淀、承载着外部调用契约的核心业务,推倒重来的代价依然极高。 真正决定一个东西能不能被轻快替换的,不是代码有多少行,而是它的状态沉淀与业务定义,有没有从脆弱的执行实现中干净地解耦出来。
收起那只手痒的手
那么,究竟该如何验收一套系统究竟是先进还是累赘?
过去大家喜欢看静态架构图与流程图:模块对不对称,分层规不规范,大纲完不完整。 但现实世界里最真实的检验,永远发生在第三次需求变更猝不及防砸过来的时候。
当连续几次超出预期的业务剧变砸向你时,这套体系是成了顺理成章的垫脚石,还是成了所有聪明人不得不绕道走的拦路虎? 下一次你发现自己判断错了,能不能只扔掉眼前这一块而不需要向任何人打招呼,还是发现拔出萝卜带出泥,整个大厦都在跟着剧烈摇晃?
如果代码与执行已经便宜到了近乎免费,我们最该节约的,就不是击键的次数和重复的行数,而是人和系统最宝贵的心智带宽与演进自由度。
下一次,当你在代码里手痒想提公共基类,在管理上想搭大一统协作中台,在文档里想建完美的分类树时,不妨先按住自己,平静地问一句:
它们在未来的岁月里,真的有必要同生共死吗?
如果回答不上来,那就先让它们各过各的。
手段上的优雅是人类生理局限下的旧时代产物;在充沛的新世界里,容忍局部的粗粝与重复,给系统留出随时可以撤退的缝隙,才是对抗不确定性最高级的智慧。