英文原文:The Cost of Features
文/腊八粥
忠告:这是一个汽车的类推。
下图展示了几款车型过去数年的重量变化:
这么多年,这些汽车重量就高了不少。这种趋势不仅仅体现在汽车上。波音 737-100 在 1968 年首航时、不载人的重量有 30 吨,一架现在的 737-900 却有 44 吨,甚至战斗机重量也增加了。喷火战斗机(Spitfire)MkIA 空载1,953kg,七年后,Mk24 重量达到3,247kg。
重量增加是一件坏事吗?通常不是。设计师不会无理由地增加重量。汽车比过去更加安全,它们更加舒适,有更多的特性:空调、助力转向、自动变速器、气囊。同样,一架现代 737 在运送更多乘客和货物的同时,可以飞得更远。更重的喷火战斗机因为拥有更大的发动机,可以携带更多的武器和燃油。这是一项交易:特性越多,所以重量越大。
为什么我在讨论机身和汽车呢?
下面这些图展示了某些流行开源项目的代码行数。先看 httpd:
Node.js(稍微有点不同)
这些例子不是故意挑选出来的,我在其它项目上算了算,发现它们都占用了大量空间,并增加了页面载入时间。数据相当清晰了:软件项目在随着时间的进行而变大。这不应当让很多开发人员感到吃惊。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 的状态图。