兰 亭 墨 苑
期货 · 量化 · AI · 终身学习
首页
归档
编辑文章
标题 *
URL 别名 *
内容 *
(支持 Markdown 格式)
在近一年深度体验过Claude Code,Codex以后,我的日常工作形态发生了根本性的变化:只要能用清晰的自然语言描述出业务意图,交互逻辑或是数据结构,AI就能在几秒钟内写出数百行功能正确甚至附带注释的代码。 我似乎已经可以完全不手写代码了。 既然AI写代码的速度如此之快,覆盖面如此之广,那么传统的软件工程原则和程序员的角色,是不是即将成为历史?未来的开发,是不是只需要不停地对AI写Prompt就足够了? 但是,在那些“用AI十分钟写出一个网站”的泡沫背后,当我试图完全用AI来构建,维护和重构一个真正的生产级业务系统时,随着代码量和复杂度的膨胀,真正的问题才会出现: AI开始频繁产生幻觉,改了A模块却悄悄搞坏了B模块的状态。 为了实现一个简单的功能,AI会写出冗长且与现有系统格格不入的代码,不会去复用已有的逻辑。 系统陷入了无尽的Bug循环,修复一个问题往往会引发另外三个问题,最终导致项目因为改不动而陷入停滞。 很多人将此归咎于当前的AI模型还不够聪明,或是上下文窗口还不够大。 但真相并非如此。 AI编程的本质并非许愿机一样的魔法,而是一个超强的执行引擎。它拥有卓越的局部逻辑推演和语法生成能力,但它对整个系统的宏观业务直觉,领域边界的划分,以及状态一致性的全局把控,几乎为零。 代码生成的边际成本越是趋近于零,系统的复杂度就越是呈指数级爆炸。在这个时代,功能变得极度廉价,而秩序变得无比昂贵。架构设计,技术选型和边界约束的价值,比以往任何时候都放大了十倍甚至百倍。 这篇文章将深入探讨在AI完全接管代码编写的时代,为什么那些看似传统的软件工程基本功(如职责隔离,沙漏模型,流水线等)非但没有过时,反而成了减少系统复杂度,重塑系统稳定性的唯一解。 克制AI造轮子的冲动,选型和复用才是关键 在探讨复杂的架构模式之前,我们需要先直面AI编程时最常见也是最容易被忽视的一个陷阱:AI极其旺盛的造轮子冲动。 当你用自然语言向AI描述一个需求,比如:“实现一个支持拖拽排序且带有动画缓冲效果的树形列表”时,如果没有明确的架构约束,AI大概率会选择从零开始手搓代码。 它会调用原生的DOM API,自己实现坐标计算,状态管理,甚至手写一套简单的物理动画算法。从局部来看,这段数百行的代码可能运行得非常完美,充分展示了大语言模型强大的逻辑推理能力。 但这对于一个重型工程来说,往往是一场灾难。 手搓的复杂逻辑不可避免地带有边缘用例的缺陷。当用户在特定的浏览器或极端的交互路径下触发Bug时,你很难让AI迅速定位并修复,甚至因为修复一个Bug或者新增一个功能,带来更多的Bug与隐患。 除此以外,当项目变大时,每一次让AI修改这个组件,它都需要将这数百行底层的拖拽和动画逻辑重新加载到它的上下文中。这不仅消耗了大量的Token,过多的无关细节也会导致它在修改核心业务逻辑时频繁产生幻觉与错误。 开源选型,是开发者在AI时代的必修课 在Vibe Coding时代,写代码的边际成本虽然降到了零,但维护代码的成本却极高。因此,少写代码比以往任何时候都重要。 在这个逻辑下,技术选型不再仅仅是为了避免重复劳动,更是为了给AI提供一个绝对稳定且它自身极其熟悉的环境。 目前主流的代码大模型,其训练语料中包含了海量的GitHub优质开源项目。这意味着,AI对React Flow,Jotai,Framer Motion或是后端的Prisma等主流库的API烂熟于心。 同样是实现那个复杂的树形列表,如果你在Prompt中强制规定:“使用dnd-kit完成拖拽排序的实现,所有的复杂动画必须交由Framer Motion处理”,AI只需要生成几十行调用API的代码。 通过技术选型,我们将那些最容易出错的底层复杂度交给了经过千锤百炼的开源社区。AI的任务从创造变成了集成,其输出代码的简洁度和稳定性会得到质的飞跃。 代码复用,才能收敛AI的注意力 如果说外部开源库是第一道防线,那么在系统内部,将公用代码极致复用则是我们必须掌握的第二道护城河。 在传统的软件工程中,我们提倡代码复用,主要是为了让人类开发者更容易维护代码。但在AI时代,这成了一种节省上下文和规避Bug的救命策略。 想象一下,如果你在五个不同的组件里都让AI实现了类似的数据格式化函数或API错误捕获逻辑。当业务规则发生变化时,你很难确信AI能一次性找全这五个散落的地方并一致性地修改它们。 正确的做法是建立公用的逻辑库并强制AI进行复用。 当你需要修改业务规则时,你只将那个仅有几十行代码的shared/utils.ts扔给AI。在这个没有任何噪声的上下文中,AI可以做到100%的精准修改,不会因为UI或复杂的状态逻辑而产生幻觉。 职责隔离的四段式架构 如果说第一章的选型与复用是为了在宏观层面控制AI引入的复杂度,那么当我们深入到具体的业务模块内部时,面临的挑战将更加棘手。 在传统的业务开发中(特别是前端或全栈领域),开发者为了图快,常常将状态,网络请求,副作用以及视图渲染写到一个庞大的组件文件中。这种写法在人类维护时就已经足够令人头疼,而在Vibe Coding时代,它对AI更是致命的。 为什么AI极度恐惧逻辑与UI混杂? 当我们让AI去修改一个混合了500行UI标签和500行复杂业务逻辑的组件时,往往会出现一种典型问题:幻觉与上下文失焦。 AI可能会极其聪明地帮你优化了数据的过滤算法,但同时,它也把你原本精心设计的复杂DOM结构给简化了。 根本原因在于,当前的大语言的注意力机制是有限的。当它面对充斥着各种视觉细节,生命周期钩子和异步操作的庞大上下文时,它无法只专注于核心逻辑。它的注意力会被那些杂乱的信息分散,最终输出妥协后的代码。 要使用好这台缺乏全局视野的机器,唯一的解法就是实施职责隔离。 对AI友好的四段式架构模型 在深度参与重型复杂应用(如类Figma的编辑器)的实战中,我总结出了一套对AI友好的分层架构模型。这套模型不仅能让人类开发者保持清醒,更能确保每次投喂给AI的上下文都是纯粹且极低噪声的。 可以将系统严格划分为四个隔离的层级: 第一层:Types 层(统一全局契约) 这是整个系统的类型定义与绝对约束。 在人类编程时代,TypeScript的类型定义更多是为了静态检查和自动补全,但在AI时代,全局统一的Types层是约束AI生成逻辑的根本。 当你把定义严密的User, DocumentState, ActionPayload等接口文件喂给AI时,你实际上是在向AI注入整个系统的业务规范。只要Types足够严谨,AI生成的逻辑大概率是对的,因为它天然懂得如何遵守类型契约。这彻底消除了它因为瞎猜数据结构而产生的幻觉。 第二层:Core 层(纯算法与基础逻辑层) 这一层是绝对纯粹的领域逻辑。 它不包含任何外部状态(如React的State或是数据库连接),不产生任何副作用,甚至不依赖任何外部环境(Browser/Node)。它全是诸如数据转换,复杂物理计算,树结构遍历等纯函数。 这是AI最擅长发挥的区域。你只需要丢给AI一个明确的输入和输出结构,它能瞬间写出极其精妙的算法,而且这一层可以让AI自动生成全覆盖的单元测试。由于完全没有环境依赖,AI在这里犯错的概率几乎为零。 第三层:Engine 层(集中式逻辑处理与状态枢纽) 这是系统的心脏,通常是Instance-centric(以实例/服务为中心)的设计模式。 所有的状态管理(如集中式的Store),副作用的统筹,网络请求的编排,以及核心业务流程(如撤销/重做,协同同步),全被收敛并封存在这里。 当业务规则发生变更时,AI只需要也只能在这个层级进行修改。它不需要知道按钮长什么样,也不需要关心路由怎么跳转,它只负责维护业务状态机的正确运转。 第四层:UI层(生命周期,交互与渲染层) 在这一层,我们强制要求不包含任何复杂的业务计算。UI组件唯一的职责就是:订阅Engine层的数据并渲染出来,以及将用户的交互(点击拖拽输入)翻译成简单的指令转发给 Engine。 当你要改界面样式时,你只把UI文件丢给AI。因为没有复杂的业务逻辑干扰,AI可以完美地使用Tailwind CSS或各种组件库帮你做出极致的视觉效果。 隔离的红利:微型上下文与极高良品率 这套四段式架构看似增加了早期的建构成本,但在Vibe Coding中,它带来了难以估量的红利。 这种边界清晰意味着:每一次你向AI发出指令,你只需要给它喂特定领域的上下文。 要优化排序算法?只给AI看Core层的纯函数。 要增加一个鉴权状态?只给AI看Engine层的Store和Types契约。 要修改按钮颜色?只给AI看极其单薄的UI组件。 因为AI每次处理的上下文都足够纯净,它的逻辑推演能力可以完全发挥。它不会再因为修改UI 而牵连破坏核心状态,也不会在写核心算法时因为纠结如何渲染而产生幻觉。 在AI时代,最好的架构,就是让AI永远只做填空题。 沙漏模型,驯服AI的副作用爆炸 如果说前两章的模块拆分和复用抽象是为了在静态代码层面降低AI的认知负担,那么当我们系统真正运转起来,面对用户源源不断的交互指令和复杂的状态流转时,真正的考验才刚刚开始。 在任何稍微复杂的业务系统(尤其是重型编辑器,协同文档或大型后端事务流)中,最让工程师抓狂的,永远是副作用的管理。 传统的灾难链路:逻辑的组合爆炸 在传统的,缺乏严格约束的架构中,我们常常看到这样的业务流: User Input (用户操作) -> Commands (业务指令) -> Mutation (直接修改状态) + Side Effects (处理副作用) 在这个链路中,每一个用户操作都在自己负责修改数据,并顺手处理各种相关的副作用(发起网络同步,记录日志,触发动画,更新本地缓存,发送统计埋点)。 为什么这在Vibe Coding时代是一场灾难? 假设系统里已经有了50种用户操作(比如:拖拽卡片,批量删除,快捷键复制,撤销等),那么就意味着有50个散落的副作用触发点。 当你让AI去“新增一个批量修改属性的功能”时,AI会极其熟练地写出第51个Command,它会完美地修改当前的状态数据。但是,AI大概率会忘记在这个Command的末尾加上网络同步或记录日志的代码。 因为AI的上下文窗口有限,它不可能在写新功能时,把你另外50个文件里的副作用处理逻辑都遍历一遍以确保一致性。结果就是:系统在局部功能上跑通了,但在全局状态上出现了致命的不一致。这种隐蔽的Bug,随着功能增加会呈现出恐怖的复杂度爆炸。 沙漏模型:架构的收敛与复杂度降维 为了减少这种副作用爆炸,我在实战中摸索出了一条极强约束力的架构范式,即沙漏模型: User Input -> Commands (业务意图) -> Base Operations (原子操作) -> Side Effects (统一副作用) 在这个模型中,系统的控制流像一个沙漏: 漏斗上方(无限膨胀的业务意图):用户意图千变万化,前端可能有上百种复杂的交互组合。这是AI可以快速迭代的。 狭窄的腰部(极其稳定的原子化指令):无论上层的业务逻辑怎么组合,底层真正去修改系统状态的原子级写操作(比如InsertNode, UpdateAttribute, DeleteEntity)被严格收敛到极少数。 漏斗下方(统一监听的副作用):所有的副作用(网络同步,缓存,日志等)绝对不允许在Commands层触发,它们只去监听那几个极少数的Base Operations。 当你把系统的架构切换到沙漏模型时,无论业务怎么成倍增加,由于底层的原子化操作是恒定的,副作用的复杂度就被牢牢锁住了,永远不会膨胀。 这对于Vibe Coding来说,简直是降维打击: 当你让AI去写一个新的业务逻辑时,由于架构做了硬性限制,AI只需要也只能去调用那几个预设好的Base Operations组合。你根本不需要在Prompt里千叮咛万嘱咐:“记住改完数据后要发一次网络请求保存哦!” 因为只要AI调用了Base Operations,底层沙漏的管道会自动触发所有必须的副作用。 当你要修改网络同步的重试策略时,你只需要让AI去读那个特定的管道文件。当你要新增业务时,你只让AI去看业务文件。 这就解释了为什么同样的AI模型,在烂架构里总是写出Bug,而在好的架构里却能像神一样高效。因为好的架构,从根本上剥夺了AI犯错的机会。 数据流与派生策略的全局决断 当我们通过四段式架构隔离了微观职责,又通过沙漏模型收敛了动态副作用后,摆在开发者面前的最后一个,也是最宏大最致命的挑战出现了:整个系统的数据流向与宏观架构模式该如何决断? 很多人认为,既然AI的代码生成能力如此强大,只要告诉它需求,它就能自动选择最合适的架构。但事实恰恰相反,AI 是一个极其优秀的战术执行者,但在全局架构上却极其失败。这就是为什么在Vibe Coding时代,架构选型的作用比以往高出了数倍。 写操作的绝对收敛:Write Pipeline(写侧流水线) 如果不加任何系统级的约束,AI最自然的反应是在需要修改数据的地方,随手写下一个分散的写入逻辑(比如在React 中随处调用setState,或者在后端直接updateDB)。 在简单的CRUD页面中,这或许能凑合运行。但在重型应用(如协作编辑器或复杂交易系统)中,这种散点式写入是维护的灾难。 为了让AI能够在一个高度确定性的环境中工作,我们必须引入统一的Write Pipeline机制。这在传统后端架构中被称为CQRS(命令查询职责分离)的写侧,但在前端和客户端复杂应用中,它同样是极其关键的存在。 所有的状态变更,必须被封装为一个统一的Operation。所有的 Operation,必须被送入唯一的一条Write Pipeline中去执行。 为什么这对AI如此重要? 因为在这个模型下,系统的数据变迁变得百分之百可追溯。当AI在开发新功能时,如果涉及到数据的写入,它只需要生成一个Operation丢进流水线。流水线上的各种中间件(统一的监控打点,异常捕获,细粒度鉴权,甚至乐观更新)会自动对这个写操作进行处理。你不需要每次都在提示词里提醒AI“别忘了加try-catch”或“记得判断用户权限”。 当你需要排查数据不一致的Bug时,你只需要让AI审阅pipeline.ts和相关的operation定义,而不是去翻找那50个可能触发了写入的UI组件。 读操作与派生数据:宏观架构的抉择 相较于写侧的收敛,读侧(数据的获取与派生)往往更加复杂,也更需要人类架构师的决断。 在现代前端和复杂系统中,我们经常面临这样的抉择: 驱动模式的选择:读侧的派生数据(如:根据核心树结构计算出的视图缓存),是应该采用基于Signal的细粒度响应式更新?还是采用基于事件驱动的发布-订阅模式,由各个组件按需重新计算? 通讯机制的定调:整个应用是数据驱动型,事件总线型,还是传统的同步调用型? 派生策略的统一:读侧的缓存更新和派生计算,是否也需要像写侧一样,抽象出一套统一的Operation规范? 这些问题,AI永远给不出唯一正确的答案,因为它不懂你的业务特点。如果你在这个阶段让AI自由发挥,你的系统很快就会变成一团乱麻:A模块用Signal更新,B模块用Event Bus传值,C模块在组件里狂写useEffect手动同步状态。 从代码编写者到AI系统架构师 这正是Vibe Coding时代最激动人心也是最残酷的现实:手写语法的能力正在断崖式贬值,但系统建模和架构决断的能力正在前所未有的稀缺。 在项目建构的第一天,你的核心工作就应该是: 评估业务复杂度(是简单的表单流转,还是状态密集的重型应用)。 拍板宏观架构模式(CQRS,洋葱架构,或沙漏模型)。 制定数据流向法则(统一Operation,Write Pipeline,读侧策略)。 将这些法则转化为绝对的契约(通过严格的CLAUDE.md或AGENTS.md,将其变成AI必须遵守的规则)。 一旦这套AI友好型架构的骨架搭建完成,接下来的开发过程将无比顺畅。你只需要用自然语言下达指令,AI就能在这个边界清晰的框架内,以十倍于人类的速度完美填补所有的业务逻辑。 拥抱AI,走向下一代编程 当我们重新审视前文所探讨的这一切:强制选用开源库,抽离可复用代码,职责隔离的四段式架构,收敛副作用的沙漏模型,以及读写分离的Pipeline流水线。熟悉软件工程的开发者可能会哑然失笑。 因为这些概念并非什么横空出世的新东西。它们身上,不过是Clean Architecture,CQRS,Event Sourcing以及 DDD的影子。 这似乎是一个巨大的悖论:在一个连代码都不需要人类手写的AI时代,我们为什么反而要退回到那些最经典,最复杂的软件工程里去寻找答案? 架构的受众变了:从人类到AI 过去几十年,我们推崇高内聚,低耦合,单一职责,核心诉求是为了降低人类大脑的认知负担。因为人类的短期记忆容量极小,一旦代码开始结构不清,人类就会在维护时迷失方向。 而现在,很多人误以为AI的记忆力无穷大,可以肆无忌惮地把所有逻辑塞给它。但残酷的工程实践告诉我们:LLM的Context Window和Attention机制,与人类的短期记忆极其相似。当AI看到几千行逻辑,UI和状态混杂的代码时,它也会产生幻觉。 所以,经典的架构模式在今天非但没有过时,反而迎来了它们的第二春。只不过,架构的受众从人类变成了AI。 架构越清晰,边界越明确,单一职责执行得越彻底,每次喂给AI的Context就越小,越纯净。AI生成代码的良品率,与系统架构的严谨度呈绝对的正相关。 在这个时代,依然抱有用useState随手一把梭心态的开发者,很快就会积累起无数的技术债。当系统稍微复杂一点,AI就会在混乱的状态依赖中反复报错,最终逼得你不得不回退到手动逐行Debug。 Vibe Coding绝不是让开发变得更随意,而是要求开发变得更严谨,更具全局观。 我们正在从代码的搬运工,全面转型为AI系统的产品架构师。我们的核心竞争力不再是熟练拼写各种API,也不再是能闭着眼睛写出一个排序算法,而是: 拥有极强的技术选型直觉,知道哪些部分应该交给成熟的开源生态,哪些部分必须自研。 具备控制系统熵增的能力,能够通过定义基础规范隔绝AI可能造成的复杂度。 掌握数据流向的宏观决断权,为庞杂的业务流转制定出AI必须绝对服从的规则。 定义世界,而非建设世界 AI时代的编程,本质上是控制权的交接。 我们把建设世界的苦力活完全交给了不知疲倦的机器。但作为交换,我们必须牢牢把握住定义世界的权力。 不要因为AI写代码的速度太快,就放弃了对架构的深度思考。 只有你划定了清晰的规则,AI才能在这条路上把速度飙到极限,而不用担心车毁人亡。 这就是我们在Vibe Coding时代,必须重新学习软件工程的全部意义。
配图 (可多选)
选择新图片文件或拖拽到此处
标签
更新文章
删除文章