SQL 让我感到不舒服。

发布: (2026年1月1日 GMT+8 21:05)
6 min read
原文: Dev.to

抱歉,我需要您提供要翻译的具体文本内容。请在 Source 链接下面粘贴文章的正文(除代码块和 URL 之外的部分),我会按照要求将其翻译成简体中文并保留原有的格式。谢谢!

介绍

在我的实际(而非理论)理解中,object‑oriented programming 不仅仅是传统函数式范式的另一种选择,往往更像是更进一步的方式。我把它看作是带有状态管理的函数式编程。实际中,类的行为类似于具有某种固有记忆的函数,这种记忆在程序运行期间持续存在,从而能够构建更好的有状态抽象,以建模现实世界的逻辑和概念。

当我尝试 React 的 functional components 时,我本能地把网页想象成一棵树——父组件由更小的组件构成,根节点是最终要显示的组件。可复用的组件类似于 OOP 中的接口或抽象类等抽象。为了让这些组件有意义,它们必须持有数据,并且在数据变化时 UI 需要更新。此时,持有并响应数据的组件让人联想到类的“有状态抽象”解释。

这就是把 UI 视为 Object Tree 看起来很有道理的原因。传统的移动 UI 框架也强化了这一思想:Android 使用 Java/Kotlin,iOS 使用 Swift/Objective‑C,将 UI 建模为对象层次结构。那么,React 为什么抛弃这种模型,转而使用 functional components,几乎把状态管理全部交给框架,从而让开发者的显式控制大幅减少呢?

答案并不在于函数与对象的对立,而在于 imperative vs. declarative 编程。声明式 UI 描述在给定状态下界面应当 是什么,让框架负责 如何 实现。现代移动 UI 框架如 SwiftUI 和 Jetpack Compose 也遵循同样的思路。

UI 框架:命令式 vs. 声明式

传统 UI Kit(命令式)

class CounterViewController: UIViewController {

    var count = 0

    let label = UILabel()
    let button = UIButton(type: .system)

    override func viewDidLoad() {
        super.viewDidLoad()

        label.text = "Count: 0"
        button.setTitle("Increment", for: .normal)

        button.addTarget(self, action: #selector(increment), for: .touchUpInside)
    }

    @objc func increment() {
        count += 1
        label.text = "Count: \(count)"
    }
}

现代 SwiftUI(声明式)

struct CounterView: View {

    @State private var count = 0

    var body: some View {
        VStack {
            Text("Count: \(count)")
            Button("Increment") {
                count += 1
            }
        }
    }
}

React(声明式)

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        Increment
      </button>
    </div>
  );
}

SwiftUI 与 React 的相似之处

SwiftUIReact
@State var countconst [count, setCount] = useState(0)
count += 1setCount(count + 1)
bodyreturn (…)
View (struct)Function component
Recompute bodyRe‑render function

这些相似之处展示了两个框架如何让你声明 UI 输出,并让框架在状态变化时处理重新评估。

命令式 vs. 声明式 编程

  • Imperative UI:你一步一步描述如何构建和修改 UI(例如经典 UIKit、旧版 Android)。这提供了直接的控制,但往往会导致大量样板代码、复杂的状态管理以及随着应用增长而需要手动更新。
  • Declarative UI:你描述给定状态下 UI 应该是什么样子。框架会决定实现该状态所需的步骤,从而产生更简洁、可读性更高的代码,并能自动响应状态变化。

对声明式范式的个人不适

我对这种范式感到一定的不适,就像我对 SQL 的不安以及我更倾向于使用 PyTorch 而非 TensorFlow 一样。这里的权衡在于 显式控制实现简易性 之间。声明式抽象让代码更简洁、更优雅——TensorFlow 的 model.fit() 就是一个完美的例子——但它们也会掩盖代码何时以及多频繁运行。错误会与 状态转变 关联,而不是具体的代码行,从而使定位变得更困难。

声明式编程要求我们停止像工程师那样发出指令的思维方式,转而像设计师一样描述约束。作为软件初学者,我并不声称函数式组件或声明式编程本质上是坏的。它们显然有效,且可能更适合构建大规模系统。对许多开发者而言,这是一笔值得支付的代价。然而对我来说,这仍然是一个令人不舒服的权衡。我可以在声明式系统中工作并理解它们的价值,但仍然怀念失去的显式控制感。

Back to Blog

相关文章

阅读更多 »