13 January 2016

(For an English version of the XY problem introduction please visit http://xyproblem.info/ ) 有人可能发现别人来问我问题时,我喜欢在回答前先反问一些 问题。而我问题时则会比较“啰嗦”。我这么做的目的是为了避免陷入到“XY问题(XY Problem)”中。这种做法大部分时候都能奏效;偶尔地,由于本人思维的局限而不能幸免。

所谓XY问题是指:

  1. 某人想解决问题X
  2. 他认为Y是解决X问题的方法
  3. 但他不知道Y怎么做
  4. 于是他去问别人Y具体怎么弄

XY问题的一个变种是:

  1. 某人发现了一个bug X,同时注意到现象 Y
  2. 他认为是Y导致的
  3. 但他无法解释Y是怎么发生的
  4. 于是他去问别人Y是怎么回事

例一:小明来问一个具体的expect(一种脚本语言)问题。如果我直接回答就落到XY问题的 陷阱里了。相反地,我先问清楚小明“究竟想干什么”:他是想要在脚本里ssh到远端执行一 个命令;因为以前见过用expect脚本来实现类似功能,所以想用expect来ssh并执行命令。 这属于典型的把“手段”当成“目的”。了解到此我就可以“答非所问”但真正解决问题:根本不 需要用expect,直接 ssh user@remote 'command arg ...'. 就可以。

需要注意的是:从不同层面考虑, 当前“目的”也只是实现更高层面目标的“手段”。还以上 例来讲,“ssh到远端并运行一个命令”是目的,“用expect”是达成那个目标的手段之一。如 果放到更大的背景下,可能目标是“在主机A上查询主机B上的LDAP数据”而“ssh到机器B上运 行ldapsearch”只是手段之一。如果小明问的是 “如何在A上查询B的LDAP数据”(或者我通过 反问了解到这一点),那么我的回答会是:根本不需要ssh(更别提expect了),直接在A上 运行ldapsearch并通过参数 -h B 指定B为LDAP服务器就行了。如果再往上追根朔源,则 “在A上查询B上的LDAP的数据”只是实现xxx目的的手段之一,实际可能有更简便的方法。

例二:小红问为什么PATH没问题但脚本有时会报找不到可执行程序X的错误。这属于用“自己 的分析”代替“实际问题”。小红没有介绍的背景是:出问题的脚本同时有数个实例在运行时 偶尔会报错说找不到X;经过检查后她认为“PATH没有问题,但不清楚为什么会找不到X”。如 果单纯去研究“PATH没错但脚本却找不到X”肯定是无功而返。但如果调查“某脚本同时运行好 几个实例时就会不定时地出现找不到X的情况”就可能很快发现问题是同时修改配置文件导致 的race condition。该脚本在运行时会去修改一个配置文件,删除里面的旧PATH并添加新 PATH(莫名其妙的奇葩设计,此处不深入批判)然后再source in。因为多个实例同时运行, 实例A修改完毕之后、导入之前,另一个实例B可能又删掉删掉了A刚刚添加的PATH。

“XY问题”的问题是直接排除了潜在的更好的解决方案甚至误导大家在错误的方向上努力。为 了避免XY问题,提问者应当先介绍问题产生背景及自己的“终极”目标然后再说自己采用的解 决办法和遇到的问题;而回答问题的人则最好先问明白提问者为什么要这么做(想达到什么 目的),对于提问者所声称的要打个问号。当然确定什么是“终极”目标、背景该说多少等等 也是一种能力,需要学习和锻炼。例二中如果能把背景恰到好处地限定“同时运行多个实例 时才会出现”,问题已经解决一半。如果完全没有并发方面的知识和经验则很难会想到要说 明一下有多个实例同时运行。



blog comments powered by Disqus