前端向架构突围系列 - 框架设计 [2 - 1]:面向对象编程的本质与未来

93 阅读4分钟

image.png 这篇文章是系列的第四篇,也是一个转折点

前三篇(4+1视图、UML、文档)讲的是**“术” (工具和方法),这一篇要开始讲“道”**(编程范式与思维本质)。

很多前端开发者对 OOP(面向对象编程)的感情很复杂:

  • 初级阶段:觉得 class 是 ES6 的语法糖,写 React 组件时用过,后来被 Hooks 取代了。
  • 中级阶段:觉得 OOP 是 Java 那套繁琐的东西,推崇函数式编程(FP),认为“继承是万恶之源”。
  • 架构阶段重新发现 OOP。发现大型系统的模块解耦、依赖注入(DI)、领域建模(DDD)依然离不开 OOP 的思想。

引言:被“嫌弃”的面向对象?

  • 现状:在 React Hooks 和 Vue Composition API 大行其道的今天,Class 似乎成了“过时”的代名词。很多前端认为 FP(函数式编程)才是未来。
  • image.png
  • 反转:然而,当你打开 NestJS、Angular,或者查看 VS Code 的源码,你会发现 OOP 依然统治着复杂系统的顶层架构
  • 核心论点OOP 的本质不是“类”和“继承”,而是“消息”与“多态”。 架构师需要跳出语法之争,看到其控制复杂度的本质。

1. 历史回眸:OOP 到底是为了解决什么问题?

  • 危机:60年代的“软件危机”。随着代码行数增加,过程式编程(Procedural Programming)的全局变量和 Spaghetti Code(面条代码)导致系统无法维护。

  • 起源

    • Simula 67:引入了“类”的概念,初衷是模拟现实世界(Simulation)。
    • Smalltalk (Alan Kay) :OOP 之父 Alan Kay 说过: "I made up the term 'object-oriented', and I can tell you I did not have C++ in mind."
    • 生物学隐喻:Alan Kay 的愿景是软件像生物细胞一样:每个细胞独立,通过**化学信号(消息)**通信,细胞内部怎么运作,外部完全不关心。
  • 架构启示:OOP 的初衷是封装(Encapsulation)和通信(Messaging) ,而不是复杂的继承树。

    image.png

2. 核心解构:架构师眼中的 OOP 三大支柱

这里要重新定义三大特性,去掉教科书式的废话。

  • 封装 (Encapsulation) -> 降低认知负荷

    • 不是简单的 private 变量。
    • 架构意义:隐藏实现细节,对外暴露稳定的接口(Interface)。让使用者“不需要知道内部发生了什么”。
  • 多态 (Polymorphism) -> 插件化架构的基石

    • 这是架构师最重要的工具。
    • 架构意义:依赖倒置原则(DIP)。上层模块不需要依赖下层模块的具体实现,只需要依赖接口。
    • 例子LogService 接口,可以有 ConsoleLoggerSentryLogger 两种实现。代码里写 logger.log(),具体跑哪个,运行时决定。
  • 继承 (Inheritance) -> 潘多拉魔盒

    • 批判:继承造成了强耦合。经典的“香蕉与猩猩”问题(想要香蕉,结果得到了拿着香蕉的猩猩和整个丛林)。
    • 修正组合优于继承 (Composition over Inheritance)

3. 前端架构的演变:从 OOP 到 FP,再到融合

  • 阶段一:模拟桌面软件 (ExtJS, Dojo)

    • 试图在浏览器里复刻 Java/C++ 的重型 OOP,失败。
  • 阶段二:React Class 组件时代

    • 用 OOP 封装 UI 组件,生命周期是典型的方法重写(Override)。
    • 痛点this 指针的混乱,逻辑复用困难(HOC, Render Props 的嵌套地狱)。
  • 阶段三:FP 的反攻 (Hooks, Composition API)

    • UI 本质是 f(state) = view。函数式更适合描述数据流转换。
  • 阶段四:现代架构的融合 (The Hybrid Era)

    • 微观层面 (Micro) :函数式(FP)。处理数据流、UI 渲染、无副作用的计算。
    • 宏观层面 (Macro) :面向对象(OOP)。处理服务依赖(DI)、模块划分、领域模型(DDD)。

4. 未来展望:面向对象的“无类”未来

  • Go 与 Rust 的启示:它们没有 classextends,但通过 structinterface/trait 实现了更纯粹的 OOP(封装+多态)。
  • Duck Typing (鸭子类型) :前端天然的动态性,让多态更容易实现。
  • 总结:未来的架构师不会拘泥于“我是写 OOP 还是 FP”,而是:用 OOP 划分边界,用 FP 填充逻辑。

图 1:OOP 的生物学隐喻(Alan Kay 的原意)

  • 对比:左边是过程式编程(操作数据的过程,混乱的网);右边是 OOP(独立的细胞,通过消息管道连接)。

    image.png

图 2:继承 vs 组合 (The Jungle Problem)

  • 痛点:继承树过深导致的脆弱性。

  • 解法:组合模式如何像乐高一样灵活。

    image.png


贴士

  1. 金句预埋

    • “OOP 被发明出来是为了解耦,但糟糕的继承让它变成了耦合的代名词。”
    • “架构师看 OOP,看到的不是类,而是接口边界。”
    • “React Hooks 不是对 OOP 的背叛,而是对‘组合优于继承’原则的极致践行。”
  2. Next Step (Actionable)

    • 建议尝试不用 class 关键字,仅用闭包或对象字面量实现一个“封装”和“多态”的小例子,体会 OOP 的精神而非语法。