最近,我重读了本·莫斯利(Ben Moseley)和彼得·马克斯(Peter Marks)的“走出焦油坑”(Out Of The Tar Pit)一文,为“我们热爱的工作”(Pap。这是一份非常有名的报纸。你可以在GitHub的Papers We Love存储库找到它,原因很简单,很多人都喜欢它。再次阅读这篇论文引发了一些思考,因此才有了这篇博客文章。
当心图灵的焦油坑,在那里一切都有可能,但有趣的事情都不容易。
图灵焦油坑是一种图灵完全的语言或系统(任何语言或系统都可以做到这一点),但使用起来既麻烦又不切实际。图灵机本身就是一个图灵焦油坑,因为你可能不会在工作中使用它来解决真正的问题。这可能很有趣,但并不实用。
标题的含义是,我们目前正处于图灵焦油坑,我们需要采取措施摆脱它。具体地说,文件中概述的措施。
本文由两部分组成。第一部分是关于软件复杂性的前因后果的论述。第二部分是提出的编程模型,以最小化软件中的所谓意外复杂性。
本文的论点是这样的:复杂性是软件开发中出现问题的主要原因。复杂性是有问题的,因为它阻碍了对软件系统的理解。这会导致各种不良的二阶效应,包括不可靠、安全问题、延迟交付和糟糕的性能,并且-在恶性循环中-复合复杂性,随着系统变得更大,所有的问题都会以非线性的方式恶化。
继弗雷德·布鲁克斯在“没有银弹”一书之后,作者们区分了本质复杂性和偶然性复杂性。作者将“本质复杂性”定义为用户看到的问题所固有的复杂性。“偶然的复杂性”就是剩下的一切,包括所有与计算的平凡、实用方面有关的东西。
作者认为状态处理、控制流和代码量是复杂性的驱动因素。大多数这种复杂性都被贴上了“偶然”的标签,因为它与机器的物理现实有关,而不是与用户的问题有关。
建议的解决方法是将用户的非正式问题陈述转化为正式问题陈述:派生出可执行规范。除此之外,我们应该只考虑到实际效率考虑所需的最小程度的“意外”复杂性的增加。
作者发现我们当前的编程模型不够完善,因为它们带来了太多的意外复杂性。因此,需要一种新的编程模型,一种意外复杂性最低的编程模型。论文的第二部分提出了这样一个模型。
当我再次阅读这篇论文时,让我印象深刻的是,它总体上对软件开发的复杂性和天真的原因是错误的。
这篇论文是错误的,有两个原因。首先,因为它将软件开发视为实现问题。如果那是真的就好了。不是这样的。如果我们一直认为是这样的话,我们在软件开发方面就不会变得更好。第二,因为它忽略了软件开发的动态性,并且做了无效的假设。具体地说,它对我们通过制作软件解决的问题的性质是天真的。
我同意作者的观点,即复杂性是软件中的一个巨大问题。复杂性的非线性累积通常会威胁到非平凡的软件开发工作停滞不前。许多软件系统不仅仅是技术债务,这是我们经常用来形容失控复杂性的术语-它们实际上已经破产了!然而,复杂性问题不能仅靠更好的编程模型来解决。我们必须追查复杂性的原因,超越机器的领域,深入到现实世界。虽然更好的编程模型会很好,但我们不能指望它们会带来奇迹。原因是,复杂性的根本原因在于软件系统与其运行的世界之间的紧张关系。这超出了编程模型的范畴。
根据作者的说法,软件开发团队的角色是“生产(使用某些给定的语言和基础设施)并维护服务于其用户目的的软件系统”。换句话说,角色是实现软件。另一方面,用户的角色是充当需要解决的问题的先知。作者在括号中指出,他们假设“用户确实知道并理解他们想要解决的问题”。然而,众所周知,这一假设是站不住脚的!问问软件行业的任何人吧!我们已经有麻烦了。如果没有这种知识和理解的来源,我们如何创建可执行规范?
在任何非平凡的系统中,都有一些需要解决的问题固有的复杂性。
因此,很明显,这个问题很重要。但这是什么呢?事实上,让我们通过问几个问题,把“需要解决的问题”这句话拉开一点。
问题从何而来?谁定义了这个问题?问题是如何表达和沟通的,是由谁向谁传达的?对问题是什么达成一致了吗?对这个问题有多少种解释和提法?为什么是这个问题,而不是其他问题?谁会受到这个问题的影响?谁对此感兴趣?谁拥有它?为什么这个问题很重要?是谁认定这是一个值得解决的问题?为什么要解决呢?这个问题有多迫切需要解决?时间相关吗?这一直是个问题吗?这个问题或类似的问题存在了多久?这能不再是个问题吗?如果问题得不到解决怎么办?部分解决方案可行吗?这个问题与其他问题有什么关系,或者与其他问题的解决方案有什么关系?问题多久改变一次?问题改变意味着什么?还需要解决吗?现实世界中的哪些力量可能会导致变化?我们能期望这样的变化有多激进呢?
我们很快就会发现问题不是解决方案,而是问题本身!如果这些问题中至少有一些没有答案,我们怎么能开始幻想如何最好地为我们的“问题”开发一个“解决方案”呢?软件开发的魔咒是,我们永远不能完全回答所有这些问题,但它们对我们的企业至关重要!如果我们要寻找软件复杂性的根本原因,我们必须从解决这样的问题开始。
当我们以某种方式将问题定义视为超出软件开发工作的范围时,我们就会给自己带来令人不快的惊喜--以及猖獗的复杂性。正如杰拉尔德·温伯格(Gerald Weinberg)在“你的灯亮了吗?”(Are Your Lights On?)中所说:“计算机领域是问题定义课程的母矿。”事实上,当我们试图实施一个解决方案时,任何关于问题是什么的模棱两可、误解、冲突、避免冲突等问题都会以复杂性的形式自然地回来困扰我们。
考虑一个由实际领域中的实际组织进行的实际软件开发的示例:由挪威国家公共广播公司NRK提供的电视流媒体服务。那是我工作的地方。有什么问题吗?这要看你问谁了。你应该问谁呢?我正好在附近。如果你问我,我是从事这项服务的众多开发者之一,我可能会说类似于“为挪威公众提供流行的、高质量的、多样化的电视流媒体服务”。很明显,提供这样的服务不是一个纯粹的技术问题:我们需要伟大的内容、伟大的展示、伟大的可用性、伟大的交付平台等等。创建有用的、重要的软件系统是一项多学科的工作。
同样清楚的是,这样一个高级别的问题陈述必须以一百万种方式加以解释和详细说明,才能具有可操作性。所有上述问题开始纷至沓来。谁提供必要的解释和审议?这个问题是谁造成的?是我们的首席执行官吗?电视流媒体服务的产品所有者?用户体验专家?我?。公众?答案是我们所有人都没有!
但它会变得更糟,或者更有趣,这取决于你的观点。世界是动态的。不管我们喜不喜欢,它一直在变。因此,“问题”也发生了变化。这不是我们可以完全控制的事情。我们不存在于真空中。例如,公众媒体消费习惯的变化对我们的影响很大。国际媒体巨头的行动也影响着我们的行动,大型社交媒体平台的行动也是如此。一切都在改变,有时会从令人惊讶的角度以令人惊讶的方式发生变化。
在这样的背景下,我们该如何解决“问题”呢?我们未来的最佳服务方向是什么?怎样才能使它更受欢迎,质量更高,更多样化,对公众更好?众说纷纭!是ML驱动的定制和个性化吗?它有更多的社交功能吗?挑战电视内容及其消费方式的是全新的身临其境的互动体验吗?我们也不知道。没人知道。
如果认为有“用户”这回事,那就太天真了。如果真的有“使用者”这回事,以为他们可以为我们提供“问题”,实在是太天真了。如果他们能向我们提供“问题”,以为它会长期稳定,那就太天真了。如果“问题”确实随着时间的推移保持稳定,那么认为每个人都会以同样的方式理解它的想法是天真的。以此类推。
我们不能指望“用户”向我们提供问题描述,至少我们不能用它来实现可执行规范。定义问题的问题随着时间的推移在一个具体但不断变化的背景下展开,在一个由人类行为者组成的复杂系统中展开。这不是无关紧要的,它在我们做的每件事中都根深蒂固。我们无法逃脱它。给它贴上意外标签也不会让它消失。
我们应该接受它,而不是忽视它或梦想一个“理想世界”,在那里软件开发的所有这些方面都可以被忽略。事实上,不仅接受它,而且把它视为我们要处理的工作。软件开发人员不仅应该提供编程或在生产中运行软件的专业知识,还应该提供心理模型的外部化方面的专业知识,以促进交流和支持协作建模。软件开发在很大程度上是一个通信问题。我们应该积极参与定义、描绘、描述和探索超越软件系统的问题域本身。我们应该提供更好的概念和更丰富的语言来描述该领域。它将帮助我们发现新的和更好的问题描述,这将导致新的和更好的软件系统。这种探索是一个永无止境的发现、协商和重新评估的过程。我们应该在这方面发挥带头作用,而不是等待别人为我们做这件事。
当我们假装有用户可以交给“开发团队”实现的“本质问题”时,我们是天真的柏拉图主义者。我们表现得好像“问题”是某种稳定和永恒的东西,是我们可以发现的先验的、神圣的实体。但这并不是大多数问题领域的现实。也许可以将这样的问题识别为纯粹抽象的数学结构--不需要在我们居住的转瞬即逝的世界中扎根的结构。但是大多数软件系统不处理这样的结构。
相反,大多数程序或软件系统在不断变化的动态世界中处理非正式的、模棱两可的、自相矛盾的、波动的、不稳定的问题。“需要解决的问题”总是处于谈判和局部理解的状态。假设和假定的不变量被一个没有特别考虑我们试图描述它的现实所证明是无效的。事实上,如果没有现有模式的失效,就不可能有创新!软件开发的问题不是“如何实现给定问题的解决方案而不搬起石头砸自己的脚”。它是将本质上是非正式和不可形式化的东西正规化。正如斯蒂芬·杰伊·古尔德在“斑马到底是什么?”一书中所说的那样,“我不相信大自然的设计会让我们沮丧,但我还是为她的不妥协感到高兴。”
作为软件开发人员,我们不能对这种情况视而不见。这是软件开发中的一个内在问题,因此也是一个基本问题,也是我们必须迎头解决的问题。在“世界与机器”(The World And The Machine)中,迈克尔·A·杰克逊(Michael A.Jackson)提到了他所说的“冯·诺依曼原理”:
在应用这些方法的概念和问题不明确的情况下,使用确切的方法是没有意义的。
这意味着我们必须获得深刻的理解和丰富的语言来描述问题域本身,而不仅仅是我们想要在该问题域中操作的软件系统。
挑战在于成功地打好一场不可能的战斗。我们必须不断尝试将问题锁定到足够的程度,以便能够构建一台有用的机器来帮助解决问题,就像我们目前所理解的那样。我们必须接受这个解决方案是暂时的,因为问题会改变。然后,我们必须努力在一个根本不稳定的问题和一个渴望稳定的机器之间保持舞蹈,而不是倒下。
如果我们忽视这一过程的本质,我们就不能指望这一努力取得成功。对软件复杂性的描述没有考虑到必然的正式系统和不可还原的非正式世界之间的持续紧张,这就遗漏了软件开发的一些基本内容。这就是为什么“走出焦油坑”是错误的。
我认为我们需要接受和拥抱这个焦油坑。至少那时我们正在努力解决复杂性的真正原因。现实世界是一个又热又粘的地方。这是我们的软件系统和我们作为软件开发人员必须运行的地方。任何有趣的事情都不会是容易的。但是也许我们可以振作起来,一切都是有可能的!