C++:进程开销和内部复杂度

C++ 为什么会被设计成现在这个样子,我一直认为和 Bjarne Stroustrup 的个人背景有很大关系。按照 Stroustrup 自己在 《The Design and Evolution of C++》里的描述,设计 C++ 的动机来自于他完成博士论文的时候编写一个模拟器缺乏合适的工具。从这段描述里,我冒昧地认为 Stroustrup 暴露了他早期的局限性,他意识到必须有更好的工具来管理系统的复杂性,但是眼光仅仅局限在源代码的层次。他的模拟器是一个单独的 monolith,在寻求更好设计时,Stroustrup 仅仅追求如何更好的管理这个 monolith 的内部结构,未曾考虑任何更高一级的方法——比如把 monolith 分割成相互协作的更小的模块——来提高系统的可维护性。

C++ 与进程开销

C++ 在 UNIX 上受到的欢迎程度最低,正是因为 UNIX  提供了更多的组织系统的方法,这些方法能够,而且经常是更好的代替源代码级别的方式。UNIX 不仅提供了进程和 IPC,让这些方式成为可能,而且还从一开始就不断寻求降低这些方法的开销,让它们相对于源码级的管理方式——也就是语言——更加有竞争力。所以,在 UNIX 上 C++ 没有获得它在其它一些操作系统中获得的那种主导地位。

在《The Art of UNIX Programming》的3.1.3节说的很清楚,“如果操作系统让创建进程的操作过于昂贵,或者让进程控制的操作过于困难或者过于死板,⋯⋯就会鼓励 (在一个较大的 monolithic 模块内部使用) 像 C++ 一类的源代码级别的内部分层结构,而不是 C 这样的 (在相互协作的小模块中) 相对平坦的内部结构。

我常说一句不太准确的玩笑话—— “C++ 就是微软捧起来的” 。其实也不是全无道理。作为在 PC 发展的黄金时代最广泛应用的操作系统,Windows 没有提供太多的系统级机制来管理应用软件的复杂度,开发者只能着眼于源代码级别的内部结构,寻求 C++ 之类的语言帮助。

C++ 的兴起和 PC 上 anti-UNIX 风格暂时的主导地位有很大关系。Stroustrup 的发明是对 UNIX 上管理系统复杂度的方式的一种不高明的重复。这种重复为那些由于历史原因或者因为经济原因 (比如过弱的硬件支持和操作系统支持) 没有普及 UNIX 文化的领域提供了一种似是而非的,拥有短期效益的替代品,因而受到了欢迎。

C++ 与内部复杂度

UNIX 文化鼓励通过进程和进程协作来降低单独模块的内部复杂度,而不赞成用 C++ 的方式来 “管理” 内部复杂度。事实上,UNIX 文化认为 C++ 的方式在鼓励过度的内部设计而不是有效的对其进行整体管理。

另一方面,C++ 不光忽略了在单个 monolith 的层次之上的管理方式,还低估了现有手段在单个 monolith 中应对复杂度的能力。做出这种错误判断的不只 Stroustrup 一人,在 90 年代操作系统领域兴盛一时的对 micro-kernel 的研究中,研究者和很多业界开发者都认为操作系统内核的复杂度已经到了必需舍弃 monolithic 式的内核设计,由 micro-kernel 加 user-space 进程实现的服务来替代。Linux kernel 的出现及时证明,用 C 这样的技术也足以很好的管理单个 monolithic kernel 的复杂度。Linux kernel 不光和很多 monolithic 内核同样稳定,还在性能和设计复杂度上拥有天然的优势。(比如,对于 Minix 的单线程文件系统的抱怨,其设计者反驳说该 feature 很好实现——但是始终没有真正实现,而对于 monolithic 内核来说,多线程文件系统几乎是自然而然的设计。)

今天,如果你把系统中某个组件的复杂度设计的比 Linux kernel 还高,那是一种罪过而不能被认为是必需使用 C++ 的理由。

结论

C++ 的兴起,在我看来很大程度上是不是一段普通的历史,而是反映了整个业界的一个错误。正如《The Art of UNIX Programming》所说,上世纪80年代,由于各个 UNIX 厂商的愚蠢,UNIX 文化曾经一度奄奄一息。而 UNIX 社区的开发者们又一再忽略兴起的 PC 市场 (而忘记了 UNIX 自己就是在 mainframe 的厂商忽视了 mini-computer 的情形下发展起来的)。在整个世界缺乏 UNIX 文化的情形下,出现了 C++ 这样畸形的尝试。

