最近我偶然读到了尼基塔·普罗科波夫(NikitaProkopov)的一篇文章,名为《软件的幻灭》(Softwaredisenchantment)。这让我想起了MaciejCegłowski那篇《网站肥胖危机》(TheWebsiteObesityCrisis),以及其他几篇类似主题的文章。在软件开发者的圈子里,越来越多的人达成共识:我们的软件正变得越来越庞大、迟缓和充满漏洞。而在一个硬件本应能让我们编写出比以往更快、更小、更健壮的软件的时代,情况却恰恰相反。1996年发布的游戏《毁灭战士》(DOOM)甚至能在一台验孕棒上运行,还能在其他上百种意想不到的设备上跑起来;与此同时,2022年的聊天软件在后台运行时,占用了高达500MB(或更多)的内存,有时甚至在高端硬件上也会完全卡死。
上述关于此话题的文章,大约80%是公正合理的批评,另外20%则像是与时代脱节的抱怨。或者换句话说:大多数开发者都明白,不该说出“这不就是个智能手机操作系统嘛,能有多难?”或“我90年代用的电子表格软件才10KB,怎么现在一个《异星工厂》(Factorio)就要1GB?”这样的话。如果你没有亲身经历过开发过程,就无法可靠地估计其中所包含的艰难险阻和复杂性。
但这并不意味着就没有客观批评的空间。软件确实比以前慢了,而且体积呈指数级增长,却没有带来相应的价值提升。至少,在几乎所有现代软件中,都存在优化的机会。我们本可以让它们快上几个数量级,可以删除冗余代码,可以编写小巧且有特定用途的库,还可以找到压缩资源文件的新方法。

