CC's

Back

好吧,标题有点绝对。

这篇文章会从框架的开发者和使用者的角度上来讨论这个话题,到底什么算是框架,为什么某些框架惹人厌恶,然后自然地回归到我们的标题。

什么是框架#

随着时间的发展,很多新兴的 repo 都渐渐乐忠于称自己为「framework」。比如很多论文的开源代码会称 framework,很多人会将 torch 称为 framework,verl 也是如此

也许,把自己的代码叫做 framework 会显得比较高大上,或者工作量更大。这可以理解。尤其是科研论文写作总不能把自己叫做「library」,不过这种「框架」大都指方法设计层面上的概念。嗯嗯,我还比较认可。

在我看来,开源代码的库与框架,二者的核心区别在于

  • 库:我提供功能,你来调用我
  • 框架:你提供功能,我来调用你

也就是框架管理程序的生命周期,而库不用。这一关键性区别使得框架与库有着本质不同。

写框架很难#

正因为框架要管理程序的生命周期,所以它本质上是在替用户做决定。做一个好决定比提供一个好工具要难得多。

一套好用的框架其实解决的问题就是如何将一类系统的生命周期抽象成各种概念,并以各种概念简化系统的编写。

为了加深理解这句话,一个极其优秀的例子是 ruby on rails。虽然它是个 web 框架,离我的研究领域很远,但我认为它很好诠释了框架的精髓。

  • 统一 web 应用生命周期:接收请求、解析参数、连接数据库、渲染页面、返回响应,将 web 从命令式提升到了声明式,开发者负责制定规则而不是维护状态。例如将 web 中极为常见的权限控制、数据检查等操作剥离出主逻辑,简化主逻辑。再例如通过 Active Record 把数据库的一行记录抽象为一个 Ruby 对象,隐藏 SQL 何时初始化、上下文、何时执行,业务逻辑只要关注于本身
  • 约定优于配置:这是 RoR 的一个精髓。你学习我给出的概念,然后我们都可以省大量时间,流出空闲感受逻辑之美。例如它第一个将 MVC 完美适配 web 并推向主流,将业务逻辑、数据、视图分离为 Model (Active Record) - View (Template) - C (Controller)。再例如强制路径:将类名、方法名写成规范的形式,框架来自动生成、管理路由
  • DSL:领域特定语言。高度抽象化各个资源间的关联关系。

RoR 的成功在于它提供了一套完整且充分适配各种 web 应用的生命周期管理,将 web 应用中繁杂的细节隐藏在其提出的各种简洁、必要的概念里,从而降低了开发者的开发负担。开发者不再需要关心请求如何到达服务器、数据库连接池如何维护,而是仅需几行声明式代码就能完成复杂的功能。所以,大家喜欢 RoR,RoR 也深刻地影响了几乎所有后来的框架,直到今天。

框架在解决领域问题的同时也包含作者的个人兴趣。就像 RoR 作者给出的「约定」也可以称为使用者的「妥协」。它们不是唯一解,但你想用 RoR 就得妥协于这种实践上证明有效的限制。这种约定与妥协,是每个框架的精髓,也是每个框架自身的局限。

综上,一个「有用」的框架可能至少有以下特征

  • 对领域问题有良好、且可能充满「偏见」的认知,给出通用生命周期
  • 提出简洁的概念,隐藏冗杂的细节,更好地抽象问题,降低使用者负担
  • 框架提供的帮助性代码能够解决重复劳动
  • 不会解决所有问题,使用者将为之妥协

更多的案例#

事实上,我们可以看到更多优秀的框架都符合这些特征,比如

1. React:对「UI 渲染」生命周期的抽象#

在 React 之前,前端开发是命令式的:需要手动寻找 DOM、修改属性、添加/删除节点。

  • 生命周期抽象: UI 的生命周期抽象为 Mount、Update、Unmount三个阶段
  • 概念简化: 提出 Virtual DOM 和 State。开发者不再操作 DOM,只需要操作 State,框架自动根据生命周期帮你同步 UI
  • 妥协: 必须接受「单向数据流」和「不可变数据」。不能直接改 DOM,甚至不能直接改 this.state

2. Kubernetes (K8s):对「容器运维」生命周期的抽象#

K8s 实际上是一套管理分布式系统生命周期的「云框架」。

  • 生命周期抽象: 提出 Controller Pattern,期望状态 vs 实际状态。框架不断循环:观察 -> 对比 -> 调谐。
  • 概念简化: 提出 Pod、Deployment、Service。不再关心如何在服务器上运行二进制文件,只需要声明:「我需要 3 个运行着 nginx 的 Pod」
  • 妥协: 开发者和运维必须妥协于「声明式 API」和「容器化」的思想。不能随便登录一台机器改个文件就跑,因为 K8s 的生命周期管理会立刻发现「实际状态」偏离了「期望状态」,并把修改抹除。

没框架胜过坏框架#

框架意味着某种权力。当你决定接管用户的程序时,你其实也接管了他们的信任。

我希望每个尝试写框架的人都能意识到,他们其实是在与使用者交易,说服使用者来学习自己的一套。

开发者使用者
代价脑细胞开发自由、技术债务、学习成本
收益谁知道呢工作效率、行业理解、技术优势(稳定、性能、安全性)

我希望每个尝试用框架的人都意识到,一个不好的框架反而会增加他们的负担。

  • 不稳定生命周期:昨天还能跑起来的代码,今天就坏掉了,而且 log 复杂到看不懂,看懂了也不知道为什么。
  • 无法预知的功能:框架提供的功能没有统一的约定,是否能完成预期想法只能靠亲自阅读源码检查。
  • 难以拓展的边界:代码的运行流程无法满足需求,但边界由掌控在框架手中,想实现要同时改两边。
  • 迷失的问题认知:好框架挡住泥泞,也让你看清方向;坏框架是漆黑的迷宫,非但没有解决问题,还靠各种概念徒增查错难度。

这其实很好理解。如果有人声称「哇,我的框架奇迹般地解决了你做 LLM 研究时遇到的种种问题」,那作为一个理性的使用者,谁都会问一句「how?」以防止自己付出无用的成本,然后发现对方吞吞吐吐连个设计哲学都讲不出来,这事也就掰了。但如果对方说「用我的框架,你必须先按这个形式整理数据并且只能(也许是暂时)用 GRPO」,那这事还有的斟酌。

遗憾的是,精巧的框架的确是少数,大量的框架纯一坨。那些缺乏沉淀的框架、依赖私有技术栈的框架、不提供设计文档只有样例的框架,都是如此,不能带来什么,只能徒增烦恼。

写库,别轻易写框架#

洋洋洒洒写了一些,最终总归还是一句话:别轻易写框架。

  • 写框架的人要明白自己的责任。不负责的框架不会有人使用。
  • 写框架的人要明白他即将向众人展示他对问题 全面的、独到的、高雅的 理解。

所以在敲下第一个字母前,最好还是多问一句自己:这就是我的极限了吗?

如果还没能彻底理清,那不妨先退一步:写一个库吧。把它作为一个伟大项目的起点,在实践中去沉淀那些真正通用的范式。等时机成熟,框架自然会从中生长出来。

写 library,别写 framework
https://astro-pure.js.org/blog/write-lib-not-framework
Author Cheng Chen
Published at 2026年2月14日
Comment seems to stuck. Try to refresh?✨