查看原文
其他

为什么软件开发这么难?

Jeremy Mikkola CSDN 2021-04-25

【CSDN 编者按】“学不动了、太难了!”,有不少徘徊于程序员这一职位门口以及想要进阶提升的从业者直呼道。对此,我们不禁好奇,软件开发这一行业迭代了多年,为何还是这么难,究竟是编程语言、开发环境的影响,还是存在一些其他因素?本文中,我们即将为大家分析其中具体的原因。

作者 | Jeremy Mikkola  
译者 | 弯月    责编 | 屠敏
出品 | CSDN(ID:CSDNnews)

有的人认为,一款好的编程语言可以减轻软件开发者身上的负担,且能够相应地提高他们的效率。

毫无疑问,这一点在很久前的汇编与 Fortran 时代确实如此。

然而,如今编程语言已经足够好了,我们仍然面临着一些其他方面的困难与挑战。时下,很多开发者认为,编程的难度依然非常大,但是这些困难与编程语言无关,原因有以下几点。

阿姆达尔定律


在需要执行一系列的任务时,我们就会想起阿姆达尔定律。这条定律告诉我们,仅通过加速某一项任务而获得的整体速度提升有硬性限制。

假设把水烧开需要10分钟,然后煮面条也需要10分钟。即便你找到一种方法加快烧开水的速度,做饭的时间也不会少于10分钟。任凭炉子再旺,也不可能将做饭的速度提高到两倍。

该定律的数学公式为:假设某件事的总时间比为p,则你永远无法获得大于1/(1 – p)的加速比。假设这部分工作占用了90%的时间,即p = 0.90,在优化的过程中,如果将这部分的时间降至0,则整体的工作速度将提高1/(1 – 0.90) = 10倍。

姆达尔定律的关键在于,你能够获取的最大速度提升受限于优化的工作所占的比例。

造成编程工作难度非常大的原因有很多。简单来说,我们可以认为这是由于我们需要处理的工作必须按照一定的顺序完成毕竟人类不是很擅长同时处理多项任务。在某个时间点,你可能在使用构建工具、阅读文档、编写代码或参加会议。当然你也有可能在开会的时候忘我地写代码,但你只能做一样工作,无法同时兼顾写代码和开会。因此,我们可以应用阿姆达尔定律,假设你能设法将构建时间降至0,但项目的整体速度也只能加快一点点。你的工作效率仍然会受到其他因素的限制。

曾经,将程序转化成计算机可以运行的代码非常困难。很久以前,我们甚至需要将程序转换成1和0,然后不厌其烦地将其输入到计算机。我不知道这中间需要花费多少时间,但我们可以假设这项工作占据了90%的编程时间。这意味着,如果我们能找到一种更好的办法(比如Python)告诉计算机干什么,就可以将编程效率提高10倍之多。

然而,如今我们的编程语言越来越好了,告诉计算机干什么的时间也越来越少了,将程序转化成代码也不需要花费90%的时间了。假设现在我们只需要10%的时间。这意味着,如今即便将这部分工作的时间降至0,也只能提高1.11倍的效率。效率提升比以前减少了81倍。

这是因为其余90%的软件开发工作都是非常艰巨的任务,即便编程语言再好也无法(直接)减轻我们的负担。


为什么编程的工作还是这么难?


传达需求

这里我所说的编程工作很难,实际上与编程语言毫无关系。为了找出其中的原因,暂时假设我们完全不使用计算机。你无需告诉计算机做什么,但你需要告诉你的朋友该做什么。别作弊,也不能告诉你的朋友自己看着办,你必须为他们做所有的决定。 

你会发现,你需要花费大量时间才能解释清楚关键的背景信息。你的朋友需要了解程序需要处理的现实问题,以及你认为该程序应该提供哪些功能。你必须解释清楚所有的缩写字母和术语,而且还需要讨论各种外部因素。

你的朋友需要知道所有可能出现的情况,需要处理的细节非常多。

同时,你还需要考虑不同功能的状态两两组合,用户可能会尝试的各种动作,以及所有可能出现的事件,你需要与朋友讨论大量的极端情况。

向你的朋友解释清楚这一切的难点有好几个。首先,你必须掌握所有的实际细节;其次,你必须了解程序在每种情况下应该执行的操作;再者,你必须通过朋友能够理解的方式来传达所有的信息。这意味着你必须有条理地组织这些信息,以确保便于理解。

请注意,到目前为止,我们甚至还没有提及计算机,当然也没有提及编程语言。理解需求,掌握程序应该做什么以及组织表达方式,这些都是非常艰巨的任务。

描述与规格

我们很容易搞混描述与规格之间的区别,这是一个我们经常会踏入的思维陷阱。如果你只有一段描述(“红色汽车”),则你可以测试实际情况是否符合该描述(“是红色,但不是汽车”),但是这段描述并不足以传达如何制造一辆汽车。而这就是规范的用途。

