你的框架是可替换的。你的架构不可替换。

发布: (2026年2月7日 GMT+8 23:05)
6 分钟阅读
原文: Dev.to

Source: Dev.to

框架本质上是短暂的。
它们出现、获得关注、在讨论中占据主导地位数年,随后被取代或从根本上重新构建。这并不是前端开发的缺陷;而是工具、浏览器以及开发者期望快速创新的自然结果。

许多团队犯的错误不是选择了“错误”的框架,而是认为今天选定的框架明天仍会以同样的方式塑造他们的代码库。随时间应保持稳定的应用程序的业务逻辑:规则、验证、工作流以及代表真实需求的约束。不幸的是,在许多前端项目中,这两个关注点紧密交织在一起。

Source:

问题:框架耦合

在理论上,框架只是一种工具,业务规则在组件内部实现。起初,这种方式看起来很高效——所有东西都聚集在一起,认知负担低,进展迅速。然而,随着时间的推移,框架不再是可替换的细节,而是开始定义系统的核心工作方式。此时更换框架就不再是一次简单的 UI 调整,而是一次根本性的重写。

暴露出这种耦合的典型场景:

  • 迁移到新版本的框架
  • 引入第二套 UI(例如移动端或桌面端)
  • 在不同环境中复用逻辑
  • 以有意义的方式提升测试覆盖率

当业务逻辑与框架概念纠缠在一起时,提取业务逻辑就需要引入组件渲染、生命周期模拟以及大量的 mock。即使底层规则保持不变,细微的改动也会在 UI 层产生连锁反应。

指导原则:按变化速率分离

一种有用的架构原则是根据预期的变化速率来划分关注点:

  • 框架 变化迅速。
  • UI 范式 发展演变。

Guideline: UI 层负责协调,领域层负责决策。

  • UI 层 – 处理用户交互和呈现。它收集输入,调用应用逻辑,并渲染结果。它 不应 包含验证规则、业务决策或副作用。
  • 领域层 – 包含核心业务规则和工作流,独立于任何 UI 技术。

示例:UI 与领域代码

以 UI 为中心的实现(框架代码)

// UI component (framework code)
component CheckoutForm {
  state email = ""

  onSubmit() {
    if (!email.includes("@")) {
      showError("Invalid email")
      return
    }

    const response = http.post("/checkout", { email })

    if (response.ok) {
      navigate("/success")
    } else {
      showError("Checkout failed")
    }
  }

  render() { /* ... */ }
}

问题:

  • 验证和结账工作流被锁定在组件生命周期、框架状态管理以及 UI 级别的错误处理中。
  • 复用或测试该逻辑需要框架的存在。

重构后的分离(纯领域代码)

// Domain / application layer (plain code, no framework)
function validateEmail(email) {
  if (!email) return { error: "Email is required" }
  if (!email.includes("@")) return { error: "Invalid email" }
  return { ok: true }
}

async function submitCheckout(email, httpClient) {
  const validation = validateEmail(email)
  if (validation.error) return validation

  const response = await httpClient.post("/checkout", { email })
  if (!response.ok) return { error: "Checkout failed" }

  return { ok: true }
}
// UI component (framework code) using the domain layer
component CheckoutForm {
  state email = ""
  state error = null
  state loading = false

  async onSubmit() {
    loading = true
    error = null

    const result = await submitCheckout(email, http)

    loading = false

    if (result.error) {
      error = result.error
    } else {
      navigate("/success")
    }
  }

  render() { /* ... */ }
}

好处:

  • 领域函数可以从任何地方调用(UI、CLI、后台任务、测试)。
  • 它们可以在不渲染组件的情况下进行测试。
  • 即使 UI 框架更换,它们仍然可复用,使 UI 保持轻量且可替换。

为什么这超越可测试性的重要性

  • 风险降低: 当框架演进时,降低迁移风险和重构成本。
  • 持久性: 代码库拥有更长的可用寿命。
  • 清晰度: 业务行为集中在一个位置,独立于 UI 机制,从而提升整体代码质量。

框架升级常被认为是渐进式的,但许多框架会显著改变其思维模型。因此,架构更多是关于风险管理,而非仅仅追求优雅。

实践反思

如果在五年后你被迫更换前端框架,请自问:

  1. 系统的哪些部分可以保持不变?
  2. 哪些部分需要从头重写?

如果答案是“几乎所有东西都需要重写”,那么该框架已经成为你的架构——这值得重新考虑。

0 浏览
Back to Blog

相关文章

阅读更多 »

业务逻辑被遗忘时的风险

封面图片:业务逻辑被遗忘时的风险 https://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%...