软件开发者应该了解的 10 个关于学习的要点 [译]

对软件开发者来说,学习是必不可少的。技术领域的变化不断:新技术层出不穷,老技术也在不停地更新。因此,开发者们不是仅仅学习编程一次就够了——在他们的职业生涯中,他们需要掌握许多新的编程语言和框架。

我们学习并不意味着我们了解学习的过程。在美国的一项调查中发现,大多数关于记忆的看法与科学共识背道而驰:人们对记忆和学习的工作方式缺乏直观的理解。37

以学习风格为例。支持学习风格理论的人认为,有效的教学应该符合学习者的偏好风格——视觉型学习者通过观看学习,听觉型学习者通过聆听学习,动手型学习者通过实践学习。然而,2020 年的一项研究回顾显示,有 89% 的人认为教学应该根据学习者的偏好风格来设计,尽管研究人员几十年来一直认为这种观点是错误的。28 虽然学习者有自己的偏好风格,但有效的教学应该与教授的内容相匹配,而不是学习风格。例如,科学课程应使用图表来展示数据,而不是仅仅依赖语言描述,无论学习者是视觉型还是听觉型;同样,烹饪课程应侧重于实践操作,而不是仅仅依赖阅读,不论学习者是否偏好动手操作。

经过数十年认知心理学、教育学和编程教育研究的积累,我们对学习的方式有了深刻的洞察。本文接下来的 10 个部分将提供基于研究的关于学习的发现,这些发现适用于软件开发者,并讨论其实际应用。这些信息可以帮助你自我学习、培训新员工以及招聘人才。

1. 人类记忆:远不止比特那么简单

人类的记忆是学习的核心。正如 Kirschner 和 Hendrick 所描述,“学习意味着人的长期记忆发生了变化。”20 对于熟悉计算机记忆强大功能的软件开发者来说,我们可以在计算机中存储一系列比特,并在以后精确地检索这些比特。人类记忆虽与此相似,却不那么精确可靠。

人类记忆的生物复杂性使其可靠性成为一个复杂的议题。在计算机记忆中,我们主要执行读取和写入两种操作。读取计算机记忆并不会改变它,写入和读取之间经过多长时间也无关紧要。但人类的长期记忆并不像计算机那样“一尘不染”。人类记忆似乎执行着一种“读取并更新”的操作,在回忆时不仅可以加强记忆,还可能对其进行修改——这一过程被称作“记忆重整化 (reconsolidation)”。这种修改在刚形成不久的记忆上更为常见。因此,一个事实并非只有明确知道与否的二元状态,而是可能存在于各种中间状态。我们可能会忘记以前所知的事物,尤其是在最近才学的知识上,可靠性尤为不足。

人类记忆的另一个奇妙特点是“记忆波及效应 (spreading activation)”。1 我们的记忆储存在相互连接的神经网络中。试图回想某件事时,我们会激活一条神经元通路来寻找目标信息。然而,这种激活并不局限于单一通路。就像热水管散发的热量一样,一部分激活能量会波及到其他相连的神经通路,使这些通路在数小时内处于易于激活的状态。1

“扩散激活”这个概念在记忆方面带来了负面效果1,但在解决问题时却有积极的作用32。“扩散激活”指的是相关但不精确的信息可能与我们真正想要回忆的信息混淆在一起,导致我们对信息的回忆可能并不准确。然而,从另一方面看,“扩散激活”也与灵光一闪的解题思路紧密相关。因为某些思路会在数小时内保持活跃状态,所以有时候暂时放下一个问题去解决另一个,就可能让两个原本不相关的领域意外产生交集。这种交集能激发出创造性和独特的解决方案。这也是为什么有时候散个步、洗个澡或者简单地离开问题一会儿,能帮助我们在解题时找到新思路。

总的来说,人类的记忆机制并不像计算机内存那样,只是简单地在特定位置存储和检索信息。人类记忆更加易碎、不那么可靠,但同时也因为能够将不同的知识点相互连接,带来了解题和深入理解方面的巨大优势。我们将在后续章节中进一步讨论这个话题,特别是关于如何从记忆中提取信息和加强记忆力。

2. 人类记忆:一个有限和一个无限的系统