创造事物需要做出很多决定。如果记录下每个决策的结果,就会得到一份(杂乱无章的)规范。编写程序的时候,你需要做出这样的决定,因此仅凭描述还不行,你需要一份规范。在看到一段描述(“列出文件”)时,我们很容易认为这是一个规范,因此我们觉得应该能够告诉计算机执行该动作。但实际上,这中间有大量的决定需要考虑(“文件应以什么顺序列出?每个文件一行吗?”)

在编写程序的时候,你拿到的规范常常只是一段描述。计算机无法“绘制矩形”,它必须知道这个矩形的显示位置、大小以及颜色。在编写这段代码的时候,你会发现很多尚未做出的决定。做这些决定需要付出很多努力。我们经常会弄错引发这些工作的缘由,将其归咎于编程语言,但其实这只是因为我们很难根据一段描述创建规范。

计算机本身

下面,说回计算机。开发软件不仅仅是了解软件应该做什么,并将各种想法转变成代码。计算机本身也有很多程序必须解决的问题。你的程序必须在硬件和网络上快速地运行。程序需要处理机器故障。而工具和协议的复杂性导致该领域所要面对的问题更多。这些困难都不是由向计算机解释做什么的过程引起的,它们也是需要解释的事情。

另外,你需要在脑海中运行某些程序。有时逻辑很容易理解,但有时你无法将一系列的事件和状态尽数塞入脑海中。为了正确理解程序的详细信息,在出现错误的情况下修复程序,你需要了解各种情况下程序本身的状态。

编写代码的过程,可以让你清楚地掌握程序的工作方式。然而,程序永远不会停止变化。你会发现错误、添加新功能或修改现有的行为。即便程序最初的组织方式非常有效,但也不意味着它的结构永远正确。你需要花费时间组合各种情况,考虑未来的需求,并在出现意外的时候收拾烂摊子。

人员合作

很多时候,我们需要与其他人合作编写程序,而这也会带来挑战。

所有的团队成员都必须各司其职。为了他们之间不互相妨碍工作,你必须进行分工。为了建立合理的分工,首先你需要了解程序的结构(请参见康威定律)。

如果你有多个团队,则情况会更复杂。每个团队都有不同的目标,因此你必须权衡各个方面。有时,某个决定非常利于其他团队,但会阻碍你的工作。设身处地为他人着想,并找到合理的妥协方案是非常艰难的工作,但必须完成。

在大型项目中,没有任何一个团队能够了解整个系统,更不用说一个人了。但是,你依然需要弄清楚系统的各个部分是如何设计的,又是如何组织到一起的。这比你自己承担起整个设计还要难。

虽然与人打交道并不是真正意义上的编写代码,但也是开发软件中非常重要的一部分。


如何解决软件开发的外在难题?

 

我们可以寻找一些不受阿姆达尔定律限制的方法。如果各个任务的速度不是完全独立的(比如优化一个任务能够加快另一个任务的速度),我们就有希望通过技术解决方案改善这个问题。

我们需要更好的语言和开发环境。如果我们可以用更少的人编写程序(比如两个人能代替整个团队,或者一个团队代替一个部门),则可以大大削减组织规模。如果由同一个人来编写接口的前后台,就不需要开会讨论了。生产率的提升不仅可以降低编写代码的成本,而且还会改变工作的方式,从而降低其他工作的成本。虽说如此,但这种方式也有局限性,因为程序员无法将所有业务都纳入他们的脑海中。

迭代速度是另一个杠杆。为了编写程序,你需要了解领域知识以及需要做出的决定。为此,你需要了解所有细节,然后建立一种思维模型。虽然这种方法可行,但可能不是最有效的方法。还有一种方法,根据一些显而易见的细节,构建一个小型的思维模型。然后,根据这个模型创建一个小程序,并实际验证这个思维模型。然后根据得到的反馈进行迭代,这样每次创建的模型就会越来越丰富,越来越准确。这种方法似乎更好,因为它更符合人们学习的过程。为了保证这种方法的有效性,你需要快速测试并获得反馈。理想状态是在输入完代码后,新的代码就立即开始运行。改变开发环境,实现更快的迭代周期,可以让开发人员从第一种方法转变成第二种,从而帮助他们理解问题。

更具表现力的编程语言是否能够显著地提高生产力?我并不是很乐观。然而,我认为仍然有可能出现更好的开发环境。如果我们能通过更好的工具来理解现有代码,实现更快的开发迭代周期,并减少繁琐的“体力”劳动,就有可能改变软件开发的方式,并从多方面改善我们的工作。

原文地址:http://jeremymikkola.com/posts/2021_01_01_why_software_development_is_hard.html

声明:本文为 CSDN 翻译,转载请注明来源。

☞华为:今年至少 3 亿台设备使用鸿蒙;增长 7%,互联网人薪资报告出炉;英特尔侵犯芯片专利被判赔偿 22 亿美元 | 极客头条

“5G 太耗电,关掉它!”

Go 语言“助力”恶意软件?仅 4 年基于 Go 的恶意软件数就激增 2000%!

平均 15189 元!2021 年 3 月程序员工资统计出炉

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存