为什么开发软件这么贵?为什么我的团队交付软件这么慢?为什么我的软件发布落后于计划?为什么开发一个软件需要这么长时间?我们一遍又一遍地听到上述问题是有原因的。企业每天都需要新的软件功能以保持竞争力,但随着时间的推移,我们交付软件的速度似乎停滞不前,或者更糟的是,速度变慢了。我想解释一下为什么会这样。但是,为了探讨这个话题,有必要了解一个我最关心的话题:本质复杂性和偶然复杂性。1.不同类型的复杂性无论何时你解决一个问题,而不仅仅是软件问题,都有两种类型的复杂性:本质复杂性——这是包含在问题中的复杂性。如果不解决这种复杂性,就无法解决问题。它也被称为内在复杂性。附带复杂性——这是用于解决问题的方法和工具引入的复杂性。这种复杂性不是您要解决的问题的一部分,而是解决方案中引入的复杂性。它也被称为偶然复杂性。IBM的360系统之父FredBrooks在他的经典论文《NoSilverBullet:EssentialandSubsidiaryWorkinSoftwareEngineering》中介绍了这个概念。这样想,如果你要解决一个数学问题,本质上的复杂性是指对数学的理解,因为你只有理解数学才能解决问题。如果你想解决这个问题,要么学习你需要的数学,要么找懂数学的人来帮助你。要想解决这个问题,就离不开学习数学。2.偶然复杂性我们假设这是一个具有挑战性的数学问题,完全用人脑无法解决,因此需要计算器。这是偶然的复杂性。还记得您第一次使用图形计算器吗?此时,AccidentalComplexity正在学习如何在计算器上输入所有复杂的数学信息,以帮助您解决问题。您不必使用计算器,但您知道它会为您工作并且不会太难学。现在,我们假设您熟悉Mathematica。Mathematica是一个非常强大和复杂的软件,但既然您了解了它,就决定用它来解决问题。您在学习Mathematica方面投入了很多,因此不会有很多额外的努力只是偶尔增加解决方案的复杂性。几周后,你的一位同事遇到了类似的情况,并记得你曾经解决过类似的问题。他们来找您,看看您如何解决问题,然后您将Mathematica发给他们。你认为这次会发生什么?你认为他们会学数学吗?不,他们会想出另一种方法来解决问题,或者试图让你为他们做。如您所见,这两种复杂性来自不同的地方,但它们密切相关。如果不引入一些附带的复杂性,就无法解决问题。即使是一支铅笔和一张纸也会带来一些微不足道的附带复杂性。没有附带的复杂性就无法解决问题。3.它如何在软件中表现出来过去20年软件中内在复杂性与附带复杂性的比率急剧下降,这可能会让您感到惊讶。DavidHeinemeierHansson(RubyonRails之父)使用术语“概念压缩”来描述这种趋势以及它如何使我们的行业变得更好。在过去的20年里,开源框架和库的激增一直是降低软件系统附带复杂性的最强大力量。与20年前相比,解决业务问题所需的代码量减少了一个数量级,因此您可能认为开发软件会比那时快一个数量级。但这似乎并没有发生,为什么会发生这种情况?软件越来越容易开发,但同时其他现象也在发生:我们对软件的要求越来越高公司内部的软件数量呈爆炸式增长采用新技术的步伐正在加快4.我们对软件的要求越来越高尽管我们正在利用越来越多的外部工具和库来开发软件,使软件开发变得越来越容易,但我们也对我们的软件提出了更高的要求,仅这一点就抵消了很多好处。如果我们使用现代工具开发2000年代的Web应用程序,我们会看到软件开发效率提高十倍(或更多)。但我们的世界并没有停滞不前,消费者和企业对软件的期望一直在迅速增长。我们期望软件比20年前做的更多。当我们开发这些更大、功能更丰富的应用程序时,软件的开发方式必须改变,以保持它们的可靠性、功能性和可理解性。以下是我们在过去20年中看到的一些行业变化:源代码控制-源代码控制一直存在,但不像今天那么普遍。不认为这会增加附带的复杂性吗?然后问一个第一次使用Git的初级工程师他们是怎么想的。自动化测试——我们引入了许多测试类型和测试工具。我们需要做验收测试、集成测试、单元测试等……这给项目带来了很多附带的复杂性,但有助于确保交付的软件具有预期的高质量和功能。拆分系统——随着系统复杂性的增加,组件之间的连接和交互数量呈二次方增长。也就是说,在某些时候,如果软件设计不当,交互量将继续增长,直到由于自身的复杂性而崩溃。拆分系统,尤其是进行分布式拆分,会引入很多意想不到的复杂性。专业化——随着Web应用程序变得越来越复杂,出现了很多专业化。2000年,软件工程师负责UI设计、UI构建、应用后台构建是很常见的事情,但到了2020年,这些工作被分成了几个角色。开发Web应用程序的团队通常由UI设计师、UX设计师、前端软件工程师、后端软件工程师和DevOps工程师组成。在更大的组织中,会有更多专门的角色,例如安全、架构、数据管理、数据科学等……所有这些额外的角色使我们能够在更大范围内开发软件,但所需的工具和过程引入了很多附带的复杂性。基础设施自动化——为了构建更大、更复杂的环境来运行越来越多的应用程序,我们已经开始自动化构建和维护它们的过程。这使我们更容易进行大规模的环境管理,但需要一整套工具和知识。这些工具带来的复杂性是巨大的,导致DevOps成为大多数大型团队的专门角色。频繁部署——随着应用程序规模和复杂性的增长,我们需要以较小的增量交付软件以降低风险。为此,我们引入了持续集成和持续部署的概念。同样,这对于大规模交付软件非常有用,但构建和操作这些管道所需的工具和技能会带来附带的复杂性。多种设备和形式因素——以前,我们可以说我们的软件在单一操作系统上运行,只有几种分辨率。今天,我们的应用程序需要跨平台运行在台式机、笔记本电脑和移动设备上。通常,我们会有一个本地移动应用程序和一个网络应用程序,可能会加入一些物联网应用程序和手表应用程序。我们在访问数据的位置和方式方面获得了巨大的灵活性,改变了我们的社会,但肯定会增加软件开发过程的复杂性。5.企业内部的软件爆炸在阅读上一节之前,您可能已经很清楚,对软件的需求不断增加,软件开发形式越来越多,这将导致复杂性的增加。但是,从单个应用程序的角度来看,企业中拥有更多软件是否会增加开发单个应用程序的复杂性?答案很简单:不,除非您希望该软件与其他软件进行交互。公司使用的软件越多,系统之间的重叠就越多,不同的系统需要访问相同的数据才能正常运行,这就需要为更多的系统保持共享数据并集成所有系统。例如,假设你在2000年是一家办公椅制造商,那时你还没有网络系统。您需要为您的公司建立一个库存系统,因此您需要开发软件来完成它。库存系统的用户是仓库员工,您可以通过生成夜间报告来获取库存信息,这些报告也可以发送给整个公司的人员。这个系统比较独立,举报功能对大家来说没有问题。快进到2020年,您的库存系统不再是一个独立的应用程序。您的合作伙伴可以将订单直接推送到您的系统中,网页可以获得实时库存更新并在下订单时更新库存。您的库存系统直接与您的物流系统集成,以便自动生成运输标签和取件时间表。您直接在亚马逊上销售您的产品,因此您的库存系统直接与第三方软件集成。仓库工作人员使用移动设备定位、扫描、登记和拣选物品,因此您也有针对这些物品的移动解决方案。随着系统激增并覆盖业务的各个方面,越来越多的重叠开始出现,一直到不与其他系统集成就无法满足需求的程度。虽然这带来了前所未有的生产力和自动化水平,但它也为数据移动和集成带来了大量附带的复杂性。MarcAndreesen创造了“软件正在吞噬世界”这句话。这个过程正在加速,而且看不到尽头。https://a16z.com/2011/08/20/why-software-is-eating-the-world/6。Microsoft、Sun或Borland正在加快采用新技术的步伐,您可能会购买一些组件,但无论哪种方式,整个生态系统都由单一供应商提供。此时,您采用和集成的外部工具和技术相对较少,您可以完成的任务仅限于供应商提供的功能。为了跟上快速变化的技术格局,公司正在转向更开放的技术。这带来了巨大的优势,因为您可以使用这些工具来完成以前只能梦想的壮举。但是切换工具通常是有代价的,您最终会在流程中引入很多附带的复杂性。虽然使用尖端技术可能有一些好处,但技术越新,维护起来就越困难。还有,你越早采用一项技术,当它演变成一项对广泛用户有用的技术时,你就会经历越多的痛苦。如何平衡新技术的好处和使用它的痛苦是技术专家长期以来一直在努力解决的问题。我们现在发现挑选有用的工具、框架和技术是一项非常有价值的技能。无意中使用新的、未经证实的工具或框架可能会产生不利影响。它们可能会导致很多意外的复杂性,更糟糕的是,如果框架在跨越鸿沟之前就死了,就会把你带到死胡同。7.有希望吗?软件开发时间越来越长的原因有很多,比如业务需要更快的迭代,企业架构标准,或者对安全性的重视等等。但关键是,我们在2020年构建的软件与我们的软件几乎没有相似之处开发于2010年,更不用说2000年了。在大多数情况下,这是一件好事。但也有缺点。我们似乎回到了2000-2007年,当时每个应用程序都是使用相同的工具开发的,其中许多工具变得越来越复杂。现在很多流行的工具和框架都来自大企业,但是解决了很多其他企业不会遇到的问题。正因为如此,许多中小型企业,甚至大型企业的一部分,都发现他们运行软件的能力正在迅速下降,并且不知道如何扭转这种局面。他们已经开始转向低代码和无代码以加快开发速度,但在许多情况下,这也破坏了使用这些工具构建的系统的功能和寿命。
