我看JavaScript(四)——抽象与程序构造技术

上一文讲了JS的语言动态性,JS最为核心的特性之一;本文继续讲JS第二大核心特性——面向对象。语言动态性是语言现代性一方面,它是应网络或大型交互应用计算动态性而发展的;其实语言现代性更基础的一面是其「构造方式」,面向对象是语言在表达/构造/建造程序的方式和手段上改进。

JS是具备面向对象特性的,而面向对象技术传播多时已经为大部分开发者所熟悉,但认识不一定很准确。在解释JS具体的面向对象特性实现前,我们先复习一下何为“面向对象”,有关于这种风靡全球的编程技术的通用理论。先看看维基的定义:

Object-oriented programming (OOP) is a programming paradigm based on the concept of "objects", which may contain data, in the form of fields, often known as attributes; and code, in the form of procedures, often known as methods. A feature of objects is that an object's procedures can access and often modify the data fields of the object with which they are associated. In OOP, computer programs are designed by making them out of objects that interact with one another.

面向对象编程(OOP)是一种基于“对象”概念的编程范式,“对象”封装了计算数据(字段)和代码(方法),并且对象的代码常常访问其数据,这一点是对象的重要特性。在面向对象编程中,程序是由相互作用的对象组成的。

这个通识定义还是比较全面的,全面的指出了OO的1)属概念——编程范式;2)技术特征——将代码与相关数据封装在一起;和3)意义——用作构建复杂程序。一般的开发者都能基本读懂,并应用到实际上。但还是老问题,为什么OO是这样设计,就很少有人能道明白,要深入认识面向对象,做出优秀的(计算)对象设计,还需很多阐述。

程序构造理论缺乏

我们在前一文介绍语言动态性时已经初步总结了有关「程序」的理论,并且给出常识性的程序构件,其中也有「类对象」——类对象是面向对象技术的基础概念,但是没有细说有关类对象在构造复杂程序的细节。就像没有成熟的程序理论,似乎也没有成熟的关于「程序构造」的理论。

面向对象技术是一种演化多时的复杂事物,从它的属概念——编程范式[注]——我们大概了解到面向对象是一种程序构造技术,而据我目前的认识,市面上还没有比较公认成熟的「程序构造理论」,大部分的业已形成的工业标准都是从具体实践反复总结得到,包括面向对象这种构造技术。我们可以从两本理论性较强的计算机著述,了解到一些观点。

注:编程范式(programming paradigm)主要有两种:命令式和声明式

《Programming Language Pragmatics》

“抽象”的历史发展

第一本是《Programming Language Pragmatics》,我们引用一段(略意译):

In Chapter 3 we presented several stages in the development of data abstraction, with an emphasis on the scoping mechanisms that control the visibility of names. We began with global variables, whose lifetime spans program execution. We then added local variables, whose lifetime is limited to the execution of a single subroutine;

《Programming Language Pragmatics》 《Programming Language Pragmatics》[/caption]

我们已经介绍了有关“数据抽象”的几个发展阶段的状况,并且重点指出,抽象对符号(names)可见性控制(分全局和局部等),产生了作用域(scope)机制。也就是说,抽象符号具有作用域属性。

These were followed by modules, which allow a collection of subroutines to share a set of static variables; module types, which allow the programmer to instantiate multiple instances of a given abstraction, and classes, which allow the programmer to define families of related abstractions.

数据抽象的发展从函数传到了模块(modules)——一种由共享了固定数据变量的多个函数组成的程序单元/程序数据类型,产生了模块类型(module types),一种具有类似于函数抽象性的代码封装单位,开发者可以通过具体参数创建多个模块实例。类,也使用类似的抽象方式封装代码。

Classes build on the module-as-type approach by adding mechanisms for inheritance, which allows new abstractions to be defined as refinements or extensions to existing ones, and dynamic method binding, which allows a new version of an abstraction to display newly refined behavior, even when used in a context that expects an earlier version. An instance of a class is known as an object; languages and programming techniques based on classes are said to be object-oriented.

类在所谓“模块类型”(module-as-type)的基础之上增加了继承,和动态方法绑定(多态),两种新的抽象技术。(抽象的)类经具体实例化成「对象」,基于“类”的编程语言和技术称为具有面向对象特性。

以上片断概述了编程技术(程序构造)历史发展的一些关键点,不太好翻译,也不太好懂。概述中多次出现抽象(abstraction)这个词,而这个“抽象”就是推动程序构造技术发展的关键。

《Program Development in Java》

“抽象”有不同角度的意义,我们再看看第二本《Program Development in Java》(中文版《程序开发原理》)。

《Program Development in Java》

此书开篇点明「抽象操作」与「开发大程序」的关系:大程序使用传统方法既难开发亦难维护,必须引入经典“分而治之”的思想对程序进行分解,但是程序的随意分解具有害性,需要一些分层指导原则,让分解在相邻表达层级开展,这种指导原则依赖抽象的机制。

接着给出抽象的定义、两种抽象基本操作和三种抽象种类。

抽象的定义

抽象的过程是多对一映射的应用,允许我们忽略个体信息,从而将不同的事物当作相同的事物来对待。进行抽象主要将相关的属性和其他不相关的属性分开,以简化分析过程。

抽象的基本操作

  • 参数化抽象:用参数替换数据特征来进行抽象
  • 规格化抽象:将执行细节(HOWTO)抽象为用户所需求的行为结果(WHAT)

每个抽象种类(下面的过程抽象、数据抽象和迭代抽象)都会结合运用参数化抽象和规格化抽象;

《程序开发原理》

抽象种类

  • 过程抽象:我们能通过由编译语言定义的虚拟机来进行新的运算,过程抽象能够引入一些新的操作
  • 数据抽象:数据抽象(或数据类型)是由一组对象的集合以及一组以对象的行为表现为特征的操作组成;数据抽象能引入新的数据对象类型
  • 迭代抽象:略

此书的作者是个女士,叫巴巴拉(Barbara Liskov),神奇女性,拿过图奖,拥有了不起的抽象思维大脑。可是,我以为她对“抽象”的总结还不够抽象,问题主要有:

  • 第一,对“抽象”的定义不够精确,抽象高度不够,导致第二个问题;
  • 第二,对(两种)抽象基本操作本质掌握不够透彻;
  • 第三,抽象种类分类归结有不足,例如迭代抽象其实是过程抽象的一种(特殊的),数据抽象不仅仅只有数据,还有过程抽象,名字就定的不准确。“数据抽象”其实是多个过程抽象的组合。

Barbara Liskov

其实程序员每天都和抽象打交道,因为任何一个符号,无论是数据变量、函数方法,还是对象实例,都是抽象的结果。不同的人理解“抽象”有不同角度和意义,就像第一本书,一种从语言特性发展的角度,自下而上对“抽象”作为的将通用的计算操作(结果)提纯,不断增加抽象表达的抽象度,制作高复用性的程序构件。而第二本,则是从工程分解的角度,从自上而下定性“抽象”给大程序分而治之提供粒度参考。

裸男
Nakeman.cn 2023 Build by Gatsby and Tailwind, Deploy on Netlify.