译者 | 刘涛
审校 | 重楼
作为一个编程社区,freeCodeCamp为众多对自身所写代码存在疑问的编程爱好者提供了强而有力的帮助。然而,尽管直接给出答案然后继续推进这种方式看起来颇具吸引力,但实际上,这种做法对编程爱好者的学习进程是有害的。这其中的主要原因在于:
当直接给出答案时,编程爱好者会失去那种“恍然大悟”的瞬间。这剥夺了他们通过独立思考得出结论的机会,使得他们以最小的努力甚至无需过多思考就能取得进步。
那么,如何用最合适的方法帮助编程爱好者解决代码问题呢?
什么是苏格拉底式问答法
古希腊著名哲学家柏拉图的老师是苏格拉底,在柏拉图的诸多作品中,他时常描绘苏格拉底与同事以及学生之间的辩论场景。
苏格拉底会通过这些辩论,指出人们普遍秉持的信念,并对其予以仔细审查,质疑这些信念与其他信念是否和谐一致,从而引导人们深入探索真理的本质。
然而在数字时代,这种方法又该如何应用于我们当下的交流互动当中呢?
让我们从一个社区的真实案例中来思考这个问题:
你可能很想给上述问题一个直接的答案,例如以下代码所示:
const sum = nums.reduce((acc, el) => acc + el, 0);
但是,如此行事实际上是你替学习者完成了逻辑推理的过程。
相反,你应当专注于提出具有针对性的问题,以此引导他们寻得答案。例如,你能够从以下问题着手进行提问:
如果不使用代码,你如何用纸笔计算出一系列数字的总和?
要求学习者脱离代码来回答这个问题,看似有悖于直觉,但实际上你是在引导他们思考问题背后的逻辑。
让我们假设学习者给出了如下的回答:
我会逐个浏览每个数字,并将其累加到之前数字的总和上。
随着学习者开始回应你的问题,对话应当以这种一问一答的形式展开,并且随着学习者逐渐趋近解决方案,你的问题也应愈发具体且具有针对性。
举例来说,一系列问题如下展开:
导师:“很好,那么什么是数字数组?”
学生:“一个列表?”
导师:“不错!你将如何遍历这个列表?”
学生:“用一个for循环。”
导师:“那么在每次迭代中,你的循环需要做什么?”
学生:“将当前数字加到总和中。”
导师:“你在哪里可以找到总和?”
学生:“我可以把它放在一个循环外部的变量中。”
导师:“很好,现在你可以尝试编写代码了。”
——此示例为本文原创
此时,学习者很可能会将各个要点联系起来,并得出最终的解决方案。
苏格拉底式问答法在现代文化中的应用
学习苏格拉底式问答法(Socratic method)并非易事。实际上,许多人往往要到上大学时才会接触到它。不过,在现代流行文化当中,存在着不少能够帮助你理解苏格拉底式问答法如何运作的实例。
在电视剧《豪斯医生》(House, M.D.)里就充斥着此类例子。以名为“三个故事”(Three Stories)的一集为例,请看下面的对话:
豪斯:“肾结石会导致什么?”
学生:“尿中带血。”
豪斯:“你的尿是什么颜色?”
学生:“黄色。”
豪斯:“你的血是什么颜色?”
学生:“红色。”
豪斯:“我用了哪些颜色?”
学生:“红色、黄色和棕色。”
豪斯:“还有棕色。棕色是由什么导致的?”
学生:“废物。” ——(Frapier,2008)¹
你会留意到这段对话的展开方式。豪斯的目的并非直接给出答案,而是通过提出演绎性的问题,引导学习者自行得出结论。
再来瞧瞧热门电影《黑客帝国》(The Matrix):
墨菲斯:“尼奥,你有没有做过一个梦,如此真实,让你深信不疑?”
尼奥:“这不可能是……”
墨菲斯:“不可能是什么?不可能是真的吗?”
墨菲斯:“如果你无法从那个梦中醒来,尼奥,你怎么知道梦境和现实世界之间的区别呢?” ——(沃卓斯基姐妹,1999 年)²
在这个场景里,墨菲斯运用苏格拉底式问答法引导尼奥让他对现实的感知产生质疑。这是一个颇为戏剧化的例子,但其前提是相同的:并非告知学习者他们应当如何思考,而是引导他们凭借自身的意愿得出结论。
最后,我们来看一个出自《律政俏佳人》(Legally Blonde)的例子:
Elle:“你父亲被枪杀的时候,你正在洗澡?”
……
Chutney:“是的。我正在洗头。”
Elle:“Windham小姐,你能跟我们讲讲你当天早些时候在做什么吗?”
Chutney:“我起床后去了星巴克,然后去了健身房,烫了头发,就回家了。”
Elle:“然后你洗了澡。”
Chutney:“是的。”
……
Elle:“……Windham 小姐,你以前烫过头发吗?”
Chutney:“烫过。”
Elle:“那你能说说大概烫了多少次吗?”
Chutney:“从十二岁开始,每年两次。你自己算算吧。”
……
Elle:“Chutney,为什么 Tracy Marcinko 的卷发被水冲过后就毁了?”
Chutney:“因为卷发湿了。”
Elle:“没错。因为烫发保养的首要规则不就是,烫完头发后至少二十四小时内不能弄湿头发,否则可能会使硫代乙酸铵失效吗?而一个一生中烫过——三十次发?——的人,不应该很清楚这条规则吗?而且,如果你事实上并没有在洗头,就像我所怀疑的那样,因为你的卷发还完好无损,那你难道没有听到枪声吗?”
——(Luketic,2001)³
苏格拉底式问答法在法律领域颇为常见,而这段对话便是一个极为出色的范例。在此段对话中,Elle 并非试图引导 Chutney 得出结论,而是在引导观众(在这种情形下是陪审团)得出结论。这对于像我们这样的社区而言是一个重要的区别:与一位成员展开苏格拉底式的讨论,实际上能够让当前以及未来可能观察到或回顾这段对话的成员从中受益。
苏格拉底式问答法的目标
认识到苏格拉底式教学法(Socratic method)的目标并非是迅速地交换信息,这一点极为关键。恰恰相反,其首要目标在于让学习者认识到自身所知晓的内容比他们自认为的要少,而后通过引发特定思考过程的问题来引导他们探寻到答案。
当把这一方法运用到学习编程当中时,铭记“挑战你的假设”这一说法是十分重要的。我们常常觉得自己清楚所编写的代码在做什么,所以当代码无法正常运行时,我们的第一步应当是检验这些假设。
在引导学习者进行调试的过程里,我们期望提出的问题也能够发挥同样的作用。你的常用问题当中应当涵盖“这行代码的作用是什么?”。当学习者给出的信息不准确时,要用能够深入到代码更小组成部分的问题来予以回应——也就是说,要将问题拆解成小块。
以这个例子为例:
学习者:“但也许那样不行,因为我需要找到书,而不是书中的 ID。”
导师:“正确。好消息是,我们有一个函数表面上能够做到这一点。坏消息是,这个函数实际上做不到。那么,这个函数真正是做什么的呢?”
学习者:“返回 bookId”
——摘自Discord 社区
通过提问“这个函数实际上是做什么的?”,导师为学习者指明了得出正确结论的方向,而无需提供任何具体的信息。学习者已经知晓该函数未按预期执行,而导师提出的问题则是为了挑战学习者关于该函数确实按预期执行的假设。
再举一个例子:
导师:“这是来自Chalenge(原文拼写错误)一个例子。你理解他们给出的这个例子了吗?”
学习者:“是的,但是我没懂 for-in循环,我不明白‘(const food in refrigerator)’这句,要用const或let来声明字符串属性名让我感到困惑(现在我已经懂了)”。
导师:“好的,那我们就从这里开始讲起,而不是直接讲Challenge的全部解决方案。”
导师:“运行这段代码时会发生什么?”
……
学习者:“对象的每个键都被设置为在for-in循环中创建的变量 food,然后它遍历对象,并输出键和分配给键的值?”
——来源于Discord社区
同样,我们能够看到导师是如何通过提出具有针对性的问题,引导学习者凭借自身的推理找到解决方案的。
这便是苏格拉底教学法的最终目标:借助学习者自身的推理,引导他们得出合乎逻辑的结论。
苏格拉底式问答法的长期益处
苏格拉底式问答法的意义并不仅仅局限于当下问题的即刻解决。在这种方法中所运用的演绎推理过程,同样能够为学习者带来长远的好处。
通过向学习者提问来挑战他们原来的假设和知识,并引导他们找寻解决方案的这一过程,同样也能够被学习者内化。这对于解决调试问题、隔离假设,甚至是学习如何清晰地阐述问题而言,都是一个强有力的工具。
也就是说,通过引导学习者进行这种一问一答式的对话,学习者也能够学会自行向自己提出这些问题。他们能够将这种不断提出愈发具体问题的过程视作一条逻辑路径,并在以后遭遇代码问题(甚至生活中的其他方面问题)时,在脑海中运行这一路径!
结论
直接为学习者提供解决方案,会抑制他们的智力发展,并且剥夺他们通过自身得出逻辑结论所获得的有益体验。通过使用苏格拉底式问答法等技术手段,我们能够营造出一个更强大、更高效的教育环境,让学习者得以持续成长。
这种方法或许看起来既繁琐又冗长,事实也的确如此。直接给他人提供解决问题的代码要迅速得多(并且可以说更为容易)。
但那种方法往往最终会对学习者造成损害。如果作者要分享一个亲身经历作为例证,我曾目睹人们在成为苏格拉底式问答法的对象时感到沮丧,或者对这种一来一回的对话失去耐心。但我从未见过他们对自己通过推理得出问题解决方案的那一刻感到不满或失望——在那一刻,他们恍然大悟。
原文标题:How to Help Someone with Their Code Using the Socratic Method,作者:Naomi Carrigan