人类记忆主要由两部分组成,对学习至关重要:长期记忆(long-term memory)和 工作记忆(working memory)。长期记忆是信息被永久储存的地方,它的功能几乎是无限的;1 可以类比于计算机的硬盘存储。另一方面,工作记忆则用于有意识地处理信息,帮助我们解决问题;2 它就像是计算机中 CPU 的临时存储区,只能存储有限量的信息以供实时访问和处理。

工作记忆的容量是有限的,大体上在出生时就已确定。2 虽然较高的工作记忆容量通常与更高的智力水平相关,但它并非决定个人表现的唯一因素。22 更大的工作记忆容量有助于加快学习速度,但我们的长期记忆无限,这意味着我们能学到的知识总量是没有限制的。1 专家程序员不论工作记忆容量大小,他们的专业知识主要源自于丰富的长期记忆储备。

当人们对一个话题有更深入的了解时,他们会把信息组合成信息块a 信息块化让多个信息片段在工作记忆中作为一个整体来处理。例如,学习一个电子邮件地址时,一个熟悉的域名,比如 gmail.com,就被视为一个整体信息,而不是像 xvjki.wmt 那样的一串无规律字符。因此,信息块化得越多,工作记忆的实际容量就越大。38 类似于计算机,我们的工作记忆/CPU 寄存器可能只能存储五个指向长期记忆/硬盘中信息块的指针,但信息块的大小没有限制。因此,通过实践使用信息和解决问题来增大信息块的大小是一种优化策略。

学习新工具或技能时,理解任务对工作记忆容量的需求,即认知负荷,非常重要。认知负荷分为两部分:内在负荷外在负荷。内在负荷是完成任务固有地需要处理的信息或信息块的数量,除非改变任务本身,否则无法更改。相比之下,外在认知负荷指的是执行任务时的不必要信息。例如,在实现数据库模式时,使用带有表格和属性的图示要比仅用纯英文描述来得简单,因为后者增加了外在负荷,你需要在脑中将文字描述转换成模式,而图示则可以直接应用(参见 图 1)。对于初学者来说,由于他们难以区分任务中的内在和外在信息,因此通常会感受到更高的外在负荷。

图 1: 展示同一数据库架构描述的两种方法,各自产生不同水平的额外认知负担。
图 1: 展示同一数据库架构描述的两种方法,各自产生不同水平的额外认知负担。

当面临看似超出个人能力范围的任务时,我们需要认识到,通过重新安排这个任务,是可以改变这种局面的。把问题分解成可以单独处理和组织的更小部分,最终会帮助个人解决复杂的问题。无论是在自己面对当前技能极限或超出自己技能范围的问题时,还是在指导初级开发者和新入职员工时,运用这一原则都十分重要。

3. 专家的识别与初学者的推理

初学者与专家的一大区别在于,专家对各种情况都历经沧桑。国际象棋专家的研究显示,他们的主要优势在于能够记忆并识别棋盘状况,这让他们能够更迅速、更轻松地做出反应。15 Kahneman19,b  把认知分为两个系统:“系统 1”和“系统 2”,这证明开发者在命名事物时也会遇到困难。系统 1 迅速且依赖识别,基于长期记忆中的模式识别;而系统 2 则较慢,专注于推理,需要在工作记忆中进行更多的处理。这属于被称为双过程理论的广泛概念。34


专家开发者能够通过记忆程序代码中常见的模式,在更高层次上进行推理,这有助于释放他们的认知能力。


专家开发者通过记忆(通常是基于经验隐式地记忆)程序代码中的常见模式,能够在更高层次上进行推理,释放认知能力。4  例如,编程中的“设计模式”就是这样的一个案例,与前文提到的代码块类似。专家可能会立即识别出某段代码正在执行排序算法,而初学者则可能逐行阅读代码,试图理解其运作方式,却未能看到整体架构。

由此可见,初学者可以通过大量阅读和理解代码成为专家。专家通过积累丰富的编程模式库,使得他们在将来阅读和编写代码时更加得心应手。只看命令式的 C 代码可能对理解函数式的 Haskell 代码帮助有限,因此接触不同的编程范式将更有益。总的来说,通过阅读和实践更多、更多样的代码,就能提升编程技能。

4. 从抽象到具体再到抽象的理解过程

