为什么构建软件需要这么长时间? (2020年)

2021-01-28 21:54:16

为什么构建软件需要这么长时间?我们经常听到这个问题的变化:为什么构建软件如此昂贵?为什么我的团队交付软件如此缓慢?为什么我的软件永远落后于进度?

我们有很好的理由一遍又一遍地听到这些问题。为了保持竞争力,企业每天需要越来越多的定制软件,但是随着时间的流逝,我们交付软件的速度似乎停滞不前,或者变得越来越慢。

我想和大家谈谈为什么会这样,但是为了探究这个话题,我需要向您介绍一个我心中最亲近的话题:基本的复杂性和偶然的复杂性。

无论何时解决问题,不仅是软件问题,都有两种复杂性:

基本复杂性–这是解决问题的复杂性。不解决这种复杂性就无法解决问题。这有时也称为固有的复杂性。

意外的复杂性–这是您用来解决问题的方法和工具所伴随的复杂性。这种复杂性不是您要解决的实际问题的一部分,而是解决方案带来的复杂性。有时将其称为附带复杂性。

弗雷德·布鲁克斯(Fred Brooks)的开创性论文“ No Silver Bullet –软件工程的本质与事故”向我们介绍了这个想法。这样想吧,如果您想解决数学问题,那么本质上的复杂性就是对真正计算解决方案所需的数学的理解。如果您想解决问题,则必须学习所需的数学知识(或找一个知道的人)。如果您想解决问题,就无法逃脱数学运算。

让我们假装这是一个具有挑战性的数学问题,而在您的脑海中做所有这一切实际上将毫无用处。在这种情况下,您将需要使用计算器。这是偶然的复杂性。还记得您第一次尝试将图形计算器用于除基本数学之外的其他功能吗?偶然的复杂性是学习如何使用愚蠢的TI-83来输入所有复杂的数学运算以帮助您解决问题。您不需要使用计算器,但是您知道它会有所帮助,并且学习起来可能不会太难。

但是,让我们假装一下您对Mathematica的熟悉。 Mathematica是一款功能强大且复杂的软件,但是由于您已经知道它,因此您决定使用它来解决问题。您已经在学习Mathematica上进行了投资,因此这并不需要您付出很多额外的精力,但是您只是将解决方案的意外复杂性提高了天文数字。

几周后,您的同事处于类似情况,并且记得您解决了一个非常相似的问题。他们来找您解决问题的方法,然后将其发送给Mathematica项目。您认为此时会发生什么?您认为他们会学习Mathematica吗?不。他们将找出解决问题的另一种方法,或尝试使您自己解决问题。

如您所见,这两种复杂性来自不同的地方,但是它们有着千丝万缕的联系。没有一些意外的复杂性,您就无法解决问题。甚至铅笔和纸也带来一些微小的意外复杂性。

这可能会让您感到惊讶,但是在过去20年中,软件的真正革命是显着降低了基本与意外复杂性的比率。 DHH使用术语``概念压缩''来描述这种力量以及它如何使我们的行业变得更好。在过去的二十年中,开源框架和库的激增一直是减少软件系统意外复杂性数量的最强大力量。

您可能认为大量的外部框架和库增加了复杂性,在某种程度上,我认为这是对的。但是,请考虑我给出的上一个示例,其中提供了Mathematica来解决您的数学问题。 Mathematica带来了很多意外的复杂性,这是因为该工具的功能强大,并且需要学习曲线才能加快该软件的速度。但是软件本身的复杂性如何?已经开发了数十年的Mathematica这样的工具内部的复杂性是巨大的,但是这种复杂性在很大程度上对您隐藏了。只有您需要与之交互的区域的复杂性才会真正影响您。

现在,当然,如果工具内部出现问题,并且您必须对其进行深入研究,那么您会突然面临内部复杂性。如果您使用的是最可靠的工具,那么您几乎不会以这种方式接触内部。

与20年前相比,解决业务问题所需的代码量减少了一个数量级,因此您会认为创建软件的速度要比当时快一个数量级。不过,这似乎没有发生,那为什么不呢?怎么了?

软件已逐渐稳定地易于创建,但是在这种情况下,同时发生了其他现象:

尽管我们正在利用越来越多的外部工具和库来创建我们的软件,这将使软件的创建更加容易,但是我们对软件的需求却越来越多。仅此一项就抵消了巨大的收益。如果我们仍在尝试使用现代工具构建2000年代的Web应用程序,那么实际上我们会看到软件构建的生产力提高了十倍(或更多)。

但是事情不会停滞不前,消费者和企业对软件的期望都在迅速增长。我们希望软件比20年前做更多的事情。而且,当我们构建这些更大,功能更多的应用程序时,为了使它们保持可靠,功能性和可理解性,我们不得不改变构建软件的方式。

这只是过去二十年来我们在整个行业中看到的变化的一些示例:

源代码控制–源代码控制已经存在了很长时间,但是并不总是像现在这样普遍。难道这不会增加意外的复杂性吗?第一次去问一个使用Git的初级工程师。

自动化测试-我们引入了许多测试和测试工具。我们进行验收测试,集成测试,单元测试等……这给项目增加了很多意外的复杂性,但是这样做的好处是确保交付的软件具有高质量和预期功能。

拆分-随着系统复杂性的增加,组件之间可能的连接和交互的数量呈二次方增长。这意味着,在某些时候,如果软件设计不当,这些相互作用将继续增长,直到软件因自身的复杂性而陷入困境。分开系统,尤其是在网络上分散时,会带来极大的意外复杂性。

