第二章:我们是如何做决定的
来自 Tudor Girba 和 Simon Wardley 著
为什么要谈做决定?开发人员常常花费超过一半的时间来理解系统,以确定下一步该做什么。他们可能需要探索变更的影响、一个错误的根本原因,或者如何迁移一个组件。离实际的代码编辑和提交越远,就越需要做出诸如架构或产品选择等重要决定。
总的来说,软件工程可以被视为一系列关于不断变化的系统及其周围环境的决策过程。但这样的决策过程究竟是怎样的?这很少是我们自己会去思考的问题。
我们通常更加关注决策的结果,而不是决策的过程本身。也就是说,我们会问是否可以使结果更符合业务目标(结果),而不是问决策过程是否可以“更佳”地进行。理想来说,我们既要关注这两方面,但首先应该注重的是过程。
通常,理性地做出工程决策的方式可以描述如下:
- 我们评估这个问题
- 要评估这个问题,我们需要探索我们正在考察的系统。
- 要探索系统,我们需要与人或系统进行对话。
- 进行对话需要我们能够分享或接收的信息。
- 信息不会凭空出现,而是需要以某种方式获取或处理的。
- 要获取信息,我们需要某种形式的开发经验来与系统交流。
图1展示了这些步骤。
图1- — 决策的过程如下。
这些步骤已经在Wardley地图中绘制完成。这些地图提供问题空间的可视化,并基于一套系统的标记体系(它们也让Simon感到满意)。我们使用地图,因为试图解释软件决策的特点和后果是一件极其困难的事情。我们知道这一点,因为我们尝试了15年来通过概念和科技来传达这些想法,但总是无法充分表达。问题在于叙事的局限。地图使我们能够简洁地呈现复杂和多维度的信息。
沃德利地图的基本构成包括一系列相连的组件,每个组件都需要下一个组件,因此形成了需求链,并根据其在x轴上的进化位置来定位每个组件。x轴始终分为四个部分,用不同的标签表示资本的不同发展阶段。这种资本可以是活动、实践、数据或知识。对于我们的地图,因为我们使用了多种形式的资本,我们为x轴的每一部分选择了两个标签。这些标签分别是概念/起源、新兴/定制、趋同/标准化产品和通用/商品化。
用红色文字编写的标签“概念、新兴、汇聚和已被接受”描述了信息使用过程中共识的程度。这些标签对应于地图上半部分以红色绘制的组件和连接。例如,“探索”这个词通常被认为是一种新兴的做法,我们在后面会解释原因。
这些蓝色标签,包括起源标签、定制构建、产品和商品,描述了信息提取流程和工具的工业化程度(蓝色连接)。例如,有许多竞争性的开发工具。
这本书中的许多概念在描述上可能显得抽象,但在实践中却非常有力。因此,为了帮助读者克服这种感觉,我们通过从我们的实际经验出发,以问答的形式逐一解释每一个步骤。我们首先来探讨一下“我们今天是如何在实际中做决策的?”这一问题。为了解答这个问题,我们从图1的底部开始,逐步向上进行。
我们只能通过一些形式的开发体验来体验一个系统,而这些工具提供体验该系统的方式。当前的做法是使用 _单一式 的工具,这些工具是为通用使用而设计的,没有针对特定上下文需求进行专门设计。因此,我们用于调查医院系统的软件工具通常与调查在线赌博网站的工具相同。在现实世界中,这就好比试图用同一套工具来建造一级方程式赛车和挖掘深矿一样。
这些标准的软件工具非常普遍,你可能不需要查看就能描述它们的样子。它们通常在左侧有一个导航窗格,顶部有一个简单的搜索功能,还有一个显示选定项目信息的一般窗口(如代码)。你甚至可以通过右键点击导航窗格中的某个项目来查看其属性。即便如此,你查看和与系统“数据”互动的方式已经被预定义了,也就是说,工具限制了你如何查看数字世界中的数据。
使用这些工具,我们手动审查系统,来获取我们所需的信息。在此过程中,我们花费了超过50%的开发时间,包括阅读大量代码、调查错误跟踪或检查日志条目以找到我们认为必要的信息。
我们找到的信息随后会人工整理成系统视图。例如,我们可能会创建架构图、领域模型或网络图。我们常常需要离开那个单体工具,以不同的格式呈现这些信息,比如用 PowerPoint 展示架构图,而该架构图表示我们通过代码编辑器找到的代码。有时我们甚至不使用数字工具,而是用白板、纸张或便利贴来创建这些视图。
有时会使用自动化工具,例如事件随时间变化的图表,但这些工具通常非常通用且高度限制性,预定义的视图有限。如果你曾经使用过这些工具,你可能会发现图表并不完全符合你的需要,并且在工具内部无法对其做出任何改变,通常只能尝试将数据导出到其他工具(如Excel),以创建一个“更好”的图表。
我们创建的视图被认为是关于系统的数据的代表,我们的对话也是基于这些视图,例如图表中的事件随时间的数量,以及可能与我们的网络图的连接。但请想一想,这些视图有多具代表性?你见过多少架构图实际上是错的,后来才发现缺少某些组件,或者自架构图创建以来已经发生变化?关于系统的手绘图就好比用来记录历史的画作,它们更多地反映了作者当时的视角,而非系统本身。我们称之为 “以数据为中心”, 但因为这些视图究竟有多具代表性我们心里没底,所以在‘以数据为中心’这个词上加了引号。
在这种持续部署的世界里,放弃详细绘制架构图几乎成为了一种时尚,要么保持架构图的高层次,仅包含必要信息,要么依赖定期手动更新的纪律。一篇 InfoQ 的文章表示:“最大的错误之一是为系统中变化频繁的部分创建详细的架构图。” 这实际上是在承认失败,接受我们应该依赖那些不可靠的东西。即使使用了供应商工具,通常也被认为是不够的,因此需要通过手动建模的图表来补充,因为工具无法捕捉到关键的上下文信息。
这些对话是我们探索系统的一部分。在软件探索中,这一过程通常是由一系列临时的对话和互动驱动的。相比之下,地理探索则遵循一种更为结构化的方法。它从一张空白的纸开始,通过移动、观察和使用专业工具(如经纬仪等),系统地构建景观模型,从而创建可靠的地图来帮助我们更好地了解空间。
没有可靠的系统可视化,任何依赖手动绘制图表的探索可能只是部分的,不完整,并且可能包含隐藏的信念。这会导致评估主要基于我们是否相信所呈现的观点,因此主要基于我们的直觉感觉。
总之,当前的做法可以描述为基于直觉的感觉评估,这种评估是基于即兴探索,建立在被视为“data-centric(数据驱动的)”的对话之上,这些对话是通过手动信息合成的。该过程使用的是通过单一工具开发经验进行的手动审查。我们已更新了Wardley map以反映当前的做法,如图2所示。
图2显示了今天软件工程中制定决策的常见流程。
在创建这张新地图时,我们引入了管道这一概念,并考虑了当今实践中各组件的发展程度。管道代表了一个共同的含义。尽管软件工程师间可能存在重大分歧,关于如何进行探索,但普遍认为他们的方法较为随意,并且对更结构化的方法几乎没有任何共识。因此,地图中认为即兴探索的概念比探索本身更加成熟。
根据这种逻辑,从临时探索到单一式工具的各个组件都被逐步添加了。手动检查被描述为一种新兴做法,而不是一种工业化的做法,因为由于我们单一式工具的僵化往往迫使我们进行其他大量手动操作,如阅读代码。对于手动检查具体指的是什么,几乎没有形成共识,而且阅读代码等主题很少被深入讨论。虽然阅读代码对于包含数百万行代码的大型系统来说并不实用,但它具有高度的灵活性,可以适应任何上下文,因此被用来应对当前开发过程中的僵化问题。例如,当工具无法显示代码对象之间的联系时,软件工程师不得不自己阅读代码来寻找这些联系。
尽管今天的方法有些缺点,但仍有一点值得注意:有三点值得留意。
- 不论是技术层面还是业务层面的任何决策,都需要从系统中获取信息。
- 这些信息需要从系统中以某种方式整合,唯一的方法是借助能够提供良好开发体验的工具。
- 现在的开发人员花在写代码上的时间很少,大部分时间都在阅读,试图弄清楚下一步该怎么走。在软件工程中,最大的成本就是弄明白现有的系统,而我们却并没有为此优化工作流程。
在一个数据、自动化和系统丰富的世界里,我们不知何故陷入了即兴决策过程。造成这种情况的原因似乎是我们使用了通用工具,这显然符合工具供应商的利益,我们已经将理解系统的一部分过程交给了他们。并且,我们接受了构建工具是困难的——需要大量的资金和时间——至少,这就是工具供应商一直向我们传达的信息,他们强调他们的世界级解决方案和广受喜爱的工具可以带来极高的效率。软件开发是一场团队运动,工具供应商则像是裁判,同时提供场地和设备。
如果你想找一个反派,可能会选苹果,它将施乐帕克研究中心开发的个人计算概念封装在了一个物理盒子中,并通过封闭的应用程序(如苹果麦金塔)实现了这一概念。另一个选择可能是微软,它通过移除了物理盒子(任何x86架构都适用),将个人计算的概念卖给了大众。在这两种情况下,操作系统变得更像一个封闭的黑盒子,所销售的是完成任务的便利性,而非对发生过程的理解。尽管有漂亮的宣传册子,供应商并没有赋予人们理解和能力,反而将他们简化为依赖其所售工具的有限空间。
我们天生就想反抗这种情况。孩子们甚至在像 Minecraft 或 Roblox 这样的受限环境中也开始构建计算系统。如果我们想增强这些自然倾向,就需要去掉工具的限制,给予更多的自由。这就是以四项自由为表达形式的开源运动所提出的对抗所有这些控制的核心理念。
计算机本来是应该增强人类智力的,而不是为了方便而削弱它。我们所走的道路对人类的影响如此之大,以至于大多数专业的软件工程师甚至不再考虑自己构建工具。即使在开发论坛中,工程师在解决问题遇到工具的局限时,往往会选择放弃,转而求助于工具供应商。更糟糕的是,许多人甚至用搜索网络或夸大的论坛来寻找答案,取代了探索和理解。这在无尽的推销视频中得到了体现,这些视频声称能提供“所有编码问题的最佳答案”——Stack Overflow。
示例:尝试以传统方法优化数据处理流程为了进一步探讨这些想法,我们来看一个真实的例子。一家大型企业希望将核心数据管道的性能提高一个数量级(倍)。这从商业角度来说是必要的。在他们的情况下,这是主要的营销管道,通过该管道向数百万客户发送优惠信息,他们需要能够更快地响应市场变化。这个问题已经引起了高层的注意,并发起了一项倡议,以实现更快地响应市场变化的业务目标。
然而,经过几年的努力,数据在管道中的流动速度依然和以前一样。那么,为什么所有的努力到头来却毫无成效呢?人们对此问题非常关注,并为此投入了数百万美元寻求解决办法。
我们将使用他们手动绘制的高级架构图(图3)来解释环境。
图3 — 高级架构图。
该管道采用了一个基于Excel的内部特定领域语言(DSL)。程序员会在Excel表格中编写复杂的查询,这些查询会被自动转换为数据的数据库转换,并应用到数据上。最终数据会被存入一个SQL数据库(Oracle)和一个NoSQL数据库(Cassandra)中。这两个数据库作为低代码平台的输入,该平台还具备AI功能。此外,其他程序员会在该平台上编写特定于各种营销活动的脚本。
架构很简单,但无论怎么优化工程或查阅 Stack Overflow,都未能帮助改善其性能。尽管没有明确的性能指标,他们的调查表明,可能生成了过多的数据,这些数据最终并未被使用。
他们最好的猜测是“暗数据”,类似于“暗物质”——很多我们看不见但有影响的东西。使用DSL的团队无法看到实际使用情况。编写低代码脚本的团队只能看到数据库里的数据,但他们并不清楚哪些转换会影响到这些数据。
更复杂的是,这个低代码平台确实被认为实现了其帮助人们更快地编写代码的承诺,但它没有提供性能测量的支持,也没有提供追踪数据使用位置的功能或工具。由于这些观察,他们意识到因为各自独立工作,他们无法优化整个管道。他们明白,他们需要准确的数据血统来验证他们的信念,但没有适合他们特定技术组合或相关技术栈的工具或Stack Overflow网站(Stack Overflow)文章。在一个包含数万个变量的系统里,他们不得不花费数个人周的时间来手动追踪一个变量在管道中的使用。
总之,他们的评估方法包括使用由单体化的工具组成的发展经验,这些工具因方便性而限制了操作范围。他们通过手动检查来合成信息。例如,他们试图通过手动阅读代码来追踪某些变量在低代码脚本中的传递过程。他们将信息整合成对系统的手动视图。图3中的高级架构图就是一个例子。他们的对话基于这些手动视图以及一种信念,即这些视图能代表系统。这些对话使他们进一步相信“管道中生成的数据可能太多且最终并未被使用”。他们对系统进行探索的方式是即兴对话和与系统的交互。这种方法是无系统的,主要是基于不同团队中软件开发人员和架构师的好奇心。他们根据这些探索中形成的信念来评估并做出决策。结果是数百万美元的投资却没有任何明显的效果。
一个新路径:灵活开发在一个充斥着僵化工具、人工检查、临时性探索和直觉感觉的世界里,一群研究人员(后来在feenk找到了归属)问是否有可能走一条不同的道路来做决策?这需要挑战我们做决定的方式、我们对工具的看法,以及我们与系统交互的方法。他们逐步开发出了一条新的路径,被称为可塑性开发。为了更好地理解,让我们反过来重新审视决策制定的步骤。
我们放弃了那些通常定义我们开发体验的单一工具。相反,我们选择用 微工具 来构建体验,每个微工具都是为特定情景下的特定问题而设计的。通过使用我们的微工具,我们从 特定的代码 中综合出所需的信息,即直接、未经中介的系统数据流。这种综合化要求创建工具的成本足够低,不会产生任何实质性的影响,例如,可以在几分钟或几小时内而不是几天、几周或几个月内完成。制造微工具的过程需要尽可能工业化,理想情况下是通过使用工具包来实现。在测试领域,我们也看到了类似的情况。当创建一个测试的成本变得如此之低以至于可以忽略不计时,自动且工业化的测试被广泛采用。我们可以把测试视为一种将系统执行转换成红/黄/绿信号的微工具。同样的理念可以应用于任何工具,包括可视化或查询工具。
信息随后通过生成的视图来展示。这些视图直接来源于我们系统通过微工具处理的信息。无论信息展示在哪,都是实时直接从系统中提取的,而不是人工生成的。这就像用照片取代绘画作为一种记录方式一样。
生成的视图实际上是在模拟系统。我们的对话从“数据为中心”转变为“模型中心”的方式,这种方式是直接从系统生成并可以查询的。
我们的探索从即兴转变为更加正规的方法,我们称之为可塑开发。我们利用系统模型提出新的问题,随着我们进一步探索系统,不断创建新的微工具来合成新的信息,并将这些新信息整合进我们的系统模型。随着我们进一步探索,系统模型也变得越来越完善。这类似于地理勘探,我们从一张空白的纸开始,通过观察和使用微工具作为我们的经纬仪来逐步建模地形。
评估变得以假设为基础,我们根据直接从系统中创建的模型进行探索来做决定,这个模型不需要我们对其持有任何信念。我们不需要信任这些信息,因为我们可以直接对模型进行验证,而这个模型本身是从系统中实时生成的。
我们在图4中添加了一个新的实践到 Wardley 地图。
图4所示 — 决策的新路径
比如:我们要按照新路径来优化数据管道为了进一步探索这些想法,让我们回到一个真实世界的例子。一家大型企业希望将其中心数据管道的性能提升一个数量级。经过多年的努力,数据依旧以相同的速度通过管道。这导致了业务与工程团队之间产生了分歧,工程团队的压力越来越大,他们需要尽快找到一个解决方案。
当你发现自己的努力似乎对现实没有产生任何影响时,这表明你的系统模型可能与实际情况大相径庭。在这种情况下,你首先应该做的是提高自己理解实际系统的能力。
我们的第一个假设是,他们没有达到结果可能是因为他们对系统的理解不够到位。因此,我们首先问“系统是怎样的?”
在我们的情况下,我们想要一个工具来为我们提供系统的准确的视角。但是因为技术的组合和特定的业务案例,市面上并没有现成的工具能满足我们的需求。比如,在特定营销活动中使用了哪些数据点,这样的特定性也使得我们不得不自己动手做了。
在构建模型的过程中,我们发现第一个系统输出的数据与数据库中的数据不一致。这一发现让团队意识到存在一个他们之前并不知道的外部系统!如图5。
图5 — 调整后高级架构图。
这证实了我们之前的猜测,即他们对系统的可见性不完整也不准确,而且过去的决策都是基于这种感知。他们需要一个准确的系统概览。由于概览是细节的汇总,为了提供一个准确的系统概况,工具需要从最基本的部分开始,比如单个属性如何在管道中流转。
如图6所示,其中一个工具生成的视图展示了这样一个过程:一个单独的输入点(内部的蓝色点)影响了其他多个数据点(内部的红色点)。这些数据点随后成为了外部系统的输入点,并进而影响了更多的数据(外部的红色点)。最终,这些数据点成为了低代码系统中的输入点。
图6 — 一条数据谱系,展示通过管道的单个属性的数据流
如果不理解这个流程,任何试图优化整个系统的行为都可能无效且充满失败的隐患。他们正经历的正是这种情况。
基于属性级别的数据流转关系,我们构建了生成多个管道概览的工具。其中一个概览量化了沿管道产生的数据量,如图7所示的那样。
图7 — 管道的概要
对于每个系统,可视化展示了在其他系统中被使用或未被使用的属性组。红色部分对应于创建但以后未被使用的属性组。本质上,这些是“暗数据”,即未与其他部分互动但增加了系统“负担”的数据。
这些可视化结果展示了团队确实生成了一些未使用的数据,但更重要的是,这让他们意识到情况并非没有希望,并且即使系统是由异构且老旧的组件构成,也有可能获得整体了解。基于这些输入,他们决定重新构建管道,通过整合信息来减少不必要的转换。
从头说起,我们从一个最初的问题“我们的服务为什么变慢了?”开始,这又引出了一个问题“是否有不必要的数据生成?”,进而需要了解“如何传输数据?”。为了回答这些问题,我们开发了一套由微工具组成的系统,这些微工具提供数据管道中的实时信息。这些对话是基于如图6和图7所示的实况视图,而不是最初在图3中错误的观点。
这个案例表明,采用一种系统的方法进行探索是可行的,即通过构建系统模型,并利用这些工具来回答系统本身的问题。总共需要54个不同的微工具(即至少54个问题的答案)才能正确回答“是否生成了无用的数据?”这一核心问题。这仅需两人月的投入。与之前动辄投入数百人年和数百万美元的尝试相比,这至少提高了600倍。
这个例子对你来说怎么样?看到这个例子时,你可能会想:“他们怎么忽略了那个第三方系统?”或者说:“我们绝不会做这样的事情。”客户的工程师团队非常有能力,其中还包括了服务业整合领域的全球领导者。这些工程师都非常有资格,拥有学位和行业认证。然而,这个系统非常庞大,由多年来逐步构建的多个较小部分组成。一些人退休了,一些组件系统也被遗忘了。团队也被拆分成不同的小组,包括一个内部系统团队、一个数据库团队、一个低代码团队等,整体上没有一个清晰的概览。
尽管这可能看起来极端,但我们基于经验认为,高技能团队往往各自为战,难以协同,试图在一个对系统理解不够全面的模型下管理庞大的旧系统环境,这种情况很常见,甚至可以说是常态。我们并不对83%的数据和遗留迁移项目要么失败,要么超出预算或时间表的情况感到惊讶。真正让我们感到惊讶的是,竟然有17%的项目成功了。然而,如果这17%的数据是准确的,那么这些结果其实应该能在更快的速度和更低的成本下达成。
如果你有任何形式的遗留系统或资产,那么我们认为这个例子和你有关。测试方法是让工程团队提供系统模型。如果结果是手写的或 PowerPoint 图表(如图 3 所示),则要求与实际运行的版本进行对比。
不能直接让AI解决这个问题吗?2025年,大多数CIO谈到人工智能时,他们通常指的是诸如大型语言模型(LLM)和大型多模态模型(LMM)之类的特定变压器架构,这些架构通常存在于代码助手中。使用这些模型来协助开发工作完全没有问题(作者也这样做),但截至2024年12月的市场调研显示,代码助手可以帮助开发者提高效率高达1.55倍(即55%)。值得注意的是,这些数据来自市场调研,常常受到独立研究的质疑,后者认为效率提升可能低至1.05倍(即5%)。
通常,像这里描述的以模型为中心的方法,我们会看到显著的改进。正如上面的案例所示,改进达到了600倍(即60,000%)。由于缺乏可比较的基线,量化这种差异通常非常困难。即便有数据存在,往往也难以进行直接的比较,即一组未能找到答案或放弃,而另一组找到了答案。此外,由于延迟导致的机会成本通常没有被充分考虑。尽管变化显著,但由于样本量较小,我们仍不能排除运气、工程师技能或作者偏见的影响。
因此,我们无法具体量化更具灵活性的方法带来的影响,而是必须依赖我们的大量经验。然而,这两种方法,即使用AI模型和可塑性开发,并不是对立的,而是可以相互补充的。我们会在本书后面的章节中详细讨论这一点。
在这章里,我们讨论了问题与答案的角色。接下来的旅程中,我们会进一步探讨为什么这很重要。
我们都学到了啥?软件工程可以主要被视为不断变化系统中的决策活动。这一过程包括评估问题情况、系统探索、对话交流、综合信息并利用开发经验。
当前的做法常常依赖于凭感觉和临时性尝试的探索,采用手动、数据驱动的方法。此外,传统的软件开发工具往往是庞大且限制性的工具,导致需要手动核查。
灵活开发提供了一种替代方法,依赖于生成系统的实时系统视图。这些视图是通过为每个具体问题特别定制的上下文微工具获得。
我们提供了一个实际案例,展示了塑形开发是如何应用于优化一个之前难以改进的数据管道的过程。在案例研究中,仅用2个人月的时间解决了过去数百人年都无法解决的问题。虽然确切的改善程度难以量化,但经验表明,塑形开发可以在软件工程的问题解决中带来成倍的改进。
家庭作业练习:难度设置找一些你认识的软件开发的同事们,一起来讨论一下这些问题吧。比如以下问题:
- 我们是否同意,我们花费超过50%的工程时间试图通过阅读各种系统文档或资料来了解系统?
- 我们上次讨论我们怎样阅读代码是什么时候?我们讨论的是阅读的方法,而不是代码本身。
- 我们能否通过编程手段来检查性能问题?对于安全问题或业务领域事件,又有何方法?
- 我们是如何获取架构图的?这些图是手工绘制的,还是从系统的代码生成的?我们对这些图能够准确反映系统情况的信心如何?我们如何验证这一点?
—
软件工程的重新生态化共同學習,寫下你的評論
評論加載中...
作者其他優質文章