Skip to main content

One post tagged with "ProgrammingParadigm"

View All Tags

在软件工程的演化史上,我们似乎经历了一个巨大的钟摆运动。

从 C 语言的自由狂放,到 Java/C++ 面向对象(OOP)的森严壁垒,再到如今 Rust 和 Go 的崛起。很多人认为这是一种“倒退”,因为它丢弃了继承,丢弃了复杂的类。

但实际上,这是一种螺旋上升的综合(Synthesis)

现代编程范式并非简单的“去 OOP 化”,而是站在 C 与 OOP 的中间,利用强大的类型系统作为粘合剂,达成了一种更高级的哲学境界:该聚合的聚合,该分离的分离。


第一阶段:C 语言的“完全分离” (The Thesis)

哲学:数据就是数据,代码就是代码。

在 C 语言的时代,世界是平铺直叙的。

  • 分离struct 定义内存布局,函数定义逻辑。两者在语法上没有必然联系。
  • 自由:你可以写一个函数去操作任何符合内存布局的数据。
  • 代价:这种分离过于彻底,导致了“内聚性”的缺失。数据缺乏保护,逻辑散落四处,全靠程序员的自律来维持秩序。

第二阶段:OOP 的“强行聚合” (The Antithesis)

哲学:世界是由对象组成的,数据必须和行为绑定。

为了解决 C 的混乱,OOP 走向了另一个极端。

  • 聚合:OOP 认为数据(属性)和行为(方法)必须死锁在一个 Class 容器里。
  • 约束:通过继承(Inheritance)来复用代码,通过 private 来保护数据。
  • 代价:这种聚合过于僵硬。为了复用一个简单的功能,你不得不继承庞大的父类(“香蕉与大猩猩问题”)。业务逻辑被层层叠叠的类结构锁死,修改变得极其困难。

第三阶段:现代范式 —— 中庸之道 (The Synthesis)

Rust、Go 等现代语言的出现,标志着我们终于在“分离”与“聚合”之间找到了平衡点。它们的设计哲学可以概括为:物理上分离,逻辑上聚合,类型上约束。

1. 该聚合的聚合:回归 Struct 与 模块化

我们不再需要庞大的 Class,但我们依然需要高内聚(High Cohesion)

  • 数据聚合:我们沿用了 C 语言的 struct,因为它在内存中是最紧凑、最高效的表达方式。
  • 封装聚合:我们没有退回到 C 的“裸奔”。通过现代语言的模块系统(Module System)(如 Rust 的 pub(crate),Go 的首字母大小写),我们将相关的数据和逻辑在模块/包的层面上聚合。
  • 以前是“类封装”,现在是“模块封装”。范围更宽,更灵活。

2. 该分离的分离:Trait 与 Interface

我们承认,**行为(Behavior)**往往是跨越数据类型的。

  • 行为分离:不管是 Duck 还是 Car,只要能 Run,就是可行的。现代语言将行为剥离为 Trait(特质)或 Interface(接口)。
  • 去耦合:逻辑不再硬编码在继承树里。行为变成了可以随意插拔的“插件”。

3. 关键变量:强大的类型系统 (The Type System)

这是区分“现代语言”与“C 语言”的核心区别。如果说 C 靠自律,OOP 靠类层级,那么现代语言靠的是编译器与类型系统

它在“分离”与“聚合”之间架起了一座安全的桥梁:

  • 代数数据类型 (ADT) / 枚举 (Enum): Rust 的 Enum 比 OOP 的多态更精准。它允许你定义“要么是 A,要么是 B”的数据结构(Sum Type),配合模式匹配(Pattern Matching),你可以在不使用继承的情况下,优雅地处理多种状态。
  • 泛型与约束 (Generics with Bounds)fn process<T: Speakable>(item: T) 这句话翻译过来就是:“我不关心 item 是什么数据结构(分离),但我要求它必须具备说话的能力(聚合约束)。”

案例对比:思维的跃迁

让我们看一个简单的例子:处理 HTTP 请求

  • C 语言思路:定义一个 struct Request,写一堆独立的函数 parse_request, handle_request。如果处理错了类型,运行时崩溃。
  • OOP 思路:定义 AbstractRequest 基类,派生 GetRequest, PostRequest。逻辑分散在继承树里,难以直观看到全貌。
  • 现代思路 (Rust)
  1. 聚合数据:用 struct 定义请求体。
  2. 类型约束:用 enum Method { GET, POST } 穷举所有可能性(编译器保证你不会漏掉任何一种情况)。
  3. 分离行为:定义 Handler trait。
  4. 组合:通过 impl Handler for Request 将它们联系起来。

结语

现代编程范式之所以迷人,是因为它不再执着于“万物皆对象”的教条,也不再容忍“指针满天飞”的混乱。

它汲取了 C 语言Struct的高效与直观,吸收了 OOP 封装的思想,最后引入了数学般严谨的类型系统

这就是**“该聚合的聚合,该分离的分离”**:

  • 让数据在内存中保持紧凑(聚合)。
  • 让行为在逻辑上保持解耦(分离)。
  • 让编译器在构建时保驾护航(类型系统)。

这也许才是软件工程成熟的标志。

鱼雪