比尔盖茨是这样审查项目的 1
——选自《软件随想录:程序员部落酋长Joel谈软件》
2006
年
6
月
16
日
,星期五
早先,
Excel[1]
有一种没有名字的很蹩脚的编程语言。我们管它叫做
“
Excel
宏语言”(
Excel
Macros
)。这是一种功能很弱的编程语言,它没有变量(你不得不将值存在电子表格的单元格中),没有局部变量(
local
),没有子例程的调用(
subroutine
call
);一句话,它的程序几乎无法维护。不过,它也有一些高级语言的特性,比如任意跳转语句
Goto
,但是
label
标签实际上是看不到的
[2]
。
这种语言存在的唯一一点合理性,在于比起
Lotus[3]
中的宏语言,它看上去很强大。
Lotus
宏语言编程则仅仅是在单元格中敲入一个长字符串。
1991
年
6
月
17
日
,我进入微软公司的
Excel
开发小组工作。我的头衔是“程序经理
[4]
”(
Program Manager
),安排给我的职责是为
Excel
宏语言找到一个解决方案。实际上,所谓解决方案就是要让它与
Basic[5]
编程语言联系起来。
Basic
?一点没错!
我花了一些时间,与不同的开发小组进行沟通。那时,
Visual Basic 1.0[6]
刚刚发布,它真是太酷了。其中包括一个方向错误但还在开发中的项目,代号是
MacroMan
。另外,还有一种面向对象(
Object-Oriented
)的
Basic
也在开发,代号是
Silver
。
Silver
开发小组被告知,他们的产品将有一个客户:
Excel
。
Silver
的销售经理是
Bob Wyman
(是的,就是
Bob Wyman
那个家伙),他只需将他们的技术推销给一个人:就是我。
就像我前面说的,
MacroMan
的方向错了,开始有人还不信,不过最后它还是停止了开发。
Excel
开发小组说服
Basic
开发小组,我们真正需要的是针对
Excel
开发的某种
Visual Basic
。我设法在
Basic
里加上了
4
样好东西。我让他们加上了变型(
Variant
),这是一种可以储存任何类型数据的数据类型,否则每次要储存一个单元格中的变量值,你就不得不用
switch
语句先进行一番判断。我还让他们加上“后期绑定”(
late binding
),后来它被叫做
IDispatch
接口,又称
COM
自动化,因为
Silver
的原始设计对理解类型系统(
type system
)的要求很高,而
Excel
宏语言的各种编程者根本不需要懂这个东西。另外两个我得到的很棒的语法结构是从
UNIX
的
shell
语言
csh
中借鉴的
For Each
结构,以及从
Pascal
语言中借鉴的
With
结构。
然后,我开始坐下来,写
Excel Basic
的规格说明书。这个文档真是巨大,有几百页。在我的记忆中,写完的时候,长度是
500
页。(“瀑布开发法
[7]
”,有人在偷笑了。是的,就是这样,别笑了。)
那个时候,我们有一档子事叫做“
BillG
审查”。基本上,比尔·盖茨会审查每一个重大的功能。我被通知将规格说明书复印一份,送到他的办公
室,准备接受审查。那差不多用掉了整整一包打印纸。
我急忙将规格说明书打印了出来,送到了他的办公室。
那天晚些时候,我有了一点儿空闲时间。于是,我就开始琢磨,
Basic
的日期和时间函数是否足以完成所有能在
Excel
中完成的任务。
在大多数现代编程环境中,日期都是以实数形式存储的。实数的整数部分是从过去某个公认的日期至今所经过的天数,这个公认的日期在
Excel
中叫做“纪元”(
epoch
)。比如,今天是
2006
年
6
月
16
日
,存储的值是
38884
,而对
1900
年
1
月
1
日
来说,存储的值就是
1
。
我开始看
Basic
和
Excel
里的各种日期和时间函数,东试试西试试,结果我注意到
Visual
Basic
的文档有一个问题:
Basic
的纪元不是
1900
年
1
月
1
日
,而是
1899
年
12
月
31
日
,但是奇怪的是,当天日期的值在
Basic
和
Excel
里居然是相同的。
原因何在?
我找来一位
Excel
开发人员,他资历很老,应该记得这些事。艾德·弗莱斯
[8]
看来知道答案。
“哦,”他告诉我,“检查一下
1900
年
2
月
28
日
。”
“存储值是
59
。”我说。
“再去看
3
月
1
日
。”
“存储值是
61
!
”
“
60
是哪一天?
”
艾德问。
“
2
月
29
日,
1900
年是闰年!它能够被
4
整除!”
“思路正确,不过猜错了。”艾德说,我愣在那里。
噢,可恶。我又想了想。所有能够被
100
整除的年份中,只有能够被
400
整除的年份才是闰年。
1900
年不是闰年。
“
Excel
里有
bug
!”我惊呼。
“嗯,其实不是啦,”艾德说,“我们不得不这样设计,因为我们需要导入
Lotus 1-2-3
的工作表。”
“你是说,这是
Lotus
里的
bug
?”
“对,不过可能这是故意设计的。
Lotus
占用的内存不能大于
640KB
。这是很有限的空间。如果忽略
1900
年,那么就可以根据最右面的两位数字是否为
0
,判断任意一年是否为闰年。那就简便多了。
Lotus
的那些家伙可能觉得,过去的所有时间中只有两个月受到影响,不是很重要的事。但是看起来,
Basic
的那些家伙不想放过这两个月,所以他们将纪元向前推了一天。”
“天啊!”我发出了一声感叹,转而继续研究,为什么一个名为“
1904
日期系统”
[9]
(
1904 Date System
)的选项对话框(
options dialog
)中有一个复选框(
check box
)。
第二天就是令人紧张的
BillG
审查日。
【继续】http://blog.csdn.net/turingbooks/archive/2009/12/03/4933293.aspx
[1]
Excel
是微软公司的电子表格软件,第一个版本是在
1985
年发布的,从
1993
年第
5
版起,被并入
Microsoft Office
软件套装中。
[2]
Goto
语句通常和
label
配套使用,使程序直接跳转到
label
处。一般认为,这种跳转功能对结构
化编程是一种破坏,不提倡使用。作者在这里说:“
label
实际上是看不到的”,意即
Goto
语句在“
Excel
宏语言”中,只能直接跳转到行号,比
label
还不如。
[3]
这里
Lotus
指的是电子表格软件
Lotus 1-2-3
,这是
20
世纪
80
年代最流行的电子表格软件。微软开发
Excel
的直接目的,就是与
Lotus
1-2-3
进行竞争。
[4]
微
软的程序经理是个很特殊的职位,选择标准是:技术水平是程序员队伍中的最高级别,能做最多且最难的工作,有人格魅力。比尔·盖茨将程序经理描述为程序员队伍中最聪明的那个家伙。——编者注
[5]
Basic
语言是高级编程语言之一,最早是在
1964
年出现的。它是微软公司起家的编程语言。
[6]
Visual Basic
是微软公司基于
Basic
语言开发的第三代事件驱动的编程语言,主要特点是完全在图形界面上进行编程。
Visual
Basic 1.0
是在
1991
年
5
月发布的。
[7]
瀑布开发法(
Waterfall
),是一种软件开发方式,按照顺序从头到尾一步步完成,就好像垂直的瀑布一样,完成上一个阶段后,再前进到下一个阶段。现在一般认为这种方式已经过时。
[8]
艾德·
弗莱斯
(
Ed Fries
),后来转为开发游戏,成为微软游戏部门的副总裁,并且是
Xbox
的早期主要开发人员之一。他已于
2004
年
1
月离开微软。
[9]
1904
日期系统是微软公司为了解决
1900
年闰年问题设计的另一个日期系统。它支持的日期纪元是
1904
年
1
月
1
日
。