特性的代价

本文是翻译,版权归原作者所有


忠告:这是一个汽车的类推。

下图展示了几款车型过去数年的重量变化:

几种汽车车型的车身重量逐年变化图

这么多年,这些汽车重量就高了不少。这种趋势不仅仅体现在汽车上。波音737-100在1968年首航时、不载人的重量有30吨,一架现在的737-900却有44吨,甚至战斗机重量也增加了。喷火战斗机(Spitfire)MkIA【注4】空载1,953kg,七年后,Mk24重量达到3,247kg

重量增加是一件坏事吗?通常不是。设计师不会无理由地增加重量。汽车比过去更加安全,它们更加舒适,有更多的特性:空调、助力转向、自动变速器、气囊。同样,一架现代737在运送更多乘客和货物的同时,可以飞得更远。更重的喷火战斗机因为拥有更大的发动机,可以携带更多的武器和燃油。这是一项交易:特性越多,所以重量越大。

为什么我在讨论机身和汽车呢?

下面这些图展示了某些流行开源项目的代码行数。先看httpd

httpd代码行数逐年变化图

Node.js(稍微有点不同)

node.js代码行数逐年变化图

Cassandra

cassandra代码行数逐年变化图

这些例子不是故意挑选出来的,我在其它项目上算了算,发现它们都占用了大量空间,并增加了页面载入时间。数据相当清晰了:软件项目在随着时间的进行而变大。这不应当让很多开发人员感到吃惊。Zawinskin’s Law数个世纪前就被创立了。

但是,为什么汽车、机身和软件在增加呀?我们应当天真地期待它们当中至少有一些随着时间而收缩。

我不知道答案,不过我的确有一些臆测。工程学参与了交易。其它所有条件相同的情况下,代码越多,意味着bug越多。当然,其它所有条件是不同的。特性越多,意味着代码越多。通过复杂缓存层次化、索引和有效率的数据结构提高性能,就需要更多的代码。让软件可靠、分布式、可伸缩将产生海量代码。直到最近,网页上的圆角效果所需要的代码数量还是怪里怪气的。

因此我们有增加代码的正当理由了,不过,这不足以引起软件膨胀。当我们随着时间的进行添加代码的时候,通过移除足够多的代码来阻止膨胀。我们为什么不那样做呢?一些理由涌上心头:

因此移除代码是一项艰巨的任务。但是我们该怎样阻止软件项目被它们自己的体积压垮呢?我能给出的最佳答案就是:你阻止不了。只要你敲入git init,你就输了战争。为什么?

我们再看看汽车,汽车公司在设计汽车方面有巨大的预算,但是他们不会减少重量,他们有不同的战略:随着一种车型在重量、功能和价格上的增加,厂商就可以引进更小的车型。本田思域(Civic)是本田在美国市场最小的汽车。十年前,他们引入了飞度(Fit)。大众的Polo代替了旧Golf的角色。

类似的过程也在软件上发生着。随着一款软件越来越复杂和膨胀,较新的项目将取代老款软件。Firefox取代了Netscape和Internet Explorer。在Debian和Ubuntu里,dash取代了bash。Nginx、Node.js和其它软件正在吞噬httpd的领地。

我上面说过,工程学参与了交易:代码多是因为特性、性能和可伸缩性。如果朝相反方向做同样的交易,会怎么样?回到汽车:如果你为了降低重量而移除了特性,你会得到什么?甚至符合现代排放和安全要求,开发一款与30年前小型汽车同等重量的汽车也是可能的,结果就是路特斯Elise(Lotus Elise)【注1】。它并不适合每个人,但它绝对是汽车行业壮举。

有没有遵循同样模式的软件项目呢?人们使用现代语言、资源库和技术开发过只做好一件事的一款小众软件吗?那就是Unix哲学【注2】,但是当我试图举例的时候,却想不了太多。甚至Ag【注3】已经开始吸收了更多功能(尽管如此,这仍然没有让它变慢)。

本文太长了,我没有任何主要结论能总结出来,因此我就写到这里。我这是失礼的举动,不过它没有发布在《纽约人》上。顺便提醒一下:这篇结构混乱的文章甚至和科学都靠不上。我将钻研深挖这个话题,不过我最近在忙于工作。乐观地讲,我从来没有这么富有成效,请看我的GitHub的状态图

译文:特性的代价 》| 腊八粥