当我们在谈论架构
2026-07-29 14:46:33我们为什么要编写代码?
别动,这在线上能跑。
因为我们希望指导计算机去实现一些特定逻辑和业务功能,来解决某些问题,业务功能的达成是我们的目的。那么一个最朴素的问题是,如果我的代码能实现功能,甚至比那些“良好设计”的代码具有更优秀的性能,我为什么要考虑除“实现功能”之外的任何其他问题,比如“良好的设计”?毕竟走的再远,也不要忘记为了什么出发。
“架构”明显是“实现业务功能”之外的目标,很多人趋之若鹜,很多人嗤之以鼻。这个目标到底是技术狂热者无意义的自嗨,还是在服务于更深层的价值?我们可以想象以下场景:我需要一个可以在线订机票的系统,我的代码实现了这个功能,但是整个系统的代码是一个数兆大小、上万行的流水账形式。试问我是否需要投入资源对其进行重新设计,以实现那些老生常谈的高内聚、低耦合?
——当然不用。这个答案的底气来自于“我的代码实现了这个功能”。我们达到了我们的目的,它可以订机票,而代码是否组织良好不提供任何实际价值,重新对其进行良好设计、或者从开始就使用更好设计的投入产出比是零。
但是为什么“架构”这个词还总是出现在故事中?这看起来不仅仅是技术专家的艺术执着,因为“我的代码可以正确地实现功能”往往不是故事的全部内容。
我们再问一个故事背后的问题:
我们如何编写代码?
engineering一词来自于拉丁文ingenium(意为“巧妙”)、ingeniare(意为“设计”)。
对比一下:指导计算机做事时使用的语言形如open("1.txt","r"),指导人做事时使用的语言形如open the file named 1.txt for reading。我们发现似乎前者并不比后者更具难度。
在给定一系列微观的具体逻辑时,把具体细节逻辑转换成代码本质上是一种翻译行为。在某程度上需要如数据库之类的上下文知识,但相较于人类语言上的“直译(literal translation)”,似乎并不需要更多的能力。如果只是把宏观逻辑平铺直叙地流水账式的分解,像字典一样从“car”到“汽车”进行一比一转换,好处是转换过程没有引入任何额外难度;但是在目标足够宏观、足够复杂的时候,“直接翻译”得来的逻辑复杂度的规模一定会爆炸,导致:
- 在空间上,规模可能达到常人无法掌控,只能按照某条路径去局部探索,认知负载高,无法保证正确性;
- 在时间上,在业务需求可能有调整时,需要在盘根错节之中牵一发而动全身的进行修改,响应变化的成本极高。
这对应着工程的两大劲敌:复杂性和不确定性,最终都指向一个问题:在种种情况下我们是否还可以保证上一章的那句“我的代码可以正确地实现功能”。
因此这里真正的挑战是:当要实现的目标足够复杂(或后续可能累加到很复杂的程度)、存在潜在的后续变化时,考虑如何设计和组织业务领域中的概念和逻辑,让我们能够在复杂和变化中,保持对所执行逻辑的掌控。这和一个劳动密集型团队的管理问题很一致,一个执行团队管理者管理的是团队的可靠执行,一个工程师管理的是人造装置的可靠执行。
保证劳动密集型任务执行力的核心,是消解每个人直接面对的复杂性和不确定性,通过分工、流程、监督等机制,把目标组织成一个可复制、可检查的执行系统。软件工程面临的目标同样类似:真正重要的是让概念和逻辑不要变成一团只能局部摸索的纠缠物,而要被组织成可以理解、复用、替换和低成本修改的结构。它关乎着正确性、可持续发展性。
在接受“良好架构”这一新目标之后,更多的挑战就接踵而至:紧张的功能交付周期与架构设计投入的矛盾(选择更早一些的上线还是更整洁一点的架构?)、团队成员水平不一致(为什么研发团队比安全团队有更多的观点分歧碰撞?因为在安全团队中,一个系统能有漏洞就是有漏洞,其目标不是多重的、隐含的、晦涩的、面向未来的)、业务逻辑本身就超级复杂等等。一个优秀的架构,往往不在于我们“做了什么”,而在于“我们能克制什么”,这是一个权衡和妥协的过程。
总之,架构不是业务之外的装饰,而是一组针对概念、逻辑进行职责/协作/边界/依赖设计的高影响决策,其目的是在面对复杂性、不确定性的情况下,仍以可接受的成本维持系统正确。
回到架构
原来这个世界就是在摸大象。
这篇文章实际始于去年,写到一半一直放着,起因是当时团队对于代码设计的不重视,或者说对于设计的不重视。除了研发用代码1:1翻译业务逻辑的情况盛行,产品经理同样会犯产品逻辑发散、缺少一致性的问题。看起来,架构似乎不仅仅关乎于软件本身。
如果产品设计有问题,那么工程层就很难实现低复杂度的“正确性”。在软件工程理论中会区分“本质复杂度”和“偶然复杂度”两个概念(偶然复杂度可以被消解),如果产品设计也可能“不正确”,那么什么才是“正确”、才是真理?要最终解决的问题就是真理,事物的最初形态会自指其最深的本质,这也是为什么业务领域建模是架构设计的起点,领域建模识别本质复杂度,架构设计消解偶然复杂度。因此,设计稿上写的不是交互和跳转流程,而是要解决的问题是什么和怎么解。
前文说过工程和劳动密集型团队的管理问题很一致,但分工消解了个体所面对复杂性的同时,也引入了沟通成本。产品与研发若未对领域概念形成一致理解,沟通中的分歧最终也会沉淀为产品中混乱的边界与依赖。康威定律说设计系统的架构受制于组织的沟通结构,沟通结构本身也是组织系统设计的一部分:谁要理解什么、谁对什么负责、谁与谁之间的交互协议。做好共识成本管理,边界之内的人可以在不了解全貌的情况下做出正确的决策。因此,架构图上画的不是函数和模块,而是职责和协作关系。
和人脑一样,当前大模型的context限制同样是源于“复杂度”和“认知负载”。在高上下文占用时,context rot会导致模型输出质量有所下降。因此使用大模型在解决问题时同样需要架构来隔离控制上下文,这个约束在今天并没有随着AI时代的到来而被削弱。不只是coding场景,Andrej Karpathy也表达过目前“AI做不了”的场景,大多数情况下的原因并非是受限于模型的能力,而是没有把上下文/工具/分解方式等内容合理的配置给AI。梁文锋在谈到AGI路线时也说:“如果你能把一个问题描述的很清楚,给AI完整的上下文和指令,它已经超过人类了”。因此,需要架构的不是代码,而是站在世界复杂性面前的有限认知力。
其实,程序的目的是解决现世问题,是人类能动性在当代世界的代理。架构实际上是对于真实世界中概念和逻辑的设计,代码只是一种表现形式。
Turing was wrong
AI通过了图灵测试,但没通过 code review。
距离动笔写这篇文章已然过去了近一年的光景,像蒸汽机普遍进入手工业,大模型已经从根基开始撼动软件工程业。
回看AI巨头之前的发展,包括在ChatGPT在内的模型都或多或少的偏向对话场景,都在追逐自己的ChatGPT时刻。到后来claude在模型能力和商业上双双取得成功,现在每个模型都在卷coding场景。大模型从最开始的段落补全、到后来生成函数,再到目前借助harness工程、与人协作做到几乎零手写。一个反复被人们提起的问题是,程序员是不是要被取代了。
先跑一点题,AI带来的不只是编码效率的提高,我们同时看到了软件工程中的经典内容开始在harness/loop/及未来的其他XXX engineering的场景下被重新广泛讨论:如何确保在不同理解主体(agent和人)之间达成共识、如何针对产出做工程化验证、为了约束agent行为,架构设计也从各种“老态龙钟”的书籍中搬到了各个务实的skill中,与使用ai的人共同成长。这些方面都在通过skill或者agent建设在网上被更频繁的讨论和分享。所谓饱暖思淫欲,在另一个角度上我们也喜闻乐见的看到,因为执行成本的降低,间接也导致了大家的精力投入从执行层慢慢转向上面的判断层、价值层。有趣的是,随着skill不断被建立、然后纳入模型训练,AI的能力也会在近乎相同的路径上不断发展,这好像是一番人与AI互相提携成长的温馨场面。
在最初为什么团队会对代码设计不重视?因为代码设计解决的是未来的问题,而不是现在的问题。人们的成长是通过不断接受反馈从而逐步完善的过程。但是未来的问题不会立即给予反馈,因此只有两种选择:一个选择是架构师在问题苗头阶段立即给予反馈修正,但这样成员发挥空间变小,甚至不知道为何做出如此修正;第二个选择是等到未来的到来,见证错误做法带来的实际后果,真实结果会引起深刻思考和理解,但这时候再做出修正往往需要更大成本。因此有时候项目的快速发展和团队的快速发展是矛盾的,在某种情况下团队试错成长空间和项目交付效率是零和游戏。
大模型的成长和人是一样的,只不过反馈机制更加明确–目标函数,古德哈特定律说“一项指标一旦变成了目标,它将不再是个好指标”,说的意思是一旦开始观测某个指标,那么这个指标大概率会达成,只不过不一定是以期望的方式达成。指标往往是对目标的极端有损压缩,现在评估大模型完成局部功能性的swe-bench评价分数几乎已经被打满(90%+),但是评估代码是否满足真实合入标准的新FrontierCode评价却远未饱和(10%+)。纯yolo vibe coding的项目经历不断迭代到最后无法维护的例子已经很多了,因此才需要各种harness和loop来做控制。这说明大模型对长程任务的表现更差只是冰山一角,背后的问题是全局性、战略性视角的缺失。
上一章说过,形成有意义的视角的条件是认知力要覆盖被认知内容的复杂度:要么提高抽象层次来消解复杂度,要么硬提升认知力。梁文锋说“大模型的下一个大突破是持续学习”,持续学习意味着成长不仅发生在模型训练阶段,大模型的架构要支持其在推理过程中成长。这不只导致成长效率的提升,也使其接收到的反馈从局部的、微观的人造用例提升到真实世界中更广泛的尺度,使大模型可以在更高维度进行成长,更高维度意味着更抽象的视角,更深入的拆解架构能力。
那么程序员到底什么时候会被替代呢?我的答案已经在提出问题之前给出来了:程序是人类能动性的代理,如果 AI 能在给定任何问题后完全自主地写好解决该问题的程序——包括问题分析、建模、方案拆解,那么它就必然可以在给定任何问题后完全自主地解决问题。
当然,这个答案取决于对“程序员”的定义:图灵曾用“会说话”来定义“思考”,我们正再次用“会写代码”来定义“程序员”。