背景

最近经常会有人找我问一些非常有趣,但是又非常玄学的问题。这类玄学问题我指的是正常情况下明明能工作,现在却不知为何无法工作的情况。

这些问题往往和非常多的难以预料的因素(例如环境)有关。例如:为什么我无法将一个文件签入到git?

解决大部分玄学问题,往往需要我主动在他的电脑上进行大量操作、环境分析,才能知道到底是哪里对程序产生了影响。或往往需要我反复沟通数十条消息才能真正判断问题所在。而且这类问题,由于正常情况下是能工作的,所以非常难以通过Google和Stack Overflow解决。

后来我想,与其每次都花费大量时间帮别人解决问题,不如抽象出一套能够解决上述问题的通用方法,来让大部分人能够自行解决这些问题。

夹逼调试法由此诞生。

夹逼调试法

夹逼调试法,指的是通过两个方向共同限制作用,使得问题根源的可能范围集中在最小化的条件变化中。

夹逼调试法适用于解决:

平时或在理想情况下工作正常,而在某些环境中能够稳定工作不正常的错误。

执行方法

夹逼调试法的执行方法为:

首先你已知了一个环境中 E1,程序 P 出现了一个异常现象 A。

此时,你需要构建一个尽可能理想的环境 E2。所谓理想的环境,即:满足程序 P 不出异常现象的所有条件。

构建环境 E2 后,在 E2 中运行 P。

如果 P 出现了异常现象 A,则证明 P 本身存在设计缺陷。

如果 P 并没有出现异常现象 A,则证明是环境 E1 和环境 E2 的差异导致了 A。

此时我们需要探究是 E1 和 E2 的何种差异导致了A。

将 E1 环境进行过的配置操作流程与 E2 环境进行差异对比。得到一个差异集合 C = { D1, D2, D3 ... Dn }。且C不是空集。

分别将每个在 C 中的差异 D 去应用给 E1,使得E1 更加接近 E2。

在每个差异 D 应用后,在 E1 中重新运行 P。

如果 P 此时开始出现异常现象 A,则证明 D 可能是导致了 A 的原因。

如果 P 仍然没有出现异常现象 A,则证明 D 可能和 A 无关。

回滚差异 D。

分别将每个在 C 中的差异 D 去应用给 E2,使得E2 更加接近 E1。

在每个差异 D 应用后,在 E2 重新运行 P。

如果 P 仍然出现了异常现象 A,则证明 D 可能和 A 无关。

如果 P 此时不再出现异常现象 A,则证明 D 可能是导致了 A 的原因。

回滚差异 D。

此时,我们已经得知了是哪些可能的因素会导致 A 发生。

人类语言表述

对于一个发生的bug,我们可以构建一个理想环境,使得理想环境下不会发生这个Bug。然后列出出现Bug的环境和理想环境有哪些差异。

分别改变这些差异,使得理想环境和故障环境互相接近靠拢。

观察最终是哪一个差异能够真正导致故障。

备注

夹逼调试法,只能找到“可能的条件”。而不是“必要”、“充分”、”充分且必要“的。

这是考虑到条件的组合可能会影响结果。因此夹逼调试法只适用于需要快速定位可能的原因的情况。

例题1

已知我的电脑无法正常运行Spotify。请问是为什么?

首先构建一个理想环境。使用最新版Windows 10专业版,在一个全新的今年发售的电脑上全新安装。然后完成所有系统更新,确保国际网络畅通。并通过Spotify官网下载安装Spotify,然后启动Spotify。

此时大概率Spotify能够正常工作。此时我们开始比较故障环境和理想环境的差异:

  • 故障环境使用了中文操作系统,而理想环境使用了英文操作系统
  • 故障环境连接了中国网络,而理想环境使用了国际网络
  • 故障环境没有安装最新的系统更新,而理想环境安装了系统更新
  • 故障环境使用了Windows 10 N,而理想环境使用了Windows 10专业版
  • 故障环境是在某个盗版小网站下载的Spotify,而理想环境是在Spotify官网下载的Spotify
  • 故障环境里还额外安装了300多个其他软件,C盘只剩余3%的空间。而理想环境没有安装任何其它的软件,C盘剩余95%的空间

然后我们开始夹逼调试。从故障环境逼近理想环境开始。

  • 给故障环境切换为国际网络。观察发现:仍然不正常运行。
  • 给故障环境切换为英文操作系统。观察发现:仍然不正常运行。
  • 给故障环境安装最新的系统更新。观察发现:仍然不正常运行。
  • 给故障环境去Spotify官网下载Spotify。观察发现:仍然不正常运行。

然后此时继续从故障环境向理想环境逼近已经有些困难。我们转而从理想环境向故障环境逼近:

  • 给理想环境也额外安装故障环境安装的300多个其他软件。发现理想环境仍然正常。
  • 给理想环境从Windows 10专业版降级为Windows 10 N。发现理想环境不再正常。此时,Windows是否使用了带N的版本,为可能的原因。

之后我们再去故障环境验证这个原因:

  • 给故障环境切换为Windows 10专业版。此时观察发现:故障消失。

综上,我们得到了:Windows 是否是带N的版本,可能会影响Spotify的运行。

例题2

已知一个飞机的驾驶室里有10个开关和一个启动键。每个开关分别都对应着开、关两个位置。

我们曾经将10个开关全部扳到 开 位置,此时按下启动键,飞机就能成功启动发动机。

但是今天,我们试图启动飞机。但是飞机无法启动。已知此时10个开关全部都是 关 位置。你需要快速知道大概是为什么,飞机无法启动。

执行夹逼调试法。

首先将10个开关全部扳到 开,验证飞机确实能启动。

依次尝试关闭其中每一个开关。如果飞机不能启动了,证明这个开关对于飞机启动可能是必要的。

如果上述方法遇到障碍,或成本过高,或执行缓慢,则:

将10个开关全部扳到 关。验证飞机确实不能启动。

依次尝试开启其中每一个开关。如果飞机能启动了,证明这个开关对于飞机启动可能是必要的。