研究表明,专家和初学者在处理概念时有所不同。专家倾向于使用普遍且抽象的术语,专注于探索概念的核心原理,而非纠结于细节。相反,初学者往往只看到表面的细节,却难以把这些细节与整体大局联系起来。这种差异不仅影响了专家的推理方式,也影响了他们的学习方法。

比如,在向初学者讲解 Python 中的可变参数函数时,专家可能会简单地描述它为一个可以接受不同数量参数的函数。而初学者可能会关注如何声明和调用这种函数的具体语法,甚至可能误以为只传递一个参数是一种特殊情况。相比之下,专家在理解或预测这个概念的细节时可能会更为得心应手。

学习一个新概念时,结合抽象的特征和具体的细节示例会更有帮助。更具体地说,你会从跟随“语义波”中获益,这是澳大利亚科学家 Karl Maton 提出的一个概念,25 正如图 2所示。

图 2. 可变参数函数的语义波。
图 2. 可变参数函数的语义波。

在遵循语义波的过程中,你会不断在概念的抽象定义和多个具体示例之间切换。这些示例越是多样化,效果越好。甚至错误的示例也有助于你通过与正确示例的对比来理解错误之处,23 比如在学习什么是常量时,看到一个被错误地标记为非常量的可变变量。这个过程被称为“拆解”。

有了这些多样化的示例,你就能够重新审视抽象的定义,并对概念形成更深层次的理解。深入理解源自于你如何将示例中的多个细节与定义中的抽象概念联系起来,这个过程被称为“重构”。

我们常有一个误解,认为解决问题是一种普遍适用的技能。然而,大脑在处理问题时的实际运作方式并非如此。

在编程中,我们经常需要学习一些抽象的概念。例如,在学习像“函数”这样的抽象概念时,人们往往会先找一些具体的例子来理解,比如 abs 函数,它用来计算一个数字的绝对值。17 难点在于,概念越是抽象(从值到变量/对象,再到函数/类,直至高阶函数/元类,甚至范畴论),要找到与之对应的具体实例就越难。但随着我们对这些抽象概念的理解加深,它们就会变得更加具体易懂。一开始,函数对我们来说是个抽象的概念,但经过大量练习,函数就会变成我们脑海中清晰的概念(或知识块),这时我们就能够理解更高层次的抽象了。

5. 学习的时间安排和重复性

大家都知道考试前刷夜复习是不明智的,因为很可能第二天就忘得一干二净。这个常识背后,其实是认知心理学中一个被广泛认可且持久的现象——间隔效应 10。间隔效应告诉我们,人们在解决问题的学习中,若能将练习安排在不同的时间、不同的天甚至不同的周,效果会更好。

为什么间隔学习如此有效?这与长期记忆和工作记忆的关系密切相关。当我们练习解决问题时,实际上是在锻炼两种技能:一是将问题中的信息与解决方案(例如编写特定的循环代码)联系起来,二是运用这个方案来解决问题。第一个技能需要激活通往长期记忆中相关概念的神经路径 5。如果我们一直重复练习同一类型的问题,比如各种循环问题,那么这个通往长期记忆的路径会始终处于激活状态,导致我们缺乏练习辨识问题的机会。不合理间隔的练习通常会导致我们只有在明确知道使用哪个概念时才能解决问题 5。虽然交替练习不同类型的问题,例如循环和条件判断,能够有所帮助,但神经路径恢复到正常状态还是需要时间,因此,合理的间隔练习对于充分利用练习时间至关重要 10。此外,大脑也需要适当的休息,以巩固新学到的信息,进而应用于新的问题。

与长久以来的原则相悖,密集型编程训练营要求学员在连续不断的会话中密集练习解决问题的技巧。尽管这并非理想状态,但研究间隔效应的学者早就发现,大多数学习者更倾向于在尽可能短的时间内集中练习。10 对于那些只能通过密集训练营学习编程的人来说,我们可以运用间隔学习的研究成果,帮助他们取得最佳学习效果。

要有效安排一天的学习时间,学习者应该将每个学习周期控制在 90 分钟或更短时间内。21 因为大脑中的神经化学平衡会使得超过这个时间点后的集中注意力变得更加困难。21 每段学习时间后,至少要休息 20 分钟。21 在休息时,可以选择散步或静坐,避免做其他工作、漫无目的地上网或与人闲聊。休息有助于加快信息巩固过程,而这一过程也会在睡眠中进行。