专业化-随着Web应用程序变得越来越复杂,我们开始引入很多专业化。在2000年,软件工程师设计UI,构建UI和构建应用程序的后端并不少见,而到2020年,这只是少数几个角色。通常,构建Web应用程序的团队将由UI设计器,UX设计器,前端软件工程师,后端软件工程师和DevOps工程师组成。在大型组织中,您将把人员与安全,架构,数据管理,数据科学等方面的更多专业知识混在一起。所有这些额外的角色使我们能够大规模构建软件,但需要组织团队的工具和流程像这样会带来大量的意外复杂性。

基础架构自动化–为了构建更大,更复杂的环境来运行越来越多的应用程序,我们已经开始自动化其创建和维护。这使我们可以更轻松地大规模管理环境,但需要有效地做到这一点的全套工具和知识。其中一些工具带来的复杂性可能非常庞大,导致DevOps成为大多数大型团队的专门角色。

频繁部署-由于应用程序的规模和复杂性不断增长,我们需要以较小的增量交付以降低风险。为了实现此目的,我们引入了持续集成和持续部署的概念。同样,这对于大规模交付软件来说是很棒的,但是它带来了构建和操作这些管道所需的众多工具和技能带来的意外复杂性。

多种设备和外形-我们曾经可以说我们的软件在单个操作系统中以几种已知的分辨率使用。现在,我们的应用程序需要在众多平台上的台式机,笔记本电脑和移动设备上运行。通常,我们将拥有本机移动应用程序以及Web应用程序。可能会投入一些IoT应用程序并观察它们。这为我们提供了在何处以及如何访问数据的极大灵活性,这一变化已经改变了我们的社会,但无疑给软件构建过程增加了复杂性。

甚至在阅读以上部分之前,您可能对如何对我们的软件提出更多要求并构建多种外形会导致复杂性增加的想法非常了解。但是,在单个应用程序的基础上,企业内部拥有更多软件如何增加构建单个应用程序的复杂性?

答案很简单。不需要,除非您希望该软件与其他软件进行交互。公司中存在的软件越多,系统之间的重叠就越多,这意味着不同的系统需要访问相同的数据才能起作用。这意味着更多的系统可以存储共享数据以及它们之间的集成。

举例来说,假设您是2000年的办公椅制造商,但是您还没有网络。您需要为您的公司构建一个库存系统,因此您需要构建软件来做到这一点。该库存系统供仓库中的人员使用,您可以每晚运行报告以获取库存水平,并且可以将这些报告发送给整个公司的人员。该系统相对独立,每个人每晚的报告都​​可以。事情进展得并不快。

快进到2020年,您的库存系统绝非独立的。您拥有可以直接将订单推入系统的合作伙伴,您拥有一个网上商店,可以实时更新库存并在下订单时更新库存。您的库存系统直接与托运人集成在一起,因此您可以自动生成托运标签并安排取件时间。您直接在Amazon上销售产品,因此库存系统直接与管理该流程的第三方软件集成在一起。仓库中的人们正在使用移动设备来查找,扫描,检入和拣选库存,因此您可能拥有一个移动解决方案来管理所有这些。

随着系统的扩散,并接管业务运营的方方面面,它们开始越来越多地交叠,直到不与其他十几个系统集成就无法满足其需求。尽管这提供了前所未有的生产力和自动化水平,但您猜到了,它在所有数据移动和集成周围引入了大量意外的复杂性。

马克·安德森(Marc Andreesen)以“软件正在吞噬整个世界”这个词而著名,该过程正在加速发展,而且没有尽头。

早在2000年,您通常是从单一供应商(例如Microsoft,Sun或Borland)购买平台的,并且可能会购买一些组件,但是整个生态系统都是从单一供应商那里购买的。您在供应商支持下可以完成的工作有限,但是您采用和集成的外部工具和技术的数量却相对较少。

为了跟上快速变化的技术格局,公司开始采用更加开放的技术,这些技术会迅速发展。这具有巨大的优势,使您可以使用以前可能梦previously以求的工具来完成这项任务。但是切换工具经常要付出代价,最终您会在流程中引入很多意外的复杂性。

尽管使用前沿工具可能会在某些领域为您带来性能提升,但它越新,您在使用它方面的痛苦就越多。此外,采用这项技术的时间越早,随着它逐渐成长为一种对广大用户有用的工具,您遭受的痛苦就越大。在很长一段时间内,技术人员一直在努力平衡利用新技术所带来的痛苦和使用新技术带来的痛苦。

现在,我们发现自己处于一个能够筛选大量有用工具(可能会持续6个月以上)的工具,框架和技术的世界中,这是一种非常宝贵的技能。但是,如果您不小心,抓住未经验证的新工具或框架可能会产生不利影响。如果该框架在跨越鸿沟之前就消失了,它们可能导致大量意外的复杂性,甚至更糟的是,死胡同。

当然,我们还有更多理由可以讨论为何构建软件需要这么长时间。诸如业务之类的事情需要更快地改变,企业体系结构标准或对安全性的日益重视。但关键是,我们在2020年构建的软件几乎与我们在2010年构建的软件类似,而在2000年则少得多,这在很大程度上是一件好事。

但是,还有一些缺点。感觉到我们回到了2000年到2007年的时候,每个应用程序都是使用相同的工具构建的,其中许多工具正变得越来越复杂。现在流行的许多工具和框架来自大型组织,这些组织可以解决许多企业没有的问题。

因此,许多中小型企业,甚至大型组织中的部门都发现,他们在软件上执行的能力正在迅速下降,他们不知道该如何解决。他们已经开始转向低码和无码围墙花园,以提高开发速度,但是在许多情况下,他们正在削弱使用这些工具构建的系统的功能,寿命和持续的维护成本。

在以后的文章中,我将讨论意外复杂性对软件项目的影响,以及如何在确保仍然满足业务需求的同时更有效地避免这种情况。