This post is a translation of Julia EvansHow to ask good questions. I personally like it a lot and think it’ll be a good idea to share with translation. She has acknowledged the translation but not endorsed or verified it.

这篇文章是 Julia Evans这篇博客文章的翻译。我觉得写得很不错所以翻译了这个版本。翻译得到了原作者授权,但没有审核或者背书。

提优秀的问题是一个软件开发时超级重要的技能。我在过去几年中做的越来越好(以至于我的同事还经常评论和提及)。以下的几点是我很受用的原则!

首先,我其实非常同意「你完全可以问很蠢或者不那么优秀的问题」。我自己就经常问别人比较蠢的问题,那些问题其实我自己可以 Google 或者搜索代码库就可以解决。虽然我大多数时候尽量避免,但是有时候还是问了很傻的问题,之后也不觉得是世界末日。

所以以下的策略并不是关于「你在提问之前必须要做这些事情,否则你就是一个坏人且应该自责」,而其实是「以下这些事情曾经帮我更好的提问和获得我想要的解答」。

什么算是一个优秀的问题?

我们的目标是问那种容易解答的技术概念的问题。我经常遇到这样的人,他拥有一堆我想了解的知识,但他不总是知道如何以最好的方式解释给我听。

但如果我可以问一系列好的问题,那我可以帮那个人有效地解释清楚他所知道的,并且引导他,告诉我我感兴趣的东西。所以我们来讲讲如何做到这一点!

陈述你所知

这是我最爱的提问技巧之一!这种问题的基本形式是:

  1. 陈述关于这个话题你目前的理解
  2. 然后问「我理解的对么」?

例如,我最近和一个人(一个非常优秀的提问者)讨论计算机网络!他说:「所以我的理解是,这里有一系列的递归 DNS 服务器……」。但那不对!事实上,递归 DNS 服务器是没有「一系列」的(当你访问递归 DNS 服务器的时候,这里只有一个递归服务器参与其中)。所以他事先陈述了他的目前的理解,这帮助我们很容易的就厘清了其中的工作原理。

我之前对 rkt 感兴趣,但并不理解为什么 rkt 跑容器的时候比 Docker 多占用了那么多磁盘空间。

但「为什么 rkt 比 Docker 占用更多的磁盘空间」感觉上不像该提的问题——我或多或少明白它的代码是如何工作的,但并不明白为什么他们要这么写。所以我向 rkt-dev 邮件组写了这个问题:「为什么 rkt 存储容器镜像的方式不同于 Docker?

我:

  • 写下了我对 rkt 和 Docker 是如何在磁盘上存储容器的理解
  • 提出了几点我认为的他们如此设计的理由
  • 然后就只问了「我的理解对么?」

我得到的答案都超级超级的有用,正好是我想要的。我在组织问题上花了不少时间,才得到我满意的方式,但我很高兴我花了这些时间,因为它帮助我更好的理解了来龙去脉。

陈述你的理解其实一点都不容易(它需要你花时间去思考你所知,并且理清你的思路!!)但是它很有用,而且让回答你问题的人可以更好的帮助你。

你的问题的答案应该是一个客观事实

我一开始的很多提问都有点模糊,比如「SQL 里面 join 是怎么工作的?」那个问题并不好,因为 join 的工作原理分好多部分!对方怎么可能知道我想了解的是哪一部分呢?

我喜欢问的那些问题,他们的答案是一个简单直接的事实。比如,在我们的 SQL join 的例子里面,一些以事实为答案的问题可能是:

  • Join 两个大小为 N 和 M 的表的时间复杂度是什么?是 O(NM)? 还是 O(NlogN) + O(MlogM)?
  • MySQL 是不是总是在 join 之前先对 join 的列进行排序?
  • 我知道 Hadoop 有时候会做 hash join——其他数据库引擎是不是也会使用这个?
  • 当我在一个有索引的列和一个未索引的列上做 join 的时候,我需要事先对未索引的列排序么?

当我问这样超级具体的问题的时候,对方不总是知道答案(但这没关系!!),但是至少他们明白我想了解哪种问题——比如,明显我对如何使用 join 不感兴趣,我想了解的是具体实现和算法。

敢于说出你不理解的地方

当有人给我解释一个东西的时候,他们常常会说一些我不明白的东西。比如,有人给我解释数据库的时候可能会说:「好,我们在 MySQL 里面使用了乐观锁,然后……」我完全不知道「乐观锁」是什么。所以,那就是一个理想的提问时机!:-)

学会打断对方,然后说「嘿,那是什么意思?」是一个超级重要的技能。我觉得这是一个自信的工程师的素质之一,而且是件很棒的事情。我经常看到一些资深工程师,他们经常提问要求清楚解释概念——我觉得当你越来越对你的技能自信的时候,这一点也变得更容易。

主动提问越多,我就越觉得请求对方解释这件事情很自然。事实上,在我解释事情的时候,如果对方不主动问题,我会担心他们不是在认真听。

同时这也创造了更多的机会来给回答问题的人承认,他们已经穷尽了他们所知。我经常碰到提问的时候对方不知道答案的情况。我问的人通常都比较擅长说「不,那个我不知道!」

指明你不清楚的概念

