# 二十七、程序设计界的LordPalmerston 曾经一度如果读过Peter Norton的一本书,就能完全了解在IBM-PC上写程序所需 的全部知识。在过去20年间,全世界的程序员很努力地在IBM-PC上建立层层的抽 象机制,让程序更容易撰写而且功能更强大。 不过抽象渗漏法则表示,即使他们建立了这些理应让程序更易设计的抽象机制, 做个伟大的程序员所需的各种知识还是一直在增加。 要真正地精通某个程序设计领域需要好几年的工夫。当然也有很多出色的青少年 学了一星期Delphi,再学一星期Python然后再学一个星期的Perl,就自认已经精 通了。不过他们根本不知道自己差得有多远。 我打从ASP和VBScript刚出来就在用了。VBScr i pt是世界上最微不足道的程序语 言,而ASP程序设计大概只要上五堂课会了,而且其中只有两堂是会经常用到的。 可是直到现在,我才感觉自已知道架构一个ASP/VBScript应用程序的最佳作法, 我才终于觉得自己知道数据库存取程序最适当的位置,用ADO取得recordset的 最佳作法,分离HTML和程序代码的最佳方式等等。另外我也终于会用正规表示式, 不再每次都重写一次字串操作函数。另外我上星期才学会如何取得不在内存中 的COM对象,这样就就可以不需整个web服务器重开就能重新编译。 Fog Creek太小了养不起专家,所以当我要为FogBUGZ(我们用ASP/VBScript制作 的产品)写一个真正好的安装程序时,我得拿出数年C++/MFC和Windows API的经 验,再用我还不错的Corel PhotoPaint技巧做出放在精灵角落的图片。另外为了 让FogBUGZ能无误地使用Unicode,我还得用C++和ATL写一个小小的ActiveX组件, 这里头有着数年的C++和COM经验,还有当初实作CityDesk时学了一周左右的字符 编码知识。 所以当我们遇到某个只有NT 4.0才发生的怪问题时,我只花了三分钟就解决了, 因为我知道如何使用VMWa「e,而且我有一套用VMWa「e灌的干净NT4.0机器,另外 我也知道如何用Visual C++做远程除错,还知道可以由EAX缓存器知道函数的回 传值。完全没接触过这些东西的人要抓同一个问题,恐怕得花一个小时或更多的 时间,不过我已经知道了很多很多「东西」,那些基本上是从1982年拿到我第 一台IBM-PC和那本Norton书时就开始学的东西。 有漏洞的抽象表示我们面对一个直线上升的学习曲线:你可以用一星期学到每天 工作所需知识的90%。不过其他10%可能得要好几年才能补齐。有些人会说:「不 管你要我做什么,我都可以拿本书来就学会了。」真正有经验的程序员超越这种 人的地方就在这里。如果你正在建立一个团队,当然可以找一堆经验较少的程 序员用抽象工具制作出一大堆程序代码,不过如果少了经验老到的人去做真正困 难的事情,这个团队是做不起来的。 程序设计有很多不同的世界,每个世界都需要大量的知识才能真正的精通。以下 是我个人最熟的三个领域: 1. MFC/C++/Windows 2. VBScript/ASP 3. Visual Basic 基本上这全部都可以称作Windows程序设计。没错,我也写过Unix或Java的程序, 不过很少就是了。我对Windows程序设计的专精不光是了解基本技术,也知道整 个支持的整体结构。我敢宣称对Windows程序设计很在行,是因为我也会COM、ATL、 C++、80x86 汇编语言、Windows API、IDispatch (OLE Automation)、HTML、DOM、 Internet Exp lore「对象模式,Windows NT以及 Windows 95 内部机制,LAN Manager 和NT网络以相关安全机制(ACE、ACL等等)、SQL及SQL Server、Jet和Access、 JavaScript、XML,还有一些其他有关直角三角形斜边的有趣事实。如果不能在 VB里用StrConv函数达成我的目的,我会为了用C++和ATL呼叫MLang函数而去写一 个COM控制组件,眼睛连眨都不会眨一下。我花了很多年才达到这种境界。 还有很多其他程序设计的世界。有开发BEA Web log i c的世界,里头的人要懂J2EE、 Oracle还有各种我列不出来跟Java相关的东西。另外也有硬派的麦金塔开发者, 他们懂的是CodeWarrior、MPW、由System 6到OS/X各版本的Toolbox程序设计、 Cocoa、Carbon、甚至还有现在已经没用的OpenDoc等过时的好东西。 不过只有极少数人能清楚一个以上的世界,因为要学的实在太多,除非在这些世 界工作过几年,否则是不会真的全部都懂。 不过你却必须学会。 面试时因为没有Win32或是J2EE或Mac程序设计经验而被拒绝,大家都会觉得很生 气。或者某些笨蛋面试官其实根本不知道MSMQ,却打电话问面试者是否具有「五 年的MSMQ经验」,也会让人觉得很不爽。 如果你刚写Windows程序不久,你可能认为Win32只不过是个链接库,跟其他链接 库差不多,要用到时再去查书学着怎么呼叫就好了。你可能会认为基本的程序 设计(比如你的C++专业技能)占九成,所有API合起来算是只占一成的小事,几星 期就可以恶补回来。对这些人我只能小声地建议:时代已经变了。现在的比例 是反过来的。 已经很少有人需要去做把字节搬来搬去的低阶C算法了。现在我们大多数人都把 全部时间花在呼叫API而不是搬移字节。一个没有API经验的C++程序高手,对用 API写程序的日常工作内容其实只知道大约一成而已。当经济状况好的时候这并 不打紧。你还是会得到工作,而雇主会花钱让你熟悉平台。不过当经济不景气时, 每个工作都有600个人申请,雇主有本钱选择已经精通该平台的程序员。比如说 能列出四种Visual Basic中FTP档案的方法,还能指出每种方法优缺点的人。 这所有的程序设计世界的表相都很多,因此常常引发毫无意义的论战,争执哪个 世界比较好。某位匿名者在我的讨论区写了以下这段自以为是的意见: 「再说另一个让我乐意留在『自由世界』的理由,言辞的自由(几乎),以及免于屈从安装程序和 registry这种东西(还有很多,我只是举两个例子)的自由。」 我认为这个人真正要说的是,在Linux世界里是不写安装程序的。嗯,我讨厌让 你失望,不过你的世界也有些一样麻烦的东西:imake、make、config檔等玩意。 另外当你完成应用程序之后,要发行时还得附上20KB的INSTALL档案,里头全是 些拿古怪装有趣的指示,比如「你会需要zlib」(那是什么东西?)或是「这会 要花一些时间,去拿一些runt吧。」(我猜runt大概是某种糖果吧)。至于registry 登录档,虽然你并没有用一个有组织的大结构(hive)存各个名称/值的组合,不 过你有上千种不同的文件格式,每种应用程序都各有一种,而且到处都有.「c和 foo.conf档案。另外想在emacs里更改设定还得学写lisp程序,而每个shell都 要你学它独有的shell脚本方言才能更改设定,还有其他其他其他。 只认识一个世界的人是很讨人厌的。他们每次听到其他世界的复杂状况时,就会 觉得自己的世界没那么复杂。不过事实上是一样的。只是你已经很精通,所以 视而不见。这些世界实在太大太复杂无法相互比较。帕麦尔斯顿勋爵(Lord Palmerston)说过:「什列斯威-好斯敦问题(Schleswig-Holstein Question)问 题实在是太复杂了,整个欧洲也只有三个人了解。第一位是已经逝世的Prince Albert。第二位是某个疯了的德国教授。第三位就是我,不过我已经完全忘掉了。」 软件的世界也是如此巨大复杂而多面相,以致当我看到某些其方面很聪明的人 在网志写些像「微软不懂操作系统」之类的空话时,不禁要坦白的说他们看起 来很蠢。Windows是由数百位程序员在十到廿年间所创造,具有数百个功能的几 百万行程序。想象尝试要概述这种庞然大物,却连开始了解其中一大部份就没 有。我并不是在为微软辩护,只是觉得这种源自极度无知的巨大模糊概括,是现 在网络上最浪费时间的东西。 常来的读者应该已经注意到我在思考要如何发展跨Linux、Macintosh和Windows 平台的应用程序,又不必为Linux和Macintosh版本投入不成比例的成本。这时候 你需要某种跨平台链接库。 Java有这个野心,不过Sun并没有真的把GUI弄通,不能做出真正感觉自然的应用 程序。这就像星舰迷航记里的太空异形透过望远镜观察地球一样,他们知道人类 食物的外观,却不了解它的味道。Java程序会在正确的地方画出菜单,可是键 盘操作和Windows程序完全不一样,而且Java的分页对话盒看起来有点恐怖。另 外不管怎么试都不能让菜单栏和Excel的一模一样。为什么会这样呢?因为Java 在抽象机制失败时,并没有提供很好的方法去将就使用平台原始的机制。当你用 AWT写程序时并不能取得窗口的HWND,不能呼叫微软的API,当然也不能把 WM_PAINT拦截起来自己画。而Sun已经表示得很明白了,如果你这样就就不够纯 粹。你被污染了所以活该去死。 试图用Java建立GUI的努力经过多次众所周知的失败之后(比如Corel的Java Office suite和Netscape的Javagator),不少人学会要和这个世界保持距尚。 Eclipse运用平台原本的机制,从最底层开始建立了他们自己的窗口链接库,这 样才能写出使用观感符合原平台感觉的Java程序。 Mozilla的工程师决定用他们自己的发明XUL来处理跨平台问题。到目前为止令我 印象深刻。Mozilla终于做到用起来感觉对劲的境界。连我最喜欢的怪用法「用 Alt+SpaceN把窗口缩到最小」都可以在Mozilla里面使用;虽然花了很久不过他 们还是做到了。 成立Lotus并创造123的Mitch Kapor决定下一个计划要做一个叫wxWindows和 wxPython的产品,目标也是跨平台支持。 哪一个比较好呢?是XUL?是Eclipse的SWT?还是wxWindows呢?我不知道。这些 都是很庞大的世界,大到我根本无法实际去评估并找出答案。光是读完教学并 不够。你必须自己去辛苦用个一两年,才能真正知道它是的确够好,还是怎么试 都无法让做出感觉对劲的使用接口。不幸的是,大多数项目都必须在写第一行 程序之前决定要用哪个世界,而这正是信息最少的时候。在前一个工作我们得面 对某些很烂的架构,因为最早期的程序员利用该项目同时学写C++和Windows程 序设计。有些最初期的程序代码是完全不懂事件驱动程序设计下写出来的。核心 的字符串类别(我们当然有自己的字符串类别)可以写进教科书,用以示范C++ 类别在设计上会犯的各种错误。最后终于把很多旧程序清理并重整干净,不过还 是让我们头痛了好一阵子。 所以现在我会建议:至少要有一个对所用的语言、类别、API以及平台有数年以 上经验的设计者,否则还是不要启动项目吧。如果你可以选择平台,就用你的 团体最熟悉的吧,即使这个平台并不是最符合趋势或看起来最有生产力也没关系。 另外在设计抽象机制或程序设计工具时,多做些努力让它不会漏吧。