OOP Versus Functional Decomposition.

在此之前,我们已经接触了三种各具特色的语言:ML,Racket 与 Ruby,这门课程选择它们作为示例语言是十分别具匠心的。ML - statically functional language, Racket - dynamically functional language, Ruby - dynamically OOP language.

在 Part B 中,我们以 ML 与 Racket 为例比较了 static typing 与 dynamic typing;在这一节中,我们将以 ML,Racket 与 Ruby 为例比较 functional programming 与 object-oriented programming。

The Basic Set-Up

Followed is the canonical example of a common programming pattern. Suppose we have:

  • Expressions for a small “language” such as for arithmetic.
  • Different variants of expression, such as integer values, negation and addition expressions.
  • Different operations over expressions, such as evaluating them, converting them to strings, or determining if they contain the constant zero in them.

对这个范式我们应该已经相当熟悉了;之前我们也分别用 ML 与 Racket 实现过这个算数小语言。该问题能被一个矩阵 (two-dimensional grid) 进行表示:其中的每一个格子代表某个 variant 与 operation 的组合。例:

variant/operation eval toString hasZero
Int
Add
Negate

No matter what programming language we use or how we approach solving this programming problem, we need to indicate what the proper behavior is for each entry in the grid.

Functional v.s. OOP Approach

Functional decomposition breaks programs into functions that performs some operation and object-oriented decomposition breaks programs down into classes that give behavior to some kind of data.

也就是说,对于上文中提到的矩阵,functional programming lays out the program by column — 其定义操纵不同类型数据的函数,按列实现程序。要素有 datatype, constructor 与 function。

而 object-oriented programming lays out the program by row — 其定义不同的类,类中包含与其他类的实例交互的方法,按行实现程序。要素有 class, subclass 与 abstract method。

因此,functional decomposition 又被称为 procedural decomposition (过程分解) - it breaks the problem down into procedures corresponding to each operation。相对的,OOP decomposition 被称为 data-oriented decomposition - it breaks the problem down into classes corresponding to each data variant.

至于哪种分解方式更好完全是一个见仁见智的问题:对于不同的问题模型,有时基于过程的分解更为自然,有时基于数据的分解更为自然。但本质上,这两种分解方式是对立而又统一的 (so exactly opposite that they are the same).