更多状态,更多错误:空指针、类型系统和 A/B 测试系统有什么共同点

2022-11-14   出处: Fernando‘s blog  作/译者:Fernando/Yilia


  这是关于软件工程的一个基本事实:你的程序可以处于的状态越多,bug 潜入的可能性就越大。
  考虑到相对于产品的大小,可以分配给测试给定版本的时间大致是恒定的。另一方面,可能的状态数量通常会以更高的速度增长,如果不小心管理,甚至会成倍增长。这意味着将会有越来越多的状态在每次发布时接受越来越少的测试时间。
  这篇文章探讨了空指针异常、类型系统作为控制可能状态的一种方式的重要性,以及一些在处理不当时可能导致状态爆炸的常见特性。

十亿美元的错误

  托尼·霍尔 (Tony Hoare) 以计算机科学中的两大思想而闻名:快速排序 (Quicksort) (1960) 和空引用 (null references) (1965)。作为一名出色的计算机科学家,他现在将空指针称为十亿美元的错误。
  为什么?想象一下,有一个函数,该函数将两个布尔变量作为输入,例如:calculate(a,b)。总共有 4 种可能的情况,这意味着我们可以轻松处理,甚至对每个情况进行单元测试:

expect(calculate(false, false)).toEqual(someValue1)
expect(calculate(false, true)).toEqual(someValue2)
expect(calculate(true, false)).toEqual(someValue3)
expect(calculate(true, true)).toEqual(someValue4)

如果输入变量可以为空怎么办?测试用例数增长到 9,是原始状态空间的两倍多。
如果有 3 个布尔变量怎么办?测试用例数从 8 个(无空值)增加到 27 个(有空值)。下表显示了几个值的差异:

number of bool arguments with nulls without nulls
3 27 8
4 81 6
5 243 32
6 729 64

  代码库是否具有反映此特定示例的功能是无关紧要的。关键是,空指针会使可能的状态数量激增,并且程序拥有的状态越多,它可能拥有的错误就越多。

类型系统

  为什么类型系统有用?本质上,它们是一种减少状态空间的方法。回到之前的例子。 假设使用的是 javascript,那么 calculate(a,b) 的参数实际上可以有 4 个状态,分别是:null、undefined、true 和 false,总共有 16 种状态。这是很多单元测试的案例。除非确实没必要,多数情况都会在函数里对undefined做检查,这样做的结果就是状态空间将扩大一倍。类型系统用作限制程序可能处于的状态的一种方式。可能的状态越少,意味着要测试的案例越少,这意味着质量更高,错误更少。

A/B 测试的危险

  A/B 测试系统作为提高产品使用率的一种方式非常有用,同时保持较低的功能风险。 但是,这带来了一个很大的风险:就像臭名昭著的空指针一样,A/B 测试系统如果处理不当,可能会导致可能的状态激增,根本没有足够的时间来测试。
  数学本质上是一样的。 如果正在运行一个功能(n=1)的A/B测试,那么对应程序有两种状态。 可以确信,经过足够的时间后,各自会有一半的用户处于A或B状态。如果有 n=5 的 A/B 测试怎么办? 这是程序的32个变量,因此只有 3.125% 的用户会登陆每个变量。
  你可能会争辩说我的数字是错误的,因为某些变量之间通常完全独立(例如,注册流程中的变量与结帐流程中的变量)。完全同意,我只是在说明一个事实,即管理不善的 A/B 测试计划可能会对产品质量产生不利影响。如果在一个相对较小的产品中进行了 100 次 A/B 测试,这很有可能会影响质量。

RBAC系统的危险

  如果构建企业软件,最终将需要一个角色管理系统(RBAC 代表基于角色的访问控制)。这个想法是,用户可以有一组分配给他们的角色,这些角色将决定用户可以做什么或不能做什么。
  在执行这些类型的系统时,允许非常小的权限粒度以最大限度地提高灵活性。 Admin 角色可以查看用户吗?用户的个人详细信息,用户的付款历史记录呢?性别?地址? 一种解决方案是为每一位信息创建一个非常具体的权限。
  知道“状态爆炸”问题,因此只定义了两个角色:管理员和普通用户。将所有细化权限映射到这两个角色。问题解决了,对吧?
  这在理论上可行,但需要非常小心,以确保每个用户仅拥有其角色授予的权限。 随着时间的推移,CS 和销售团队会收到来自客户的非常具体的请求,询问他们是否可以授予或删除权限,从而慢慢地将一个巨大的状态空间泄漏到产品中。
  正确管理 RBAC 系统的解决方案是监控“有效角色”的数量。我所说的有效角色是指实际角色组合的数量。例如,一位大客户可能拥有 Admin 角色,随着时间的推移会添加一些额外的权限。另一个大客户进来并要求为管理员提供一组不同的权限:与其自由分配权限,不如尝试看看是否可以创建一个适合两者的超级管理员角色。

写在最后

  软件工程师的工作不是编程,而是为真实的人制造解决实际问题的产品,并确保这些系统不会随着时间的推移而崩溃。管理复杂性是构建此类系统的关键。
  确定复杂性可能呈指数级增长的领域是能够管理不断增长的产品的关键。如果不这样做,可能会导致质量下降和开发时间延长。


声明:本文为本站编辑转载,文章版权归原作者所有。文章内容为作者个人观点,本站只提供转载参考(依行业惯例严格标明出处和作译者),目的在于传递更多专业信息,普惠测试相关从业者,开源分享,推动行业交流和进步。 如涉及作品内容、版权和其它问题,请原作者及时与本站联系(QQ:1017718740),我们将第一时间进行处理。本站拥有对此声明的最终解释权!欢迎大家通过新浪微博(@测试窝)或微信公众号(测试窝)关注我们,与我们的编辑和其他窝友交流。
213° /2135 人阅读/0 条评论 发表评论

登录 后发表评论