唯实用主义

Joel 的 Blog 是个很有意思的关于软件开发的网站。里面有不少睿智的看法,比如『抽象泄漏』。但是有时候 Joel 的实用主义实在有些过度。只要两个方法都能解决同一个问题,就对它们进行无限制的无差别化,这就失去了从更高层次分辨优劣的能力。比如这篇 2003 年的《Biculturalism》,试图和 Eric Raymond 的《Art of UNIX Programming》唱唱反调。

试图和《Art of UNIX Programming》唱反调的 Blog 不止这一篇,比较新的还有这篇微软雇员写的。我觉得,以一篇 Blog 的篇幅想挑战一本书的观点,前者天然的处于下风,除非能一针见血的指出后者根基上的肤浅。可惜,Joel 的 Blog 只是说 Raymond 的观点稍稍过于执着;微软雇员的那篇则是在自设了很多假定的前提下玩逻辑游戏。如果你只是想说对手的观点稍稍有些过激(而不是全然推翻),或者想玩复杂的逻辑游戏,在篇幅和对手差一个数量级的情况下大多是自取其辱 —— 你很难有比对手更细致的分析,也很难把一个逻辑推导所需的前提假设的历史根源阐述的比对手更清楚。

回到 Joel 的这篇《Biculturalism》,开篇头一句『By now, Windows and Unix are functionally more similar than different』。看到这句话,非但没有感到 Windows 和 UNIX 之间的分歧有越来越小的迹象,我脑海里首先想到的就是kernel mode 下的 Windows GDI [1] —— 今天主流操作系统里唯一放在 kernel mode 里的窗口管理和图形界面系统,还有和 GDI 紧紧绑定的 window-based toolkit [2]。也许细心的读者会提醒,人家 Joel 说的是 functionally,你说的差异是 architectural。那么,架构上的差异是否完全对功能透明呢?我看 Joel 自己也不完全这样认为(比如『抽象泄漏』)。就像 Apache Web Server 在 Linux 上缺省采用多进程,在 Windows 上采用多线程 —— 架构上的差异导致的性能差别也会让功能的可用性发生质的改变。

Joel 说,UNIX 的文化在于崇尚为程序员提供便利,Windows 的文化在于崇尚为用户提供便利,我们最终是为用户而不是其它程序员提供产品。说这番话的时候 Joel 一定忽略了 Raymond 书上的引用的 Ken Thompson 的这一句话:

This is a consequence rather than a goal. I abhor a system designed for the “user”, if that word is a coded pejorative meaning “stupid and unsophisticated”.

问题在于,忽略了架构上的简洁的系统,是否还能可以提供完全相同的功能?比如我们提到过的,Windows 把 Toolkit(按钮、下拉框、文本框 ⋯⋯)放到窗口管理的 GDI 架构中,每一个控件都是一个窗口,其中还夹杂了直接访问硬件显存的 Direct Draw 窗口;而 UNIX 的窗口管理器一般采用 Toolkit-Agnostic 方式,窗口管理器只知道窗口的内容是一组二维像素,其中的 Toolkit 完全由应用程序空间的代码绘制。『实用主义者』会说,哪个用户会关心这些?不过,用户总是有设计者原本意想不到的应用场景。比如,今天的应用软件很多时候都加入了平滑动画功能 —— 当窗口的内容改变的时候,软件会显示一系列的中间状态。像图片旋转 90 度这样的操作,往往会短暂的显示中间的旋转状态。通常在旋转的过渡状态矩形图片的角会超出显示区域(因为我们都知道矩形的对角线比边长)。在一个 Toolkit-Agnostic 的窗口管理方式里,因为图片不过是一个像素组,超出的部分会被自动 clip。而在每个控件都是独立窗口的系统中,像 Direct Draw 这样的浮动窗口的显示在这种情况下是很难不显示出丑陋的一面的。如果这个例子只是个美观问题,那么用户还有更为严肃的应用场景。现在使用 VNC 一类的远程控制软件的用户很多。VNC 这类软件在 Linux 和 Mac OS X 上很少出问题。因为 VNC 对于传输基于像素的 Toolkit-Agnostic 方式的显示处理方式单一。而在 Windows 上,VNC 程序遇到不同类型的控件就会有很多问题 [3]。

所以,当 Joel 声称 Windows 和 UNIX 在功能上趋同,而且 Windows 更注重最终用户的时候,他既忘记了自己提出的『抽象泄漏』理论,又忘记了用户总会用意想不到的方式来使用你的软件(stupid and unsophisticated)。这也是唯实用主义在嘲笑别人热衷于设计的内部简洁的时候总是犯的两个错误。

脚注

  1. 关于 GDI 处于 kernel mode 这个问题,按照一般的思路人们会归于旧的 PC 硬件的性能遗留的历史问题。有趣的是,事实正好相反。在 NT 4.0 之前 GDI 是在 user mode 的。
  2. Window-based Toolkit,即每个控件是一个独立的窗口。这样的设计下,窗口管理器必然介入控件的层次关系的管理和消息的分派。与之对应的是 Toolkit-Agnostic 窗口管理,即窗口管理程序不了解控件是如何存在的。整个窗口内容是一个像素矩形区,比如在 Mac OS X 里,控件完全由 Cocoa 或者 Carbon 库生成和负责 sub-window 级别的消息分派(这两个库连接到应用程序的进程空间)。UNIX 的 X 是提供一定程度的 window-based toolkit,不过现代的 Linux/UNIX 程序一般建立在 GTK/QT Toolkit 之上,绕过了 X 本身的控件,此时 X 也作为一个 Toolkit-Agnostic 管理器存在。
  3. 当然这不是 VNC 协议本身的问题,而是具体 VNC 程序实现的问题。不过关键在于 Windows 的架构让 VNC 程序的实现和测试比 Toolkit-Agnostic 下的 VNC 程序更复杂也更费时费力。

发表评论

Fill in your details below or click an icon to log in:

WordPress.com 徽标

您正在使用您的 WordPress.com 账号评论。 注销 /  更改 )

Facebook photo

您正在使用您的 Facebook 账号评论。 注销 /  更改 )

Connecting to %s


%d 博主赞过: