软件熵解释:原因、影响和补救措施

已发表: 2022-03-11

本文面向对软件熵是什么、对他们工作的实际影响以及促成其增长的潜在因素感到好奇的软件开发人员或项目经理。

主要目标是建立对软件熵的认识,因为它是所有形式的软件开发中的一个因素。 此外,我们探索了一种可以为软件熵分配具体值的方法。 只有通过量化软件熵并观察其在连续发布中的增长,我们才能真正了解它对我们当前目标和未来计划构成的风险。

什么是软件熵?

软件熵得名于现实世界中熵的主要特征:它是一种衡量混沌状态的指标,它要么保持不变,要么随时间增加。 换句话说,它是衡量软件系统在改变它时内置的固有不稳定性的指标。

不幸的是,软件熵很少得到应有的重视。

在从开发团队中拉出某人、过早开始开发周期或实施“快速修复”(事实上,这是最有可能增长的时刻)时,都没有考虑到这一点。

软件开发是一门艺术和一门行业,其核心构建块定义不明确。 建造者使用水泥和钉子,而软件开发人员则使用逻辑断言和一组假设。 这些不能拿在手里检查,也不能按八分之一英寸来订购。 尽管不经意的观察者可能很想将软件开发与构建进行比较,但除了一些表面上的相似之处之外,这样做会适得其反。

水平线的图像,随着每次迭代变得越来越混乱,越来越不像线

尽管存在这些困难,我们仍然可以制定指导方针,使我们能够了解软件熵的来源,衡量它对我们的目标构成的风险程度,以及(如果有必要)可以采取哪些措施来限制它的增长。

建议的软件熵定义如下:

E = IC / S

其中I来自上一次开发迭代期间引入的意外问题的数量,C 是现在对系统实施更改导致新I > 0 的感知概率,S 是下一次开发迭代的范围。 一般来说,E 值低于 0.1 被认为是好的。 0.5 的 E 被认为是高的,高于 1.0 的值是压倒性的。

开发迭代的概念是我们理解软件熵不可或缺的一部分。 这些是从系统的一种行为到另一种行为的活动循环。 我们在软件迭代期间为自己设定的目标称为其范围。 在软件开发中,此类周期涉及修改或扩展软件的底层代码。

对代码的所有修改都发生在开发迭代中,即使执行它们的人不这么认为。 也就是说,那些以使用“快速而肮脏”的方法构建系统而自豪的小型组织——很少或根本没有收集需求或分析——仍然使用开发迭代来实现他们的目标。 他们根本没有计划。 同样,即使修改后的系统的行为在某种程度上偏离了我们的意图,它仍然是通过开发迭代来实现的。

事实上,发生这种情况的风险正是我们对软件熵的认识想要解释的,而我们测量它的愿望是为了限制它。 那么,实际上,我们可以如下定义软件熵。

任何给定的系统都有一组有限的已知未决问题 I 0 。 在下一次开发迭代结束时,将有一组有限的已知未决问题 I 1系统的固有熵指定了我们对 I 1的期望可能与其实际值有多大的差异,以及该差异在随后的迭代中可能会增长多少。

软件熵的影响

我们对软件熵影响的实际经验取决于我们如何与相关系统交互。

用户拥有软件的静态视图; 他们关心它现在的行为,而不关心系统的内部结构。 通过执行预定义的操作,用户假设软件将以相应的预定义行为进行响应。 然而,用户最不准备推断他们正在使用的软件中的熵水平。

软件熵与变化的概念相关联,在静态系统中没有任何意义。 如果没有改变系统的意图,我们就不能谈论它的熵。 同样,一个尚不存在的系统(即下一次迭代实际上是其存在的第一次)没有熵。

从用户的角度来看,软件可能被认为是“有缺陷的”,但如果在随后的迭代中,软件开发人员和管理人员按计划实现了他们的目标,我们必须得出结论,系统中的熵实际上非常低! 因此,用户的经验几乎不能告诉我们关于软件熵的任何信息:

  • 软件开发人员对软件有一个流畅的看法。 他们关心一个系统当前如何运作,只有在它必须改变的情况下,他们关心它如何工作以制定适当的策略的细节。

  • 经理可能对软件有最复杂的看法,包括静态和流动的。 他们必须在短期的紧急情况与进一步延伸到未来的商业计划的需求之间取得平衡。

这两个角色的人都有期望。 每当这些期望被破坏时,软件熵就会显现出来。 也就是说,软件开发人员和管理人员尽最大努力评估风险并为他们制定计划,但是——不包括外部干扰——如果他们的期望仍然令人失望,只有这样我们才能谈论软件熵。 它是一只看不见的手,它破坏了不在范围内的组件交互,导致生产服务器莫名其妙地崩溃,并扣留了及时且具有成本效益的修补程序。

一个复杂系统的图像许多元素和连接

许多具有高熵的系统依赖于特定的个人,特别是如果开发团队中有初级成员。 这个人拥有这样的知识,如果没有他的“宝贵”投入,其他人就无法完成他们的任务。 它无法在标准 UML 图表或技术规范中捕获,因为它由异常、预感和提示的混合体组成。 这种知识不依赖于逻辑一致的框架,因此很难(如果不是不可能的话)转移给其他任何人。

让我们假设,通过极大的决心和努力,这样一个组织能够扭转局面并稳定其 IT 部门。 情况似乎有所改善,因为当软件开发陷入停顿时,任何进展都是令人鼓舞的。 然而,在现实中,与在熵仍然很低的情况下触手可及的崇高目标相比,所达到的期望很低,取得的成就也很乏味。

当软件熵压倒一个项目时,项目就会冻结。

不能有更多的开发迭代。 幸运的是,这种情况不会一蹴而就。 向悬崖边缘缓慢而陡峭的行进是每个系统都会经历的事情。 无论第一个版本的组织和效率如何,在连续的开发迭代中,它的熵——以及因此出现意外出错的风险——都会增加,除非采取特定步骤来防止它。

软件熵不能减少。 就像现实世界中的熵一样,它只会增长或保持不变。 起初,它的影响可以忽略不计。 当它们开始出现时,症状很轻微,可以被掩盖或忽略。 但是,如果一个组织只是在软件熵成为项目中的主要风险时才试图对抗它,那么它会遗憾地发现它的努力是徒劳的。 因此,当软件熵的程度较低且不利影响最小时,对软件熵的认识是最有用的。

这并不意味着每个组织都应该投入资源来限制其产品中熵的增长。 今天开发的许多软件——尤其是面向消费者的软件——的预期寿命相对较短,可能只有几年。 在这种情况下,它的利益相关者不需要考虑软件熵的影响,因为在整个系统被丢弃之前它很少会成为一个严重的障碍。 然而,考虑软件熵的影响的理由不那么明显。

考虑运行互联网路由基础设施或将资金从一个银行账户转移到另一个银行账户的软件。 在任何给定时间,生产中都有该软件的一个或多个版本,并且可以以相当高的准确性记录它们的集体行为。

系统的风险承受能力是衡量从一次开发迭代到下一次开发迭代我们可以轻松允许的意外行为的数量和类型。 对于刚刚提到的系统类型,风险承受能力远低于路由电话的软件。 反过来,该软件的风险承受能力低于驱动许多商业网站购物车的软件。

风险容忍度和软件熵是相关的,因为软件熵必须最小,以确保在下一次开发迭代期间我们将保持在系统的风险容忍度内。

软件熵的来源

软件熵源于缺乏知识。 它源于我们的共同假设与现有系统的实际行为之间的差异。 这一事实解释了为什么软件熵仅在修改现有系统的情况下才有意义; 这是唯一一次我们的缺乏理解会产生任何实际影响。 软件熵在一个系统中找到了最肥沃的土壤,其细节无法被一个人理解,而是分散在开发团队中。 时间也是一个强大的知识擦除器。

代码是一系列逻辑断言的表达。 当软件的行为(以及它的代码)不符合它打算表达的逻辑时,我们可以说它的固有熵。 这种情况可以通过三种方式出现:逻辑是众所周知的并且与其表达有分歧,对代码要表达的逻辑有多种理解,或者逻辑不为人所知。

知识匮乏、发散逻辑、未知逻辑示意图

  • 第一种情况——逻辑是众所周知的,但与当前的表达方式不同——是最容易解决的,但也是最不常见的。 只有由两个参与者(一个开发人员和一个负责业务计划的人)维护的非常小的系统才属于这一类。

  • 第二种情况——逻辑不为人知——很少见。 出于所有意图和目的,开发迭代甚至无法开始。 如果在某个时候所有利益相关者都同意,那么他们很可能会面临第一种情况。

人类的思维解释它的经验,有效地过滤和修改它们,试图将它们融入个人框架。 在缺乏有效的开发习惯(基于自由交流思想、相互尊重和明确的期望)的情况下,对于系统当前如何运作的解释可能与团队成员一样多。 团队对当前开发迭代的目标本身可能存在争议。

许多开发人员通过加强自己对他们的需求以及系统“应该”如何组织的独特理解来保护自己免受这种情况的影响。 另一方面,经理和其他利益相关者可能会在不知不觉中寻求改变其他团队成员的假设,这是一种错误的尝试,以使他们自己的生活更轻松。

我们现在已经找到了最常见的软件熵来源:对系统要表达的逻辑有多种不完整的解释。 由于这种逻辑只有一种表现形式,因此这种情况从定义上讲是有问题的。

这种缺乏知识是如何产生的? 无能是一种方式。 正如我们已经看到的那样,对下一次开发迭代的目标缺乏共识是另一回事。 但还有其他因素需要考虑。 一个组织可能声称采用一种开发方法,但随后随意放弃了它的部分或全部方面。 然后,软件开发人员的任务是完成模糊的任务,通常可以解释。 实施改变其开发方法的组织特别容易受到这种现象的影响,尽管它们绝不是唯一的。 管理层不知道或无法解决的个人冲突也可能导致期望和结果之间的危险分歧。

我们失去关于产品的技术知识还有第二种更重要的方式:转移。 即使对于最精通的作家来说,在纸上捕捉技术知识也是一项挑战。 原因是转录什么如何转录同样重要。 如果没有适当的纪律,技术作家可能会记录太多信息。 或者,他们可能会做出导致他们忽略要点的假设。 生成后,技术文档必须仔细更新,这对于许多几乎在文档一写完就忘记跟踪的组织来说是一个困难的提议。 由于这些困难,技术知识很少单独以文档形式传递,而且还以配对或其他形式的密切、人与人之间的互动形式传递。

每当积极的参与者离开开发团队时,软件熵就会突飞猛进。 他们随身携带了大量宝贵的专业知识。 复制这种专有技术是不可能的,并且接近它需要相当大的努力。 然而,只要有足够的注意力和资源,就可以保留足够的知识,从而可以最小化系统熵的增长。

熵还有其他来源,但这些来源相对较小。 例如,软件腐烂是系统意外受到环境变化影响的过程。 我们可以想到它所依赖的第三方软件(例如库),但软件腐烂还有其他更隐蔽的原因,通常是由于系统所基于的假设发生了变化。 例如,如果系统在设计时对内存的可用性进行了某些假设,那么如果可用内存减少,它可能会在意想不到的时刻开始出现故障。

如何计算熵:为 C、S 和 I 赋值

I 是软件系统中未解决的行为问题的数量,包括缺少承诺的功能。 这是一个已知数量,通常在 JIRA 等系统中进行跟踪。 I 的值直接来源于它。 I是在上一次开发迭代中被放弃或不完整的“工作单元”的数量,以及由新引入的和意外的行为问题导致的工作单元的数量。 因为I被算作工作单元的数量,所以我们可以将它与 S 的值联系起来,S 是相同工作单元中下一次开发迭代的范围。 “工作单元”的确切组成取决于开发方法。

C 是感知概率,即当范围内的工作单元已经实施时,下一次迭代中实际未解决问题的数量 I1 将大于现在的估计。 该值位于域 0 <= C <= 1 中。

有人可能会争辩说,概率 C 正是软件熵旨在衡量的。 但是,该值与我们对软件熵的测量之间存在根本差异。 某些事情会出错的感知概率正是:它不是一个真正的价值。 然而,参与项目的人的感受是关于项目稳定性的宝贵信息来源,这一点很有用。

范围 S 考虑了建议更改的幅度,并且必须以与 I 相同的单位表示。更大的 S 值会降低熵,因为我们正在增加建议更改的范围。 虽然这听起来可能违反直觉,但我们必须记住,熵是衡量系统发展如何可能无法满足我们期望的量度。 仅仅说熵是引入问题的机会的量度是不够的。 我们自然会尝试和预测风险,并在我们的计划中考虑它们(因此在我们对 I1 的估计中,它可能会增加超过0 )。 显然,我们对承担较大的变更范围越有信心,可以说系统中的熵就越少——除非那些计划变更和/或执行变更的人不称职。 然而,这种可能性可能反映在I的当前值中。

请注意,我们不需要尝试指定 I 1的实际值与其期望值之间的差异大小。 如果我们在制定计划时假设我们的计划是正确的,那么假设我们可以预测结果不符合我们期望的程度也是不合理的; 我们只能指定它不会的感知机会 C。 然而,实际值 I 1与其期望值的差异程度是以导出值I的形式在下一次迭代中计算熵的重要输入。

理论上,I 有可能是负值。 然而,在实践中,这种情况永远不会发生; 我们通常不会意外地解决问题。 I的负值不是一个令人欣慰的信号。 他们暗示计算熵的方法是有缺陷的。 当然,可以通过采取具体措施来减少软件熵的增长,如下所述。 然而,在这种情况下,不应该假设负值,因为我们总是将我们的期望融入我们的设计中。

一个图像的四个版本的图像,每个连续版本都包含更多错误

C 是一个主观值。 它存在于开发迭代参与者的脑海中,可以通过轮询他们并平均结果来推断。 应该以积极的方式提出这个问题。 例如: “在 0 到 10 的范围内,10 最有可能,您如何估计团队在这次开发迭代中实现其所有目标的机会?”

请注意,问题是针对整个团队的目标而不是子集提出的。 响应为 10 表示 C 值为 0,而响应为 7 表示值为 0.3。 在较大的团队中,每个响应可能会根据相关因素进行加权,例如个人参与项目的时间以及他们实际花费了多少时间。 然而,能力不应成为衡量答复的一个因素。 不久之后,即使是团队中的初级成员也会感觉到它在实现目标方面的有效性。 足够大的团队可能希望在平均剩余部分之前丢弃报告的最高值和最低值。

询问专业人士他们的团队失败的可能性有多大是一个敏感且具有挑衅性的提议。 然而,这正是任何希望量化熵的组织需要提出的问题。 为了确保诚实的回答,参与者应该匿名给出他们对 C 的估计,而不用担心受到影响,即使他们报告的值非常高。

S 必须在与I相同的“工作单元”中分配一个值,因此高度依赖于开发方法。 对于采用敏捷方法的团队来说,故事似乎是 S 和I最明显的“工作单元”。 在这种情况下,开发迭代的范围跨越了每个定期计划的发布到生产中,无论是次要版本还是主要版本。 我应该量化为在发布前的每个 sprint 中未成功完成的故事数与发布后出现的意外问题导致未来 sprint 中包含的故事数的总和。

请注意,我们不将修补程序或其他未计划的生产版本视为定义开发迭代的范围,也不应从I中减去任何相关的故事。

这种方法的困难在于,必须先进行一段时间的发现和分析,然后才能将错误分解为故事。 因此,I 的真实值只能在延迟后定义。 此外,对 C 的轮询自然会在每个 sprint 开始时发生。 因此,获得的结果必须再次在整个发布的跨度上进行平均。 尽管存在这些困难,但任何采用敏捷方法方面的团队都可能发现故事是量化 S(因此也是I )的最准确单位。

今天还有其他开发方法在使用。 无论采用何种方法,测量软件熵的原则都是一样的:软件熵应该在发布到生产之间进行测量,S 和 I 应该在相同的“工作单元”中测量,C 的估计应该从直接参与者那里获取。一种不具威胁性且最好是匿名的方式。

减少 E 的增长

一个系统的知识一旦丢失,就永远无法恢复。 因此,不能减少软件熵。 我们所能做的就是抑制它的增长。

在软件开发过程中采取适当的措施可以限制熵的增长。 敏捷开发的结对编程方面在这方面特别有用。 因为在编写代码时涉及到多个开发人员,所以分发了基本细节的知识,并减轻了离职团队成员的影响。

另一个有用的做法是制作结构良好且易于使用的文档,尤其是在采用瀑布方法的组织中。 此类文档必须以每个人都理解的严格和明确定义的原则为后盾。 依靠文档作为主要交流手段和保护技术知识的组织非常适合这种方法。 只有当没有关于如何编写和使用内部书面文档的指导或培训时——在使用 RAD 或敏捷方法的年轻组织中经常出现这种情况——它们的价值才会受到质疑。

有两种方法可以减少系统中熵的增长:执行旨在减少I的更改或执行旨在减少 C 的更改。

第一个涉及重构。 旨在减少 I 的操作在本质上往往是技术性的,读者可能已经熟悉了。 必须进行开发迭代。 此迭代中旨在减少熵增长的部分不会带来任何切实的商业利益,同时会消耗时间和资源。 这一事实通常使减少熵的增长在任何组织中都成为一种硬推销。

降低 C 的值是一种更有效的策略,因为效果是长期的。 此外,C 是对 I 与 S 比率增长的重要检查。降低 C 的行动往往集中在人类的行为和思维上。 尽管这些行动本身可能不需要开发迭代,但随着参与者接受并适应新程序,它们将减慢后续迭代。 随着项目参与者和利益相关者的不同目标突然暴露出来,就应该进行哪些改进达成一致这一看似简单的行为本身就充满了危险。

包起来

软件熵是更改现有软件将导致意外问题、未实现目标或两者兼而有之的风险。

尽管在首次创建软件时可以忽略不计,但软件熵会随着每次开发迭代而增长。 如果任其发展,软件熵最终将导致进一步的发展停滞。

然而,并不是每个项目都应该考虑软件熵的影响。 在熵产生明显和有害影响之前,许多系统将停止生产。 对于那些生命周期足够长以至于熵构成可信风险的人来说,建立对它的认识并衡量其程度,虽然仍然很低,但提供了一种确保发展不会过早中断的方法。

一旦系统完全被软件熵的影响所淹没,就无法再进行任何更改,开发基本上就结束了。