【外评】发现 bug 的快乐阶梯

这篇文章的主要内容是我在发现软件 bug 时最开心的时刻,以及我如何努力将快乐最大化。

我决定把它结构成一个阶梯。阶梯越高越好。

阶梯

第 0 步 – 错误存在,但你从未发现它

用户很恼火,但还是绕过了它。我们都曾使用过一些行为怪异的软件。也许这种行为并没有恼人到让你联系任何人。也许你确实在某个地方报告了它,但它从未被正确的开发团队发现。这种 bug 会让您在使用软件时少一些乐趣。这种错误太多的话,用户就会放弃你的软件,转而使用其他软件(如果可以的话)。

第 1 步 – 用户向您报告错误

某个软件出现了令人讨厌的故障,用户设法向您报告了这一情况。既然用户都知道了,你就已经惹恼了一些人。也许损失了一点声誉,也许损失了一点生意。错误偶尔会发生,但如果经常发生就不好了。

第 2 步 – 自动记录/警报/图表告诉您错误信息

在很多方面,这与上述步骤类似。主要区别在于速度。无论你有什么自动化设备,都能在几分钟内提醒你。而用户报告可能需要数小时或数天才能到达您的手中。了解得越早,修复得就越快。也许你很快就会发现,在许多用户还没有遇到错误之前,你就已经回滚了。

第 3 步 – 通过活泼度/准备度探针捕捉错误阻止部署

在这一步中,我想象有一些自动化的先决条件阻止变更上线。这是用户没有发现漏洞的第一步。这很好。这么晚才发现错误的坏处是,它很可能会阻塞你的部署管道,因此你的团队需要在正常工作继续之前转移焦点来修复或撤销错误。

第 4 步 – 在功能标志/黑暗启动/其他

后面的手动测试过程中,我非常喜欢功能标志。因为代码在功能标志后面,所以能够快速投入生产,这非常好。用户不会看到错误。不会阻塞部署管道。与阶梯上更高的步骤相比,这是一个稍慢的反馈循环,而且需要手动测试。尽管如此,如果大部分错误都能在这里得到解决,那我们的处境就相当不错了。

第 5 步 – 在较慢的自动测试过程中(也许是集成测试)

我将所有需要几分钟运行的测试都归入这一步。在这里捕获错误相当不错。步骤 4 的所有优点:不影响用户,不堵塞管道。此外:没有花费人工。缺点是我可能需要等待很长时间才能得到这个结果。也许在等待的过程中,我还去喝了一杯,吃了点零食。所有这些都会导致我忘记当时的工作环境。

第 6 步 – 在快速自动测试期间(单元测试或其他任何快速测试)

我喜欢在工作时持续运行单元测试。理想情况下,如果语言支持,我可以在打字的同时运行测试(特别值得一提的是 wallabyjs.com/,它可以在 javascript 中实现这种连续测试)。这样做的真正好处是在积极思考代码的同时发现错误/边缘情况。在创建代码和了解其后果之间,我无需等待大量时间。我的流程没有中断。

第 7 步–在编码时,因为类型系统

我所说的这一步的例子可以是一个接受 int 的函数。在大多数语言中,如果我尝试向函数传递浮点数,就会出错。现在,类型系统有可能避免了数据丢失导致的错误。在很多方面,这与步骤 6 非常相似。主要优点是不需要维护测试,因此没有开销。

步骤∞–由于设计的原因,代码中不可能存在错误

很大程度上是步骤 7 的延续,但在这种情况下,我首先不会遇到错误。举个例子:想象一下你正在表示一组用户可以做出的选择。假设在我们的示例域中,用户必须始终至少有一个选择。在大多数语言中,我们可以将其建模为一个字符串列表。我们可以确保自己勤于测试,这样就能在第 4 步之前发现错误。但是,如果我们将其建模为一个新的类型,其构造函数中包含 “1 个或多个选择”,那么我们就永远无法创建一个无效的列表。

在一些 “启发式伪代码 ”中,它可以是这样的:

type UserChoices []string

func New(firstChoice string, extraChoices ...string) UserChoices {
	// Construct the object somehow
}

// Usage

New("up")
New("up", "down", "left", "right")

这种设计没有提供构造空列表的方法,因此我们可以更有把握地确保空列表不会以某种方式潜入代码中。这有助于减少我们需要编写的测试。但值得注意的是,在某些语言中采用这种设计要比其他语言困难得多,因此并不总是合适的。不要与你的语言作对。

你能做什么?

尽你所能攀登阶梯,但请记住:没有一个系统是完美无缺的。确保你有层次。也许你在第 6 步时稍有疏忽,错过了一些错误,但你很好地利用了功能标志,并在第 4 步时找到了自己的立足点。

我的建议是,看看阶梯上的步骤,考虑一下你的工具和流程中是否缺少任何可以帮助你在这一步捕捉错误的东西。

以下是您可以问自己的一些示例问题:

  • 您是否了解用户如何使用软件?(第 0 步)
  • 您是否有方便用户报告错误的方法(第 1 步)
  • 如果您有监控功能,是否有一些肯定表明存在错误的东西可以发出警报?(第 2 步)
  • 是否有一种烟雾测试可以在容器投入使用前启动时运行?(第 3 步)
  • 您是否可以开始使用功能标志&在 prod 中对标志背后的代码进行一些手动 QA?(第 4 步)
  • 您是否需要进行一些与真实数据库交互的集成测试?(第 5 步)
  • 您能否在团队中举办一次关于编写快速、可靠的单元测试的研讨会?(第 6 步)
  • 您是否在代码中很好地模拟了您的领域?你是否有一些可以成为类型的基元? 提示:搜索有关 “基元痴迷 ”的博客)(第 7 步 & ∞)

这份清单既非教条,也非详尽无遗。请根据自己的实际情况做有意义的事情。但一般来说,任何能帮助你尽早发现错误的方法都是好的。

本文文字及图片出自 Ladder of bug discovery joy

你也许感兴趣的:

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注