在学习的某个阶段,有几种方法可以提高学习效率。首先,建议将不同类型问题的解决顺序打乱,这样可以激活长期记忆中的多种概念。5 但需注意,虽然这种方式能提高学习效果,却也需要更多的努力。6 另一个策略是在学习中不定时地休息一会儿,这有助于巩固记忆。推荐每 2 到 5 分钟就休息 10 秒钟。18

6. 互联网并未使学习成为过时的概念

互联网的出现改变了编程知识的获取方式。曾经隐藏在参考书中的语法或 API 知识,如今只需简单几下键盘操作便能轻松获得。近来,诸如 ChatGPT、Codex 和 GitHub Copilot 这类的生成式 AI 工具,甚至能够(大多数情况下准确地)为你补充这些细节。这就引发了一个明显的问题:如果互联网能在几秒内提供所需知识,那么为什么我们还需要学习这些细节或任何东西呢?

我们通过将知识片段储存在长期记忆中,并在它们之间建立联系来学习。1  如果大脑中没有这些知识,因为你尚未深入学习,大脑就无法建立它们之间的联系,从而无法实现更高层次的理解和抽象思维。1  例如,如果你每次需要进行数据库连接的代码时,都是上网查找后直接使用,而不去深究,你就很难真正理解连接的原理。初学者与专家在依赖互联网或 AI 方面有着显著区别:一个初学者从未深入学习过这些细节,因此缺乏相关的记忆连接;而一个专家虽然掌握了更深层的知识结构,但可能只是在寻找那些遗忘的细节时需要借助搜索。1

研究表明,通过互联网搜索信息,与传统的阅读实体书相比,可能并不利于记忆。一项研究显示,通过互联网获取的信息比通过实体书获取的信息记忆效果更差。11 另一项研究则发现,如果一开始就依赖互联网搜索答案,相比于先自己思考后再搜索,对信息的记忆效果会更差。14 这似乎意味着,依赖搜索可能会减弱大脑通过回忆信息来加强记忆的机会。

此外,先前提到的“认知负荷”问题也值得关注。在互联网上搜索信息要求大脑从一种任务状态转换到另一种,这意味着我们的注意力和工作记忆(即处理当前任务所需的短期记忆)需要从编程任务转移到新的认知任务上,如在互联网上搜索并筛选结果,或是评估 AI 生成的结果。如果能够记住所需知识,不仅获取信息的速度更快(就像使用缓存而不是从硬盘上读取数据一样),还可以避免在任务切换和过滤搜索中的无关信息时的认知消耗。因此,尽管可以在互联网上找到信息,记忆信息本身仍有诸多好处。

7. 解决问题不是一个普遍适用的技能

在编程领域,解决问题扮演着重要角色。在软件开发中有一个普遍但不正确的观点,认为可以直接教授解决问题这一技能,并将其应用于开发的不同方面,如设计、调试等。因此,人们常误以为解决问题是一种普适的技能。但实际上,大脑解决问题的方式并非如此。

人类虽然具备一些通用的解决问题能力,但这些能力远不如专业领域的解决问题技能高效,例如调试程序的能力。我们能学会推理,但并非真的学会了普遍的解决问题方法。相反,我们学会的是解决特定问题的方法,比如编程问题、规划国际象棋的最佳走法、设计编织图案等。这些技能彼此独立,互不相关。研究表明,学习国际象棋对其他学术和认知技能的影响微乎其微,音乐教学和认知训练也是如此。36 正因为无法将解决问题的技能转移到其他领域,所以“大脑训练”在发展通用智能方面效果有限。29

此规则的唯一例外看似在于空间技能。空间技能是指我们能在脑海中构建物体形象(例如俄罗斯方块的形状),并对这些物体进行心理操作(如旋转俄罗斯方块)。通过训练这些通用技能,我们可以提高在其它学科领域的学习能力。这一现象十分罕见,因此在认知科学和学习科学领域引起了广泛关注。24 实际上,空间技能训练能够提升多种非语言技能的表现,而这并不受个人起始能力、年龄或训练任务类型的限制。40 最新的研究甚至显示,空间训练能够提高专业软件开发者的工作效率,这可能是因为他们还在不断学习新的概念。30 尽管空间技能训练是一个奇特的例外,但要学会解决编程问题,最有效的方法仍然是直接练习解决编程问题,而不是期待通过学习国际象棋或进行其他认知训练来提高表现。