那我们为什么不这么做呢?
普罗科波夫的答案是“软件工程师们没有为自己的工作感到自豪”。这话有一定道理。但我坚信,努力工作并创造出卓越的产品才是人类的自然状态,我们之所以没能做到,只是因为某些因素反复阻碍了我们。因此,与其用“懒惰”这种陈词滥调来解释软件的缓慢和充满Bug,我们更应该问:“是什么样的普遍力量和激励机制,创造了这样一个让软件工程师难以做到最好的环境?”
对此,我有几个答案。
速度是一项功能,可靠性什么都不是
在工程师眼中,软件是由相互交互的组件、输入和输出构成的网络。这个模型既准确又有用。然而,软件并非以这种方式被打包、营销或销售。对于商人和客户来说,软件就是一份功能列表。
以一款库存管理软件为例。它的营销材料会包括几张高分辨率的素材照片、大胆的配色方案,以及如下陈述:
-跨多个仓库跟踪库存
-与“专业配送”、“增强供应链”和“超级收银”系统集成
-提供多层级每周和每月报告
-细粒度的访问和安全控制
-在所有终端上即时更新
-可在Windows、MacOS和Linux上运行
这些都是可以被验证的陈述;要么软件具备这些功能,要么就不具备。所有这些都可以在一小时的产品演示中得到证明。但其中只有一项涉及速度。实际上,这款软件可能非常慢,点击一个按钮要等好几秒才有反应,但这并不会让“即时更新”的说法成为谎言。
我们都同意,速度会影响用户对整个软件的体验,是衡量质量的重要指标。但它很难作为卖点来推销。如果你花时间去优化一个核心流程,而你的竞争对手却开发了一种新类型的报表,那么你接下来十笔订单里可能会因此丢掉八笔。如果你向现有用户征求意见,询问下一步该做什么,他们要求的是新功能,而不是速度——除非软件已经慢到几乎无法使用的地步。更别提,任何一个正常的董事会都不会允许公司偏离产品路线图六个月,去处理技术债务。压力总是在我们身上,要求我们不断地增加功能,功能,还是功能。
程序员想写快速的软件程序,但市场不在乎。
你可能会注意到,可靠性根本没有出现在清单上。你到底该怎么说它呢?“无Bug”?没人能保证这一点,更不用说在产品演示中证明了。“90%的单元测试覆盖率和一整套集成测试”?没人知道这意味着什么,就算向他们解释,他们也只会感到无聊。没有办法以一种既能让客户相信又让他们在意的方式来表达可靠性。敏捷时代教会了他们,Bug是不可避免的,并且你会持续修复它们。由于缺乏全面衡量软件缺陷的方法(如果我们早就知道问题所在,难道不会已经修复了吗?),这使得它不是一个可以在不同产品间进行比较的功能。我们可以投入时间去测试、重构和改进,但很可能根本不会有人注意到。
程序员想写没有Bug的软件,但市场不在乎。
磁盘占用量也不在这个清单上,尽管偶尔它会以小号、低对比度的字体出现在“下载”按钮下方。在所有这些东西里,这一项或许是最不与客户心中的竞争力或质量挂钩的。你上一次因为磁盘空间不足而责怪开发者(而不是你自己或你的电脑)是什么时候?或者根据下载大小在两款电子游戏之间做选择?大概是从未有过。你可能能找到抱怨最新一版《使命召唤》体积庞大的人,但这些续作上市第一周照样能赚十亿美元。
缩小可执行文件或输出包是一件吃力不讨好的工作。而且这通常是一项技术含量很高的工作,不仅需要理解自己正在构建的软件,还需要了解其依赖的数百个底层库。此外,这种做法还常常受到劝阻(“不要重复造轮子”),部分原因是它是一个雷区。你可能不知道某一行代码是用来干什么的,但这并不意味着它是无用的。也许对于那0.01%在智能手机上使用Ubuntu的客户来说,它决定了软件是正常运行还是彻底崩溃。也许它是唯一能让软件在每四年一次的闰日不至于彻底宕机的东西。即使是最小的实用函数,最终也会演变成一种不明显的机构知识的体现。真的不值得去碰它。
有些程序员想写体积更小的软件,但对市场或我们自己而言,好处并不明显。
消费级软件的价值被低估了
分发一款软件并不难,互联网或多或少就是为了这个目的。但销售一款软件却难如登天。同样的公众,愿意为一个三明治或一张电影票支付15美元——即使不喜欢也能耸耸肩就过去了——但如果一款他们感兴趣的软件售价为一美元,他们就会产生存在主义的怀疑。只有两个群体愿意为优质软件付费:企业和玩家。不知怎的,我们已经跌跌撞撞地进入了一个所有人都期望软件免费的世界里。
这种期望对消费级软件的质量造成了毁灭性的打击。开发一款软件的成本从5万美元到50万美元不等。如果你无法让人们从一开始就付费,就必须通过其他方式收回成本。而这恰恰是导致网页和本地软件臃肿缓慢的最大原因:用户追踪、广告、营销漏斗、联盟销售、订阅墙、针对上述所有手段的反制措施,以及上百种声誉更差的盈利渠道。这些事情常被归咎于贪婪,但更多时候它们是绝望的结果。互联网上一些受欢迎的网站也只是勉强维持生计。
像这样系统的浪费和低效程度怎么强调都不过分。你发布了一款独特、高质量的软件,定价你认为是公道的。结果一天又一天,下载量始终为零。你改用免费试用/订阅模式重建它。获得了几百次下载,但只有少数用户转化为付费计划,远不足以覆盖你的成本。你在免费版本中加入了广告,尽管这让你的UI设计师心碎。你发现广告浏览量的回报是以美分的小数点后几位计算的。你又加了更多广告。用户(令人费解的是,他们仍然免费使用着软件)抱怨广告太多了。你把一些广告换成了软件内购买。用户也抱怨那些东西。你添加了行动号召弹窗,鼓励用户付费以获得无广告体验。你发现他们中的大多数人宁愿删掉软件。你加入了分析和遥测功能,以便找出提高留存率的方法。你发现“留存率”和“成瘾性”几乎是同义词。循环继续,很快你就不再是拥有一款软件;你拥有了一台无情榨取用户注意力和隐私的快乐赚钱机器。而且你仍然没赚到多少钱。
如果人们愿意为软件付费,我们就可以避免这一切。但他们不愿意。所以,软件变得又大、又慢、又充满了毛病。
开发者没有意识到自己的力量
免得有人说我只怪别人而不反省自己,让我们审视一下软件开发者的角色。肯定有些事情是我们能做得更好的。
即使在经济衰退期间,开发者也拥有非凡的影响力。我们可以坚持使用(或不使用)特定的技术。我们可以争取高薪、福利和股权。只要展现出哪怕最微小的团结,我们就能改变整个公司的文化和工作环境。优秀的程序员供不应求。每个人都知道这一点,我们也知道他们知道。
这就是我们的力量,我们可以用它来做更多的事情。
我们应该在每个冲刺阶段都留出时间来解决技术债务。当出现特别有希望优化和改进代码的机会时,我们应该偶尔推迟功能开发。我们应该说服雇主赞助开源项目。我们应该建立一种预期,即我们不会总是按照产品路线图工作;我们的代码和行业对我们有更高的期望。
大多数情况下不会有任何负面后果。我们的要求并不算太高。其他每一个行业都有超越单一职位描述的专业标准和要求。为什么我们在软件开发领域表现得好像不存在这些一样?
唯一的警告是,激励机制对我们不利。这是一场艰苦的战斗。有些经理会对我们花时间在他们不理解的事情上感到不安。有些销售人员会担心我们的软件没有竞争力。投资者可能会威胁将我们的工作外包给更听话的开发者。客户的态度和市场力量的转变还需要一段时间。但如果改变现代软件的现状是一个值得追求的目标,那么为此付出的努力就是值得的。
情况会变好吗?
北京心玥软件公司觉得很难对软件的未来感到乐观。90年代的程序员之所以能构建出小巧、高度优化的软件,是因为当时别无选择。他们的客户只有32MB内存和200兆赫兹的单核处理器。如果一个软件不能尽可能地精简,它就根本无法运行。如今,一台两年前的基础款MacBookAir拥有250倍于此的内存(更不用说更快的速度了)和一个四核处理器,单个核心的速度也是当年的数倍。你现在可以容忍更多的冗余。我们也确实是这么做的。我们交付的软件中有90%都是死重。直到有人抱怨,我们才会去优化。我们甚至在发送消息、记笔记,甚至是编写我们自己代码的软件中都捆绑了一个完整的网页浏览器安装包(我现在就在用这样的一个)。
过去二十年致力于使软件开发更快、更容易、更傻瓜化。不可否认,我们现在创建软件的速度比以往任何时候都快,功能比以往任何时候都多,使用的开发人员经验比以往任何时候都少。从商业角度来看,这不难看到其吸引力。但我们正在付出代价——我们的客户、电网和地球也是如此。
事情不会在一夜之间改变,可能在未来五年内也不会。但仍有理由抱有希望。
最新的一波Web编程语言和技术(如WebAssembly,ESBuild,SWC,Bun,Yew)正在实现编译时和运行时前所未有的速度和可靠性。Rust以其兼具C语言的性能和高级语言的开发友好性而闻名,正在网络服务器端越来越受欢迎。像Tauri这样的轻量级Electron替代品正准备接管,成为Web开发者首选的跨平台框架。摇树优化(Tree-shaking)已成为我们对编译器和打包器的基本期望。
在市场方面,几款热门电子游戏(如《死亡细胞》DeadCells和《以撒的结合》TheBindingofIsaac)已经作为付费下载登陆移动平台。虽然还有很多工作要做,但这是在重新教育全球最大的科技消费群体——智能手机用户关于软件成本方面迈出的充满希望的一步。
如果说过去的20年是为了提高我们的生产力——在此过程中牺牲了效率和经济可持续性,那么接下来的20年或许会致力于解决我们共同的技术债务,夺回效率,并在不失掉使我们生活中无处不在的软件生产力的前提下,改善经济交换。