AI Coding 时代,依赖越少的软件越成功
一个让我开始想这件事的下午
Section titled “一个让我开始想这件事的下午”前段时间我用 Claude Code 一天做了一个 aistack 工程——把 Ollama、ASR、TTS 整合成一个本地代理层,还顺手做了几个模型的性能优化。这件事如果放在 2023 年,大概是一个三人小团队两个月的活。
不是因为代码量真有这么大的差距,而是当年的时间几乎全花在”非编码工作”上:读 Whisper 的 CTranslate2 后端怎么调、查 Ollama 的 keep_alive 怎么传、翻 GitHub issue 找别人踩过的坑、对着 piper-tts 的 README 试参数、调试某个量化模型为什么吐空 token——这些事每件十几分钟,叠起来就是几周。
AI Coding 真正帮我省下的不是写代码的时间,是读文档、查 API、踩坑、对接库的那部分时间。
但当我看着这个一天做出来的工程时,意识到一件比”我快了”更重要的事——
它的依赖列表只有几行。
没有 LangChain、没有任何 AI Agent 框架、没有什么”集成 SDK”。Ollama 的 API、ASR 引擎、TTS 引擎,都是直接对接 HTTP 或 stdio。代理层是我自己写的,一千多行 Python,没有什么”中间件”夹在中间。
这种工程形态在 2020 年会被嘲笑”不专业”。在 2026 年,它是真正的”现代”。
而当我把这个观察推开来想——它不只是关于我的这个小工程,它指向了一个正在发生但还没被命名的趋势:
软件好坏的评估标准正在被改写。AI Coding 时代,依赖越少的软件越成功。
为什么这件事在 AI Coding 之前不成立
Section titled “为什么这件事在 AI Coding 之前不成立”先讲清楚为什么”依赖少”在过去不是评估标准。
过去二十年,软件好坏的主流评估标准是这些:功能多不多、性能跑分高不高、文档全不全、社区活跃不活跃、生态丰不丰富、用了多少现代技术。
这些标准在那个时代是合理的——因为那个时代”自己写”的成本极高,所以”借力”是必然。一个项目用了 50 个开源依赖、集成了 10 个云服务、对接了 20 个 SDK,会被夸”做得真完善”。
但其实这种评价标准从一开始就有内在矛盾——依赖越多,软件越脆、越难维护、越容易腐烂、越难穿越时代。只是在”自己写成本高”的约束下,这些代价被压抑了,没人愿意正视。
这背后是一条简单的成本曲线:自己实现一个功能 = 100 单位成本,用现成轮子 = 5 单位成本。20 倍的差距下,“不用轮子”是非理性的,所以工程师文化必然演化成”先找库,找不到再自己写”。npm / Maven / pip 这些包管理器的爆炸式繁荣,就是这条曲线的产物。
AI Coding 来了之后,这条曲线被压平了。
自己实现 = 8 单位成本,用现成轮子 = 5 单位成本。差距从 20 倍压到 1.6 倍。
这点差距已经无法补偿用别人轮子的隐性成本——学这个轮子的领域概念、看它的文档(还经常过时)、适应它的设计哲学、处理它的依赖传递、跟它的版本演化赛跑、等它修 bug 或者绕开它、维护”我们项目的依赖列表”这件事本身。
这些隐性成本以前被”造轮子要 100 单位”压着,看不见。现在自己写只要 8 单位,这些成本立刻变成水面之上的明显负担。
很多轮子从”省时间的工具”变成了”消耗时间的负担”——这个转折点很多人还没意识到。
那个被遗忘的指标
Section titled “那个被遗忘的指标”现在让我们正面回答:为什么”依赖数量”会成为新时代评估软件的核心指标?
因为依赖数量,决定了软件最重要的几项工程属性的上限。
第一,依赖数量决定可理解性的上限。一个工程师能完整理解的代码量是有上限的,大概几十万行是单人极限。如果你的软件本身只有几千行,但依赖了 200 个开源库总计几千万行代码——理论上没有任何一个人能完整理解这个软件。所谓”理解”只是”理解我自己写的那薄薄一层”。这种”理解的虚假性”在简单场景下不成问题,在出现复杂 bug 或性能问题时立刻暴露。
第二,依赖数量决定可演化性。每个依赖都有自己的演化节奏——它什么时候发新版本、什么时候改 API、什么时候不再维护——你都不能控制。依赖越多,你的软件就越被这些不可控的外部因素拖着走。一个有 200 个依赖的项目,每年要做的”为了跟上依赖更新”的工作量是巨大的,而且这些工作纯粹是消耗,不创造任何业务价值。
第三,依赖数量决定攻击面。每一个依赖都是一个潜在的安全漏洞入口。npm 的 left-pad 事件、Log4j 的灾难、xz utils 后门事件——这些都是依赖被毒化的真实案例。依赖越多,被供应链攻击的概率越大。
第四,依赖数量决定可分发性。一个零依赖的软件可以一个二进制文件扔过去就跑;一个有 500 个依赖的 Node.js 项目要先 npm install 半小时、还可能因为某个包从 registry 消失而装不上。自包含程度跟依赖数量成反比——而自包含程度直接决定软件能不能被普通用户使用、能不能在受限环境运行、能不能长期保存。
第五,依赖数量决定生命周期。SQLite 三十年还能跑——因为它没什么外部依赖,跑得起 C 编译器就跑得起它。一个 2010 年的 Rails 项目今天大概率跑不起来——因为它依赖的几百个 gem 中只要有几个没维护或不兼容新 Ruby 就完蛋。依赖数量本质上是软件的”保质期”——依赖越多,保质期越短。
可理解性、可演化性、安全性、可分发性、生命周期——一个软件最重要的几项工程属性,全都跟它的依赖数量负相关。这不是巧合,是数学规律。
而且这个指标特别难造假。性能跑分可以为 benchmark 做特殊优化、社区活跃度可以买 star、用户量可以烧钱补贴——但你的依赖列表是公开的、可数的、不能伪造的。一个软件号称”轻量”,打开它的 package.json / requirements.txt / Cargo.toml 一看依赖列表,立刻原形毕露。
这种透明度让”依赖数量”成为工程质量最可靠的客观证据。
那些穿越时代活下来的软件
Section titled “那些穿越时代活下来的软件”这条规律最有说服力的证据,是看哪些软件真正穿越了时代活下来。
桌面 toC 领域穿越了三十年还在的那一批,几乎清一色是纯 C core 的小项目:
- SQLite——可能是世界上部署最广的软件,单文件纯 C,飞机、手机、浏览器、操作系统里到处都是
- FFmpeg——所有人转码、剪辑、流媒体的底层,纯 C
- curl——所有人发 HTTP 请求的事实标准,纯 C
- Redis——缓存层的标准答案,单进程纯 C
- Nginx——Web 服务器领域的胜利者,纯 C
- Vim——编辑器活了三十多年,纯 C
- Lua——嵌入式脚本之王,从游戏引擎到 Redis,纯 C
- VLC / mpv——多媒体播放标准,C/C++ core
这不是巧合,这是工业筛选的结果。三十年的工程演化是一个极其残酷的物竞天择过程,什么能活下来不是因为它”被推广得好”,而是因为它在每一个具体的工程指标上都没有短板。
它们的共同特征是什么?
依赖列表极短。SQLite 的依赖基本只有 libc。FFmpeg 是模块化的,可以编译成几乎零外部依赖的版本。curl 主体也是 libc + 少数可选库。Lua 解释器和标准库不到两万行代码,零外部依赖。
自包含、可被任何环境消费。一个 SQLite 库可以嵌入 Python、Java、Go、Rust、Swift 任何语言;一个 FFmpeg 二进制扔到任何 OS 上都能跑;一个 curl 命令在 1995 年的服务器和 2026 年的边缘设备上行为一致。
整个 codebase 可以被一个人读完。SQLite 主体代码大概十几万行;Redis 早期就几万行;这些项目的整个 codebase 是可以被一个人读完的——这意味着项目永远不会陷入”无人理解”的状态。
与操作系统无关、与硬件演化无关。它们只跟 POSIX 的最小子集说话,不依赖任何特定 OS 的 GUI/事件/IPC 模型。结果就是 OS 怎么演化、硬件怎么更替,它们都能继续跑。
而那些没活下来的桌面软件,回头看会发现一个共同模式:它们的 core 都被某个特定时代的”现代框架”绑定了。
90 年代用 MFC 的程序——绑死在 Windows + C++/MFC 上,没法跨平台、没法持续维护。2000 年代的 Java Swing 桌面程序——绑死在 JVM 上,启动慢、内存占用大。各种 .NET 桌面应用——绑死在 Windows 生态。Electron 重型应用——core 跟 UI 揉在一起,几百 MB 起步。
这些都不是因为”团队不努力”,而是它们选了错误的 core 载体——把核心逻辑写在了一个有保质期的框架/运行时里,框架过气了,产品也跟着过气。而 SQLite / FFmpeg / curl 的核心逻辑写在最朴素、最稳定的 C 标准之上,所以它们没有保质期。
长寿软件的秘诀不是”用最先进的技术”,而是”用最不会变的技术”。先进会过时,只有”不会变”才能穿越时代。 而”不会变”的物理表达,就是依赖数量极少、且依赖的都是经过时间考验的稳定基础。
看依赖列表,识工程品位
Section titled “看依赖列表,识工程品位”这个新评估标准还有一层我特别喜欢的特性——它会暴露软件作者的工程哲学。
打开一个软件的依赖文件——package.json 也好、requirements.txt 也好、Cargo.toml 也好——你能看到的远不止是”用了哪些库”。你能看到这个作者怎么思考工程、怎么权衡取舍、怎么对待长期维护这件事。
- 一个 Web 框架号称”全栈解决方案”,依赖了 300 个包——它的作者是”框架式思维”,相信通过堆叠抽象层来管理复杂性
- 一个数据库引擎号称”功能完整”,但只依赖标准 C 库——它的作者是”内核式思维”,相信通过深度掌控来管理复杂性
- 一个 AI 应用号称”快速集成”,依赖了 LangChain + 50 个其他包——它的作者在借力,把所有不确定性外包给上游
- 一个 AI 应用直接对接 OpenAI HTTP API,依赖只有 stdlib + httpx——它的作者在自主,每一行代码都是自己能解释的
这些差异不只是技术选择,是不同工程哲学的外化。看依赖列表,就能看出软件背后的人是什么品位。
而且这种品位识别在招聘和合作中越来越重要。一个候选人简历上写着”精通 Spring Cloud、熟练使用 50+ 框架”——这在过去是优势,在新时代要打个问号。真正稀缺的能力不是”会用很多东西”,是”知道哪些东西不该用”。后者的判断力远比前者难培养,也远比前者值钱。
这件事的潜台词
Section titled “这件事的潜台词”这条规律之所以重要,是因为它跟其他几条工程规律是互相印证、互相强化的:
- 代码即文档、代码即设计——前提是代码是自己的、可读的、不被外部依赖打散的
- 自包含、与 OS 无关、与硬件无关——本质就是依赖数量趋近于零
- core + UI + CLI 朴素三件套——这种结构天然依赖少
- 互联网 toC 巨头都是从最底层造轮子——本质上就是把外部依赖替换为内部组件
- 该扔就扔扔得快——扔的就是冗余依赖
所有这些观察的统一表达,就是**“外部依赖越少越成功”**。这是一个把所有零散观察串起来的总指标。
它还能解释一些过去看起来”反常”的技术胜负:
- 为什么 SQLite 比 MongoDB 更受工程师尊重?SQLite 几乎零依赖
- 为什么 nginx 比 Apache 更受欢迎?nginx 依赖更少、更专注
- 为什么 Linux 比 GNU/Hurd 成功?Linux 内核非常自包含、设计聚焦
- 为什么 Go 在云原生时代赢了?Go 鼓励”少依赖”的工程文化、编译出来是单二进制
- 为什么 Tauri 在新一代桌面应用中取代 Electron?Tauri 的依赖比 Electron 小一个数量级
- 为什么 VSCode 取代 VS Studio?VSCode 的核心 Monaco editor 是薄的,扩展是按需加载的;VS Studio 是重型的,什么都内置
这些技术胜负的背后,依赖数量是一个高度准确的预测变量。
反过来,那些走向衰落的项目,几乎都跟”依赖膨胀”有关。Node.js 项目的 node_modules 黑洞已经成了行业笑话。Java 企业应用的 jar 地狱、Python 项目的版本冲突灾难、各种”用 50 个微服务搭一个简单系统”的过度工程——这些都是”依赖过多”的症状,它们曾经被当作”现代化、专业化”,AI Coding 时代回头看,会被认定为反面案例。
AI Coding 时代的工程文艺复兴
Section titled “AI Coding 时代的工程文艺复兴”更深一层——
AI Coding 不只是改变了”评估软件好坏的标准”,它在做一件更深远的事:它把过去只有顶尖工程师才能享有的工程美学,变成了普通工程师也能达到的标准。
过去这种”零依赖、自包含、core + UI + CLI”的工程美学,只属于极少数顶尖工程师能享有的奢侈品——D. Richard Hipp 写 SQLite、Fabrice Bellard 写 FFmpeg、Bram Moolenaar 写 Vim。普通工程师没这个能力,只能用别人的轮子,不得不接受依赖膨胀的代价。
AI Coding 把这个奢侈品变成了普通商品。任何认真的工程师,配合 AI,都能写出比 LangChain 更小、比 Spring 更轻、比 React 更直接的版本——专门服务于自己的需求,干净、自包含、可掌控。
一旦人人都能做到,市场标准自然就会以这个新水平来要求所有产品。
这是一次真正意义上的工程文艺复兴——它不是回到过去,是在新的技术能力(AI Coding)支撑下,重新拥抱过去那些被工业化压制的工程美德(自包含、简洁、独立、长寿)。70 年代 Unix 时代的”小工具组合 + 文本协议 + 单一职责”哲学,借着 AI Coding 重新回到主流。
我相信未来五到十年,软件工程的主流审美会发生肉眼可见的转变——“少即是多”会从少数派的口号变成行业共识。
一些行动建议
Section titled “一些行动建议”如果你认同这条新评估标准,有几件事可以从今天就开始做:
第一,打开你正在做的项目,数一下依赖数量。问自己:每一个依赖,是真的必须,还是当初为了图省事引入的?有多少依赖只是为了用其中很小一部分功能?这个练习会让你重新审视项目的真实结构。
第二,下次引入新依赖之前,问一下”我能不能自己实现一个最小版本”。在 AI Coding 之前,这个问题的答案通常是”不行,太贵”;现在这个答案越来越频繁是”可以,半天就能搞定”。每一次自己实现而不是引入依赖,都是在为项目的长期生命力投资。
第三,对老项目做一次”依赖审计”。把所有依赖列出来,分成三类:必须保留的、可以替换为更轻方案的、可以直接砍掉的。然后从最容易的开始砍,一周一个。三个月后回头看,你会惊讶于项目变得多干净。
第四,调整选型品位。下次评估一个工具或框架,先看它的依赖列表。一个号称”现代化、生态丰富”但依赖了几百个包的工具,跟一个”功能更基本但依赖只有几个”的工具——在新时代,后者往往是更好的选择。
第五,培养”反框架”的判断力。框架的承诺总是诱人的——“它帮你做好了一切”。但代价是你的代码被它的世界观塑形、你的命运被它的演化绑定。库是你调它,框架是它调你;调用关系反过来意味着你失去主导权。在能选库的时候不要选框架。
软件工程是一门会随技术能力变化而重新评估自身的手艺。
过去二十年,“自己写贵、用别人的便宜”这条成本曲线,决定了软件的主流形态——依赖膨胀、框架繁荣、生态拼装。这种形态在它的时代是合理的,但它的合理性建立在一个具体的成本结构之上。
AI Coding 改变了这个成本结构。当造轮子的成本趋近于零,“不重复造轮子”这条老规矩就要重新审视了。它没死,但适用范围在大幅收缩。
而能在新时代赢的软件,会是那些早早看出新规则、采用新评估标准的——依赖越少越成功。
不是因为依赖少看起来”清爽”,是因为依赖少在每一个真正重要的工程维度上——可理解性、可演化性、安全性、可分发性、生命周期——都更优秀。这是数学规律,不是审美偏好。
未来三五年,会有越来越多依赖少到让人困惑、简洁到让人怀疑、独立到让人不安的项目,一个接一个赢得市场。等大多数人意识到评估标准变了,先看到这个趋势的人已经做出了下一代的产品。
所以今天能做的事,就是开始用这把新标尺重新审视所有软件——包括别人的,更包括自己的。
少即是多。这一次,时代终于追上了这句话。