在招聘方面,这里也有一个值得关注的点。一种流行的编程候选人筛选方法是出一些脑筋急转弯题目,比如怎样称量一架大型喷气飞机。然而,正如谷歌在 2013 年所认识到的,这种方法并不高效7——解决脑筋急转弯问题和编程问题之间并没有直接的相关性。如果想评估一个人的编程能力,最好的方式就是直接评估其编程能力。

8. 专业技能在某些情况下可能适得其反

尽管我们已经探讨了许多专业技能对学习和表现带来的好处,但成为专家也有可能带来问题。

程序员为了提高工作效率,常使用各种工具和辅助设备,例如版本控制系统或集成开发环境(IDEs)。但这些工具对初学者和专家的影响却截然不同。初学者可能会因为专业工具提供的选项过多而感到不知所措(这是因为“认知负荷(cognitive load)”的增加),对于他们来说,初学者友好的使用提示会大有裨益。然而,对于已经熟练掌握的专家来说,这些提示反而显得多余且分散注意力。这就是所谓的“专家反转效应(expertise-reversal effect)”:有助于初学者的指导和提示,对专家而言可能反而是障碍,降低了他们的工作效率。

程序员在其职业生涯中通常需要学习多种编程语言。虽然掌握多种语言最终是有益的,但有时将一种编程语言的知识转移到另一种语言时,可能会产生错误的知识。比如,程序员在学习 Java 时知道,只要方法签名相匹配,一个方法就可以覆盖父类方法。但在 C++ 中,除了签名匹配外,还需要父类方法被声明为虚拟(virtual)。这种在不同语言间语法相似但语义有别的特性,尤其是在知识转移时构成了障碍。39

专家通常承担着指导初学者的任务,但那些没有教学经验的专家往往没能意识到初学者的思考方式与他们不同。因此,他们难以为拥有不同“心智模型(mental model)”的初学者量身定制解释。这种现象被称为“专家盲点问题(expert blind-spot problem)”:一旦成为专家,就难以从初学者的视角出发理解问题。专家可以通过仔细倾听初学者对他们目前理解的阐述,并据此调整解释方式,来克服这个问题。

有时候,专家所掌握的知识变得如此自动化,以致于他们难以将其言语化。1 这就是为什么专家在面对问题解决时会有直觉,或者会说“我就是直觉知道该怎么做”。在涉及这类隐性知识的情况下,初学者通常更适合学习专为新手设计的指导材料,即所谓的脚手架式教学,或者向同伴而非专家求教。一个知识水平更高但依然是新手的同伴,可以有效地帮助初学者学习新知识,同时也能协助专家重新找回那些已经习以为常的知识。

9. 编程能力的预测因素仍不明确

像大多数活动一样,学习编程的成功建立在天赋和练习的结合上。有些人坚信天赋决定一切,认为“与生俱来”;而另一些人则认为成功几乎完全取决于练习,就像“1 万小时理论”所描述的那样,认为只要足够练习就能成为专家。这两种极端观点都是错误的。本节我们将探讨天赋和练习对学习编程效果的不同影响。

尽管有许多研究试图预测编程天赋,但很少得出可靠结果。关于编程能力的预测性测试大多未能成功。研究表明,以下因素均无法有效预测编程能力:性别、年龄、学术专业、种族、数学成绩、之前学习的编程语言、对计算机科学的看法,以及对人文或科学的偏好。35 20 世纪 60 年代,编程天赋测试曾一度流行,但如 Robins 所总结33,这些测试的预测准确性不高,最终逐渐被淘汰。

关于实践经验年数的重要性,研究结果并不统一。在 Stack Overflow 上,程序员的声誉与其年龄有关:年长者通常声誉更高。27 然而,最近的一项研究发现,对于职业生涯相对初期的程序员而言,经验年数与编程任务的成功之间的联系微弱,31 这表明在程序员职业生涯早期,天赋可能比经验对成功影响更大。

在多数领域,影响早期编程成功的两个较弱的因素是通用智力和工作记忆容量。4 这两点大致代表了推理能力和学习者一次能处理的信息量。因此,它们更多地预测学习的速度而非绝对的能力。在这两个因素中,空间推理作为一个子指标,是编程成功的一个更强的预测因子,尽管其预测力度仍然是中等的。30 空间推理能力也被认为是其他科学和数学领域成功的一个预测因素,24 因此这并非仅限于编程领域。此外,随着经验的增长,这些从弱到中等的相关性往往会减弱。因此,并非所有智力高的人都会成为优秀的程序员,优秀的程序员也不一定在智力上表现突出。

总的来说,预测谁能成为程序员是非常困难的,特别是从长期角度来看。程序员可能来自任何背景或人群,与智力等其他因素的关联通常在经验面前变得模糊。因此,在招募新程序员时,找到评估编程能力的捷径是不现实的,也不存在任何可靠的“候选人简介”来筛选具备编程能力的人才。

10. 心态的重要性

在编程能力的理解上,长久以来人们普遍认为存在两极分化:你不是能编程,就是不能编程。围绕这种看法,出现了许多相互竞争的理论。其中,学习的连续性动力 33 是一个较有说服力的理论,它认为每一个学习主题都建立在之前的基础之上,因此一旦落后,就很难再赶上。相比之下,“极客基因”(即天生具备或不具备的能力)这个理论就显得较为薄弱,因为它几乎没有实证支持 26。正如前一节所讨论的,我们最近开始理解,编程能力的差异实际上来源于人们的先前经验差异 16。例如,那些看似处于相同情境的学习者(比如,在同一个班级,拥有相同的学位,参加同一个编程训练营)实际上可能拥有截然不同的知识和技能,这些差异使得他们在学习的连续性动力上或领先或落后,或者在某个特定时间点上,显得像是天生具备或不具备某种能力。类似的情况也出现在其他高度技术性的领域,这些领域通常是在大学之前可选学习的,比如计算机科学、物理学和工程学 9

在教学和学习领域,学者们跨学科研究了"固定思维 vs 成长思维"对学习成效的影响。12 固定思维认为人的能力是天生且不变的。从学习角度来看,这种思维意味着,如果某人在新任务上遇到困难,那么他们可能不适合这项任务。相反,成长思维认为人的能力是可以通过实践改变的。在学习中,这种思维鼓励人们认为,即使在新任务上遇到困难,也能通过足够的练习来掌握它。


尝试制作一个预测编程能力的测试通常都未能成功。


正如 Cheryan 等人所描述的,9 这两种极端的思维方式都不是绝对正确的。比如,几乎每个人都能学到一些物理知识,即便他们起初并不擅长。但是,不管练习多少,几乎没人能因此获得物理学的诺贝尔奖。在这两个极端之间,我们常常试图探索自己能力的界限。当教师和学生以成长的心态面对新挑战时,他们往往能更好地坚持不懈,有效地克服失败。12

尽管有强有力和直观的证据支持这一效应,但研究显示,要改变一个人的思维方式,让其更加注重成长,却是一件困难的事情。8 特别是,人们普遍存在两个关于培养成长型思维(growth mindset)的误解,而这些误解被证明是无效的。第一个误解是认为应该奖励努力而不是成果,因为成长型思维更倾向于通过实践而非天生才能来提升自己。然而,学习者并非没有判断力;当他们感觉到自己没有进步时,老师对无成效努力的赞扬并不会带来帮助。相反,只有当学习者运用有效的策略,并且正朝着成功的方向前进时,他们的努力才应得到奖励。13 第二个误解是,当某人以成长型思维面对任务时,他们会在整个过程中保持这种思维。事实上,当我们遇到挫折和失败时,人们往往会转向固定型思维(fixed mindset),因为我们对自己能力的极限并不清楚。因此,我们必须通过实践来克服挫折和失败,以保持成长型思维的态度。13

与固定型思维和成长型思维相关的另一个概念是目标取向。这可以分为两种类型:积极取向和消极取向。积极取向的目标是希望表现出色,这会激发积极有效的学习行为,如努力学习、寻求帮助、尝试新颖且具挑战性的话题。相比之下,消极取向的目标是避免失败,这会导致消极和无效的行为,如学习无计划、不寻求帮助、对成绩焦虑和回避挑战。重要的是,学习者应该可以在没有严重后果的情况下犯错,这样他们才更可能被引导向积极取向,而不是消极取向。


并非所有聪明人都会成为优秀的程序员,优秀的程序员也不必然在普遍智力上表现出色。


在学习新技能或指导别人学习新技能时,重要的是要认识到,采用成长型心态(growth mindset)来应对挑战虽有效,但它本身也是一种需要培养的能力。我们不能简单地告诉别人拥有成长心态,就期望立即看到成效。相反,我们应该通过寻找或提供关于学习过程和策略有效性的真诚反馈来培育这种心态。对于导师来说,要称赞学员在某些方面取得的进步,并理解他们会犯错误,而不是对此加以指责。作为学习者,在怀疑自己进步时,回顾一下过去几周或几个月你的技能是如何得到提升的。此外,要知道在失败面前,成长心态可能会转变为固定心态(fixed mindset),但通过实践,它也能够再次被培养并变得更坚强。感到沮丧是常有的事,但这并不代表你将永远沮丧。如果你感觉想要放弃,那就暂时休息一下,出去走走,重新思考你的方法,然后再试一次。

概要

在不断变化的软件开发领域,开发者必须持续学习以跟上步伐。学习,无论是编程还是其他领域,都涉及到记忆的储存。人类记忆复杂而迷人。尽管它与计算机架构有相似之处,但关键的差异使它的工作方式截然不同。本文阐释了目前科学界对人类记忆运作方式的理解,学习机制,初学者与专家的区别,并将这些知识应用于软件开发者如何改进学习、培训和招聘的具体措施。

建议。 我们的建议分为招聘和培训学习两部分。

对于招聘,我们建议:

  • 编程能力没有有效的替代指标。性别、种族等因素的刻板印象没有科学依据。要评估候选人的编程水平,应查看其过往作品或对他们进行实际编程任务的测试。强调一点:不要用脑筋急转弯的题目测试候选人。
  • 在年轻开发者中,经验年数或许并非衡量能力的可靠指标。
  • Behroozi 等人3的建议是,让候选人先独自在房间内解决面试题,然后再展示解答。因为面试官的观察或在解题过程中的交谈会增加认知负担和压力,这可能会影响表现。

在学习和培训方面,我们建议:

  • 阅读大量代码能帮助提升编程效率。
  • 专家并不总是最适合培训初学者的人选。
  • 学习需要时间,包括学习阶段之间的间隔时间。密集式的填鸭学习效果不佳,但间隔重复学习法却非常有效。
  • 离开问题一段时间有助于找到解决方案。
  • 即便可以通过互联网搜索或使用生成式 AI (generative AI) 工具找到答案,也不代表学习变得无关紧要。
  • 利用示例将抽象概念与具体可学习的事实相结合。
  • 追求成功(而非避免失败),以及相信自己的能力是可改变的,是学习和坚韧不拔的关键因素。

进一步阅读。 关于学习的许多书籍主要讨论正规教育,主要面向学校教师和大学讲师。但这些学习原则也广泛适用于其他领域,包括职业发展。这里向你推荐三本书:

  • 《为什么学生不喜欢学校?》一书由 Daniel T. Willingham 著作,该书简洁易懂地解释了许多关于记忆和大脑工作原理的知识。
  • 《程序员的大脑》一书由 Felienne Hermans 等人所著c,把这些学习概念应用到编程上,说明学校里使用的学习和复习技巧同样适用于职业发展。
  • 由 Paul A. Kirschner 和 Carl Hendrick 合著的《学习如何发生:教育心理学中的重要作品及其实践意义》20,通过解读一系列有影响力的论文,用浅显的语言介绍了这些论文的重要内容及其实践意义。

引用的这些论文也是极好的进一步阅读资料。如果你是软件开发者,可能无法获取所有论文;拥有数字图书馆的 ACM 会员则可以访问 ACM 的论文,尽管我们引用了许多来自其他学科的文献。对于较新的论文,许多作者在他们的网站上免费提供 PDF 版本;你可以尝试在网上搜索具体标题来找到这些 PDF。许多作者也愿意在你直接联系他们时提供副本。

致谢

我们感谢 Greg Wilson,他在发起和校对这篇文章方面发挥了关键作用,也要感谢我们的其他校对者:Philip Brown, Kristina Dietz, Jack Parkinson, Anthony Robins 和 Justin Thurman。这项研究得到了国家科学基金会的部分资助,授权号为 #1941642。本文中表达的任何观点、发现、结论或建议均属于作者个人观点,并不一定代表国家科学基金会的立场。