刚开始现在这份工作的时候我在数据组。在了解我的新工作职责的时候,里面全是这种词!Hadoop、Scalding、Hive、Impala、HDFS、Zoolander 等等。我之前可能听过 Hadoop,但基本上不知道以上任何单词的意思。里面有的词是内部的项目,有的词是开源项目。所以我就开始请别人帮我了解其中每一个概念的含义以及他们之间的关系。期间我可能问过这样的问题:

  • HDFS 是一个数据库么?(不是的,它是一个分布式文件系统)
  • Scalding 用到了 Hadoop 么?(是的)
  • Hive 用到了 Scalding 么?(没有)

因为实在太多了,事实上我为这些所有概念写了一个「词典」。了解这些概念帮助我找到了方向,以及在之后更好的提问。

自己做些调研

当我打出上面那些 SQL 问题的时候,我在 Google 里面搜索了「如何实现 SQL 的 join 语句」。点击其中一些链接之后我看到了「噢,我明白了,有时候有排序,有些时候有哈希 join,我都听过」,然后写下了我的一些更具体的问题。一开始先自己 Google 一番帮我提出一些稍稍更好一点的问题。

话虽如此,我觉得有的人太坚持「永远不要在自己 Google 之前提问」这件事——有时候我和别人吃午饭时候,好奇对方的工作内容,我会问一些比较基础的问题。这完全没问题!

但自己做些调研真的很有用,而且做足功课之后可以提出一系列很棒的问题,这真的挺有意思的。

决定谁是请教对象

这里我主要讨论的是问你的同事问题,因为我自己大部分时间都是这样。

我在问同事问题之前,会做以下考量:

  • 对对方来讲这是一个好的时机么?(如果对方正在处理一个紧迫的事情,很可能不是)
  • 我问这个问题节约的时间是不是值得我提问所花的时间?(如果我提问需要5分钟,可以节约我2小时的时间,那太棒了 :D)
  • 对方需要花多少时间来回答我的问题?(如果我有个需要半小时时间的问题,我可以和对方预约一个之后的一整块时间;如果我只是有个小的问题,可能我就会立刻就问)
  • 对方是不是在这个问题上太资深了?我觉得总是问那些对某个话题最在行和资深的人,是挺容易的陷进去的一个误区。但是常常去找那些稍微不那么资深的人会更好——他们常常可以回答你的大多数问题,回答问题的压力也分散了,而且他们还可以有机会展示他们的知识(这一点很棒)。

上面的原则,我也不总是搞的清楚,但是考量一下他们的确帮到我很多。

另外,我经常花更多时间问离我近的人问题——他们每天和我交流最多,我可以很方便的问他们问题,因为他们已经有了我做的工作的背景知识,也很容易给出建设性的答案。

ESR (Eric Steven Raymond)写的「如何聪明的问问题」是一篇流行但挺刻薄的文章(它开头就有「我们叫这样的人怂货」这样的糟糕语句)。这是关于在互联网上向陌生人提问的。在网上向陌生人提问是一个超级有用的技能,也可以给你很有用的信息,但它也是提问的「困难模式」。你的提问对象不了解你的处境,所以你需要以成倍的耐心去陈述你想了解什么。我并不喜欢 ESR 的那篇文章,但是它讲了一些有价值的东西。其中「如何有建设性地回答问题」一章其实非常棒。

问那些可以揭示隐藏知识的问题

以提问的方式来揭示隐藏的假设或知识是一种高级的提问技巧。这类问题其实有两个目的,其一是为了获得答案(可能有些信息是一个人知道但另外的人不知道的),其二是为了指出其中隐藏的信息,分享出来有好处。

Etsy 的 Debriefing facilitation guide 其中的「提问的艺术」一章是在讨论突发事件的背景下,对此的一个精彩介绍。以下是来自其中的一些问题:

当你怀疑这类失败发生的时候你会寻找什么迹象?
你怎么判断一个「正常」的情况?
你怎么知道数据库下线了?
你怎么知道你需要报告给哪个组?

这类(看起来挺基本,但却并不明显的)问题,在那些有些权威的人问出来的时候特别有效。我特别喜欢那种情况,就是一个主管或者高级工程师问类似「你怎么知道数据库下线了」这样的基本但却重要的问题,因为这时候会让不那么有权威的人之后有条件来问同样的问题。

回答问题

André Arko 的如何为开源软件做贡献文章里面,我最喜欢的一部分是:

现在你读完了所以所有的 issues 和 pull requests,开始寻找你可以回答的问题了。用不了多久你就会发现有人在问之前回答过、或者在你刚刚读过的文章里面回答过的问题。回答这些你可以回答的问题。

如果你刚开始了解一个小的项目,回答他人的问题是一个非常棒的强化你的知识的方法。每当我第一次回答一个关于某个话题的问题的时候,我都感觉「噢天呐,万一我的答案是错的呢?」不过一般我都可以回答正确,然后我就会觉得更了解了这个话题一些。

问题也是一大贡献

好的问题也可以是对社区做的一大贡献!我之前在 Twitter 问了一堆关于 CDN 的问题,然后在我的文章里面写出了总结。很多人告诉我他们很喜欢那篇文章,我觉得我提那些问题不只是帮到了我,也帮到了许多人。

有很多人很喜欢回答问题!我认为提出好的问题也是一件你可以为社区做的很棒的事情,不只是「提出好的问题,让对方从非常不爽,变得只是有点不爽」而已。