我承认世界并非完美。有些错误已经成为文化的一部分被保留下来。但是 UNIX 文化因为它强大的生命力终于逐渐回归。这显示出 C++ 不属于那类可以出于历史和文化原因而被永远保留的错误。这个错误至少应该不被扩大,并且可以被逐渐纠正。

3条回应 to “C++:进程开销和内部复杂度”

  1. zy Says:

    你总是说C++要不行了。你给个预测吧,什么时候如Photoshop或office这样的软件将不会用C++再开发。

    相比于一些人过于推崇OO,你又到另一个极端了。其实你们是同一种人,你们都是对方法论痴迷的人。

    而且,你很推崇Cocoa和Objective C,但它们的风格与Unix和C这样的平台和语言相隔太远了。Cocoa就是OO的,为了这,Apple还把Cobarn给废了。你好像有双重标准。

  2. sipoint Says:

    既然我能同时推崇风格相异的 Cocoa/Objective C 和 Unix,那我就不是对方法论痴迷,对吗?我反对过于推崇 OO,但是我从来不反对 OO 的一些元素,比如封装和简单的多态,而且我更是一贯认为 UI 还是 OO 处理起来最合适—— Apple 的 Cocoa 就是 UI Framework,并没有管其它的东西,这个和我对 OO 的态度是一致的。

    • fuzhou Says:

      一般地讲,俺倾向于不对C++的设计做评论。原因不是因为它设计优良,而是因为它只是符合了那个时代的需要:

      a) OO的设计模式

      这符合当时大面积兴起的UI程序的要求。相对于几乎是纯粹过程式UI的设计,包括Newt,nCurses和XWindow API,C++的设计能让程序员舒服很多;

      b) 低平台开销

      在大约15年前,任何“平台级”的改进在PC上都会被认为是过于重量级而不会被应用开发领域普遍采纳,无论是不是OO的。这里最好的例子有Java,或者更好一点,Common Lisp。

      关于东哥对Windows的评论俺是同意的。从俺的经验上看Windows的设计和组织更接近于一个乱糟糟的集市和大跃进的混合体:设计具体新功能的时候,每一个小组都能往里面随便加功能,于是乎就出现了大量的功能冲突和随之而来的special case。一个很好的例子是Roaming User Profile,Client Side Caching和 IE的cookie时间戳保存方式,都是在我手上有过bug纪录的。

      而在决定技术方向的时候,Windows更接近于大跃进。典型的表现是一夜之间所有的team开始言必称XX,所有的新一代工具都要用XX实现。远有当初的C++,近一点的有COM和C#,现在又有Powershell。问题是:这个工具是不是适合这个特定的领域?有没有更好的方法?也许有人会去考虑,但是这种意见最终不会成为主流。这里我能公开的例子有一个,就是Windows的输入法框架,TSF。如果有熟悉这个框架的朋友相信都会对MSDN中TSF帮助里大量出现的只含一两个方法的interface印象深刻,比如ITfClientId和ITfCompartment,为OO而OO的典型。另外还有一些例子,因为代码没有公开的原因只能不说了。

      所以从俺的角度上看,俺很难认为C++的流行是因为它设计完美——因为从MS的历史上看它的选择逻辑并不太像是严谨分析的典范,反倒更有一点乔太守乱点鸳鸯谱的感觉。同样地,俺很怀疑Objectactive-C成为Mac的首选是因为它的设计最好,但是俺对Mac确实知之甚少,实在无权评论。至于UNIX/Linux,考虑到已经有了Perl Python Tcl/Tk这样很好的高层抽象和底层的C配合,俺实在想不出还有什么理由引入一个yet another good tool到系统里,特别是在C++的一些模型,比如locale和IO和Unix并不统一的前提下。

      顺便也对志岩老哥诌一句:俺同意C++会慢慢没落,但没落不意味着一夜之间消失,而更倾向于表现为新的应用开发会逐步地避免直接使用C++,而使用更高一层的抽象,比如C#或者Python。所以Photoshop和Office不可能在某个版本突然宣布用别的什么东西重写,这和现在美国的COBOL程序员仍然可以赚钱是同一个道理。

发表评论

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

WordPress.com 徽标

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

Facebook photo

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

Connecting to %s


%d 博主赞过: