购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.2 适应度函数的类别

适应度函数有许多类别(我喜欢称这些类别为维度,并将在本章中同时使用这两个术语)。对我来说,这些维度应该指导开发人员为他们的软件系统定义最有用的适应度函数。适应度函数总是存在于这里所展示的维度的组合中,但要注意,并非所有这些类别的随机组合都是可能的或有意义的。

Ford、Parsons和Kua在他们的书中很好地描述了这些类别,我将在本章重复使用其中的大部分。我还扩展了他们的列表,添加了我认为重要的其他内容。

在创建和定义适应度函数和目标指标,以及在随后实施创建和验证目标指标的最终测试时,使用这些维度作为指导和输入是一个不错的主意,这样可以考虑到所有相关方面。你可以将这些维度看作一个目录,从中选择适合你的系统和上下文的正确组合(稍后将简要介绍)。正如在软件开发中一样,只使用那些能够为团队提供具体信息、方向和意义的类别。

接下来,我们一起来看一下六个必需的类别,以及四个可选的类别。

2.2.1 强制型适应度函数类别

以下六个类别对我来说是必需的,因为使用这些类别对于软件开发工作是有意义的。因此,如果在开发适应度函数、指标和测试时没有考虑这些维度,那么最终定义的适应度函数可能会缺少一些重要方面,导致其定义不够理想。

反馈是原子的还是整体的?

当创建测试指标时,测试涉及系统的多少部分?在现实世界中,某个类更像一个连续统一体而不是两种类别,为了便于理解,我们将这种连续统一体的两端视为两个不同的类别。

原子适应度函数只验证系统的部分或有限的方面。因此,一个积极的验证结果并不足以对整个系统的性能提供反馈,只会对系统的有限部分提供反馈。典型的例子包括执行静态代码分析,例如度量圈复杂度作为可维护性的指示,或者度量单元测试覆盖率作为可维护性和可测试性的指示。

另一方面,整体适应度函数提供更广泛的反馈。来自整体适应度函数的积极验证结果意味着系统的很大一部分按预期执行,并且终端用户可以按预期使用系统。整体适应度函数往往更难构建和维护。

什么会触发测试执行?

除了手动执行测试之外,通常还会通过特定的触发器自动执行测试,例如通过开发人员触发的CI工作流或预先安排的运行(例如每晚运行测试)。相比之下,持续适应度函数是持续评估的,独立于开发活动(例如对指标及其阈值的持续验证)。持续反馈通常与生产环境中执行的实际度量以及系统运行时收集的指标评估相关联。持续适应度函数通常也属于系统监控(工具)的技术领域,例如监控某个服务的响应时间时使用的可能就是此类适应度函数。

测试在哪里执行?

测试是在测试环境中执行还是在生产环境中执行?另一种选择是在持续集成/持续交付(CI/CD)流水线中运行测试(例如,直接在CI/CD系统的主机上度量单元测试代码覆盖率)。某些函数可以在测试系统中被评估(例如性能或负载测试)。在某些情况下,测试甚至可以直接从生产环境中派生出来。这些分类可能会有重叠,例如,性能测试在测试环境中运行,并且通过CI/CD流水线触发。此类别确定了测试在哪里执行,是否需要额外的硬件,以及测试是否会影响正在运行的生产环境。

指标类型

指标类型是一个相当明显的考虑因素。架构测试会产生什么样的值?它只是一个真/假陈述(“所有测试都通过”),还是产生一个数值?此外,你还应考虑所生成的指标是否将以时间序列的形式存储和可视化,并由此提供有价值的输出。

自动还是手动

手动执行某些测试可能很有用,在自动进行这些测试需要花费很多精力,成本太高或根本不可行的情况下,往往需要进行手动测试。例如,对法务需求的测试可以表示为适应度函数,但自动进行这种测试就没有意义了。 一般来说,软件架构师喜欢将事情自动化,这样就可以尽可能方便且频繁地运行测试。

质量属性要求

对于我来说,最重要的是定义软件系统的质量属性(也称为质量属性需求或质量目标)。一般来说,在开发软件架构时有三个关键驱动因素:功能需求、质量属性和约束条件。质量目标定义了事物需要达到的工作质量水平。它们概括了整个产品的功能需求如何良好地协同工作,并且说明了对系统的其他定性要求(如适应系统某个部分有多容易)。因此,根据Bass、Clements和Kazman的观点,质量目标在软件架构的开发中非常重要。 [2]

国际标准化组织(ISO)的25010标准提供了一个质量属性示例目录。它列出了产品质量的八个主要特征,然后将它们进一步细分为更具体的子属性(参见表2-1)。

表2-1:质量属性和子属性

表2-1:质量属性和子属性(续)

注:源自ISO/IEC 25010, ISO 25000( https://oreil.ly/Q3yst ,2022年3月28日访问)。

ISO标准并不是对软件质量特性进行分类的唯一方法;Hewlett-Packard还开发了另一种名为FURPS( https://oreil.ly/hAWgp )的体系(包括功能性、可用性、可靠性、性能和可支持性)。然而,在本章中,我将使用ISO的属性。

无论你在与利益相关者讨论质量目标时使用什么模板、目录或标准,都要记住,质量目标是系统架构开发的主要驱动因素之一,因此在我们努力定义适应度函数和指标时,它们也应该是主要驱动因素。

只有在对总体目标有重大影响的属性上花费时间和精力才有意义。因此,在2.7节中,与主要利益相关者统一质量目标并对其进行定义,是创建相关适应度函数及其指标的第一步。

2.2.2 可选适应度函数类别

接下来的这些类别可以提供额外的指导信息,并可能与你和你的系统相关上下文有关。我认为它们是可选的,因为它们并非总是相关的。其中某些类别通常与只在大型项目中才会出现的额外沟通和文档要求有关。

适应度函数是暂时的还是永久的?

如果某个适应度函数的使用和有效性受到设计限制,可以明确将该函数标记为临时函数;而其他适应度函数则被归类为“永久”函数。这里的“永久”是指该函数在设计时并没有特定的结束日期,并不是指它将“永远”存在:“永久”函数可以像软件开发中的其他事物一样被更改或废弃。

专门且持续时间较长的变更或重构活动就是临时适应度函数的一个很好的例子。当重构工作正在进行时,临时适应度函数和指标就会提供额外的帮助。一旦这项工作完成,它们就会退役。

适应度函数是静态的还是动态的?

静态适应度函数,或者更准确地说,静态适应度函数的指标,对目标指标有一个静态定义。然后根据这个静态指标进行验证。你已经在示例2-1和示例2-2中见过这样的适应度函数,例如我们检查了代码覆盖率是否始终高于某个静态值。

而动态适应度函数则是将目标指标定义在与另一个值相关的一定范围内。例如,你可以根据系统当前活跃用户的数量来定义系统响应时间的目标范围。在本例中,你可以根据在线用户数量(10 000~100 000名用户)定义目标响应时间范围为50~100毫秒。

对于这种动态定义,创建(自动化的)测试更为复杂。但与静态定义相比,这种定义也能更好地适应实际用例,因此可能会提供更有价值的输出,这取决于你的用例。

目标受众是谁?

适应度函数和指标的目标受众可能包括软件开发人员、运营和产品经理以及其他利益相关者。在需要额外文档和沟通的大型环境中,确定受众非常有用。提前了解目标受众对于决定如何以及在何处可视化输出并提供访问权限非常重要。

你的功能和指标将应用于哪些方面?

如果你有一个大型系统或多个系统,可能需要将适应度函数及其指标的有效性和执行范围限制在单个系统、子系统或服务上。这通常还伴随着额外的文档和沟通需求,这些需求存在于大型软件开发工作中。另外,你可能希望将给定的适应度函数限制在系统或子系统内的某种技术上,例如要求使用JavaScript编写的前端具有一种类型的代码覆盖率,而使用Java编写的后端具有另一种不同类型的代码覆盖率。

2.2.3 适应度函数类别:目录概览

表2-2和表2-3提供了强制型和可选型适应度函数的类别及其可能值,供你在创建第一个适应度函数时参考。

表2-2:强制型适应度函数的类别及其可能值

表2-3:可选型适应度函数的类别及其可能值

对适应度函数的分类有了一定的了解后,接下来让我们把它们应用到测试金字塔框架中。 gPM1kkmPD+L1YymfWmlPXLbqFno6t41nHsNFyB5Za1SB+i7m3IZbSrNVGKsPFYc/

点击中间区域
呼出菜单
上一章
目录
下一章
×