[转] 你永远不应该做的事 -- 关于重写代码

你永远不应该做的事,第一部分

by Joel Spolsky

Thursday, April 06, 2000

原文链接 http://www.joelonsoftware.com/articles/fog0000000069.html

Netscape6.0终于要进行第一次公测了。第5.0版本从来就没有发布。最后一次主要的发布就是第4.0版本了,几乎是在3年前。3年时间在网络世界中是非常长的。在这期间,Netscape停步了,绝望了,因为他们的市场份额直线下降。

我评论他们说在两次发行之间等待这么长的时间有一点虚情假意。他们是故意这样做的,是吗?

不,不是。他们这样子是犯了一个最严重战略性的错误,这个错误任何软件公司都有可以犯:

他们决定重写代码

Netscape不是第一个犯这个错误的公司。Borland在收购了Arago并把它整合进dBase的时候也犯了同样的错误,这个项目花费了如此长的时间以使Microsoft Access吃了他们的午餐,然后他们又一次犯了这个错误去重写Quattro Pro,它的功能少的令人惊讶。微软差点也犯了同样的错误,在一个叫Pyramid的项目中重写Word,这个项目被关闭,抛弃,被掩盖掉了。幸好,微软没有停止在旧的代码的基础上做工作,因此他们能有成果,这个仅仅是财政上的灾难而不是战略上的。

我们是程序员。在程序员心中,他们是建筑师,我们到达一个地方最想要做的事情是填平道路和建造宏伟的建筑。我们不热衷于翻新:修补,改良,种植花床。

有一个微妙的原因使得程序员总是想抛弃原有的代码重新开始。原因是他们认为原来的代码太混乱。而且有一个很有趣的现象:他们可能错了 。他们认为旧代码混乱的原因是由于编程上的一个基本的,主要的定律:

阅读代码比写代码要困难

这就是为什么代码重用这个困难。这就是为什么你团队里的每个人都喜欢用的不同的字符串分割成字符数组的函数。他们都自己写自己的函数是因为这个比弄明白旧代码更简单更有意思。

作为这个公理的推论,你可以问任何一个程序员关于他今天工作的代码。"这里糟糕得一塌糊涂"他们会这样告诉你。"没有比扔掉这些重新写更好了。"

为什么代码混乱?

他们说"看这个函数。这个有两页长!这些东西都不应该在这里出现!我不知道这里面有一半API调用是为了什么"

在Borland新的Windows版本的电子表格发布前,Phlippe Kahn,这位具有传奇色彩的创始人说了发表自夸的言论,说Quattro pro相比于Microsoft Excel要优秀很多了,因为它重写了所有的源代码!好像源代码也会生锈一样。

新代码要比旧代码好的观点是荒谬的。旧代码已经在使用了。已经被测试过了。大量的Bug已经被发现了,而且被修复了。这样并没有什么不好的。把程序放在硬盘中并不能使你发现BUG。难道软件像老Dogde Dart车一样,有生锈菌会在车库里等着?难道软件像玩具熊那样如果不用新材料就不会有那么多毛?

让我们回到那个2页长的函数。是的,我知道,这只是简单的显示窗口的函数,只是长出了一些其他东西而且人知道为什么。好的,我告诉你为什么:这是为了修复BUG。有一个是Nancy修改的,修复了当在一个没有浏览器的电脑上安装的时候出现的BUG。另外一个是为了修复在低内存情况下产生的BUG。还有一个是修复当文件在软盘的时候用户拔出软盘产生的BUG。这个丑陋的LoadLibrary是为了使代码在低版本的Windows95中运行。

这些BUG都需要使用好几个星期后才能被发现。程序员也许也在实验室花费了好几天再现BUG和修复BUG。和很多BUG一样,修复BUG只需要一行代码,甚至几个字符,但是为了这2个字符需要做大量的工作和花费大量的时间。

当你抛弃这些代码重写的时候,你也抛弃了所有的知识,所有的已经被修复的BUG,多年的编程成果。

你也抛弃了你的市场领导权。你给了你的竞争者2年或者三年的时间,相信我,这个时间对于软件来说太长了。

当你几年间只发布一个旧版本的代码产品,完全不能做改变且不能适应市场需求增加新功能,那你就处在一个非常危险的境地,因为你没有可以发行的代码。你也许会在这期间关闭业务。

但是再写一遍已经存在的代码是在毫无意义的浪费大量的资金。

是否还有其他选择?大家一致认为旧版本的Netscape代码非常糟糕。也许确实很糟糕,但是,你知道吗?它在现实世界这些乱七八糟的计算机系统中运行的非常好。

当程序员说他们的代码乱七八糟的时候(他们经常这样),是因为代码中有三种错误。

第一,结构上的问题。代码没有安排在正确的地方。核心代码中有一处是在任何地方的中间弹出自己的对话框;它应该被安排在UI代码里。这个是可以解决掉的,在一个时间,小心的移动代码,重构,改变接口。可以让一个程序员认真修改和检测改动的地方一次,就没有人再被这个问题干扰了。即使一次重大的结构调整也可以在不抛弃原来代码的基础上完成。在Juno的一个项目中,我们花了几个月做只在一处做结构调整:只是移动代码,清理代码,创建基类,各个模块之间创建明晰的接口。我们在原来的代码基础上做的很认真,而且我们没有产生新的BUG,也没有抛弃原来的代码。

第二个程序员认为他们的代码混乱的原因是代码效率低。Netscape的渲染代码据说效率很低。但是这只是整个项目的一小部分,你可以优化甚至重写这一个部分。不需要重写全部的代码。当优化效率,1%的工作可以得到99%的回报。

第三,代码可能非常丑陋。我工作过的一个项目有一个数据类型叫FuckedString。另外一个项目中的成员变量名一开始以下划线开头,后来使用m_开头。因此一半的函数以"_"开头,一个以"m_"开头,看上去非常丑陋。老实说,这种事情你可以用Emacs中的宏5分钟就解决了,而不需要重写代码。

一个很重要的事情你要记住,当你重写代码并没有绝对的理由相信你会比旧代码更好。首先,你甚至没有和写第一个版本一样的开发团队,因此你并不是"更有经验"。我会再一次犯大多数以前犯过的错误,而且会比原始的版本增加更多的新问题。

当实施一个大型的商业应用的时候,像以前的生成一个扔掉一个是非常危险的。如果你对写代码有经验,你可能会在想出一个更好的算法后取消掉你上星期写的函数。这行。我也许想重构一个类是它更容易使用。这也行。但是抛弃全部的程序是危险且愚蠢的,如果Netscape拥有一些成熟的有软件工业经验的管理者,他们也许就不会把自己的脚射伤得这么严重。

你可能感兴趣的:(代码)