logo
Zhanxin
Published on

适合软件开发者的学习指南

Authors

本文共有 7866 字 · 预计阅读时长≈ 40 min

对于软件开发者来说,学习是不可或缺的。技术领域在不断变化:新技术层出不穷,旧技术也在不断更新。因此,学习不仅仅是一个入门的阶段,而是开发者职业生涯中的常态。

然而,学习并不等同于掌握“如何学习”。许多人对记忆和学习的理解与科学共识不符。

以学习风格为例,你可能听说过每个人在学习时有特定的偏好,分为视觉型,听觉型,触觉型等,支持这一理论的人认为,教育应该迎合学生的偏好,例如,视觉型学习者需要更多图像和图表来帮助记忆,而听觉型学习者则通过听讲更容易理解。这个理论的广泛流行让许多老师和教育机构会特意根据学生的偏好来调整教学方法,认为这能显著提升学习效果。

然而,科学研究表明这种方法的有效性并不显著。事实上,有效教学应当根据学习内容本身的特点来选择合适的呈现方式,而不一定要迎合学习者的偏好。例如,学习科学课程时,内容通常包含大量数据和概念,使用图表和图像展示复杂的关系和趋势是最有效的方式。即使学习者更喜欢听讲,单靠听觉也很难完全理解复杂的数据关系。同样,学习烹饪技术时,实践操作显然比读书或听课更有效,因为烹饪的核心是动手技巧和感官体验,比如切菜的手法、火候的掌握等,这些都需要亲身体验。

1. 人类记忆 vs. 计算机存储:复杂机制与创新优势

学习不是短暂记住某件事情,而是把这些事情长期存储在脑海中,在需要时可以及时调用,我们可以把这种机制类比成在计算机存储和检索数据,然而,人类的记忆与计算机相比,虽然也能“存储”和“读取”,却不像计算机那样精确可靠。

计算机的记忆很简单。我们可以在计算机中执行“读取”和“写入”操作,读取过程不会改变存储的数据,而写入后的数据也不会因时间而模糊。

反观人类记忆,它更像是“读取并更新”。每当我们回想某段记忆时,大脑不仅会强化这段记忆,甚至可能对它进行改变,这个过程被称为“记忆重整化(reconsolidation)”。这就是为什么我们对某些事情的记忆会变得模糊,甚至不再准确。

例如,你小时候参加过一次生日派对,但多年后回想,派对的细节可能与当时的情形略有不同,甚至会在脑海中添加并不存在的细节。

另外,人类记忆的另一个特点是“记忆波及效应(spreading activation)”。我们的记忆存储在相互连接的神经网络中。当我们试图记起某件事时,激活的不只是单一的记忆通路,而是像波纹一样,影响到其他相邻的神经元通路。

这就像在回想朋友的名字时,相关的情景、他们的外貌和共同的经历都会浮现。这种记忆的波及效应在学习上可能产生负面效果,例如,你可能把两件相似的事情混淆;但在问题解决上,这种效应却常常是积极的。因为激活的通路会在脑中保持活跃数小时,这意味着当你离开当前问题、去思考其他事情时,潜意识中依然会对这个问题保持关注。

如果你在软件开发过程中,遇到了暂时无法解决的问题,可以尝试去散步、洗澡、或是分心片刻后,可能会获得新的见解或解决思路。

总之,与计算机的“存储-检索”模型不同,人类的记忆更加复杂且不完全可靠。这种机制虽然让记忆变得容易受到干扰,却也带来了一些独特优势:人类的记忆能在不同的知识点间建立连接,从而更有利于创新思维和深度理解。

2. 人类记忆机制到高效学习:工作记忆、信息块化与认知负荷管理

人类记忆的两个核心部分——长期记忆和工作记忆——对学习至关重要。长期记忆是信息被永久储存的地方,几乎没有容量限制,可以比作计算机的硬盘。我们可以不断在其中积累知识和经验。而工作记忆则用于实时处理信息,帮助我们解决当下的问题,类似于计算机的CPU,只能存储和处理少量信息。

工作记忆的有限容量

工作记忆的容量是有限的,大致在出生时就已经决定。尽管较高的工作记忆容量通常与较强的智力水平相关,但它不是决定学习能力的唯一因素。大容量的工作记忆的确可以加快学习速度,但关键在于我们还拥有无限的长期记忆,这意味着能够储存的知识是无限的。比如,一名经验丰富的程序员,尽管工作记忆容量有限,但凭借长期记忆中储存的丰富知识和技能,也能高效地解决复杂的问题。

信息块化

当我们深入掌握某一主题时,把零散的信息组合成一个“信息块”,这样能让工作记忆更高效地处理复杂信息。比如,记忆一个域名地址时,如“blog.luoxinxin.com.cn”可以作为一个整体信息处理,而不像“119.32.137.24”这种无规律字符难以组合。信息块化越多,工作记忆在实际应用中就越强大。可以把这看作CPU只能存储有限数量的指针,但每个指针可以指向长期记忆中的一个“信息块”。通过反复实践和应用,我们可以逐渐扩大信息块的容量,从而更有效地利用工作记忆。

认知负荷:内在负荷与外在负荷

在学习新技能时,理解工作记忆的容量需求,即“认知负荷”,十分重要。认知负荷有两种:内在负荷和外在负荷。

内在负荷是完成任务本身所需处理的信息量,是任务的固有属性,无法改变。 以学习编程为例,假设你在学习如何实现一个排序算法,比如快速排序算法。理解这个算法的基本步骤、逻辑和原理就是内在负荷,因为这些是完成该任务所必需的知识。

外在负荷则是完成任务时的不必要信息或额外干扰。 仍以快速排序为例,假如在学习过程中,教程不仅介绍了排序算法,还讲述了算法的历史背景,甚至包括开发者的个人故事,这些信息虽有趣,但并不直接帮助理解算法的运作原理。

相较于高级开发者,对于初学者来说,我们很难分辨出哪些信息是必要的、哪些是无关的可能会耗费额外的认知资源,从而白白增加了外在负荷,这常常会导致学习过程更难专注于核心内容,

对此,可以通过将学习资料简化、突出关键步骤和逻辑,从而减少外在负荷,让我们更轻松地掌握核心概念。

将复杂任务拆解

当面对看似超出能力范围的任务时,可以通过将任务重新分解为更小、更可控的部分来应对。例如,将复杂的软件项目分解为多个小模块,每个模块解决一个独立的问题,逐步完成。

3. 从初学者到高级开发者:通过模式识别和经验积累提升编程思维

初学者与高级开发者之间的重要区别在于,后者拥有大量的实际经验,对各种情况和问题都有过深入的理解。

研究显示,国际象棋专家之所以能快速做出决策,是因为他们能通过识别和记忆棋盘上的常见布局来迅速分析局势,而无需逐步推理。

类似的,心理学家丹尼尔·卡内曼在 《思考:快与慢》 这本书中提出了“系统 1”和“系统 2”理论,将人类的思维过程分为两个系统。

系统 1 是快速、自动的,主要依赖于长期记忆中的模式识别;而系统 2 则较为缓慢,专注于深度推理,需要调动工作记忆去进行分析。这种双过程理论也适用于程序开发领域中的认知模式。

对于开发者而言,高级开发者与初学者的思维差异尤为显著。高级开发者能够迅速识别代码中的常见模式或“代码块”,例如设计模式,因而在编写或阅读代码时可以直接从经验中调取适当的解决方案。

就像国际象棋专家能认出经典的棋盘布局一样,专家开发者可以立即认出某段代码正在实现排序算法或处理特定数据结构。这样一来,他们可以在高层次上进行推理,节省大量的认知资源。相比之下,初学者则需要逐行分析,试图理解代码的每一步运作,从而难以看到代码的整体架构。

例如,在编程中,“工厂模式”是一种常见的设计模式。专家开发者在看到类似的代码结构时,可能立刻明白这是一个工厂模式,并理解它在创建对象时的作用。而初学者则可能需要详细阅读每一行代码,以理解为什么选择这种方法,且不易察觉到这种结构的普遍性。

为了成长为高级开发者,初学者可以通过大量接触和理解代码来积累“代码库”——即程序中常见的解决方案、设计模式和架构。接触到更多样的代码和编程范式(例如面向对象、函数式编程等),初学者就能培养出更广泛的模式识别能力。

最终,通过多读多写代码,可以逐渐减少对细节的依赖,转而从整体上理解和掌握代码结构与模式。

4. 理解与抽象:高级开发者与初学者在学习新概念中的思维差异

高级开发者和初学者在处理概念时也同样存在显著差异。高级开发者倾向于使用通用且抽象的语言,试图抓住概念的核心原理,忽略细枝末节。而初学者往往被细节吸引,难以将这些细节融入到整体理解中。这种差异不仅影响高级开发者的思维方式,也让他们在学习新知识时更加游刃有余。

例如,在向初学者讲解 Python 中的可变参数函数时,高级开发者会简单地概括它为“一个可以接收不同数量参数的函数”,而初学者则更关注具体的声明和调用语法。对于他们来说,传递一个参数可能会显得特殊,而高级开发者更容易理解这种功能的灵活性,也更善于处理其中的细节。

要想有效学习一个新概念,将抽象特征和具体示例相结合十分重要。

澳大利亚科学家 Karl Maton 提出的“语义波”理论强调,在学习过程中不断在概念的抽象定义与多样化的具体例子间切换有助于加深理解。每次切换就如同“语义波”的一次起伏。比如,为了理解“常量”这一概念,可以通过观察错误示例(如一个被误认为常量的可变变量)来加深理解。这样的反例帮助我们更清楚地识别常量的定义,这种“拆解”过程能带来更清晰的认识。

当你积累了足够多的例子后,可以重新回到概念的定义,将这些例子中的细节与抽象概念联系起来,从而进入“重构”阶段。通过这个过程,我们不仅记住了细节,还将它们编织成了一个全面的理解。

在编程中,抽象概念的学习尤为常见。以“函数”这一概念为例,一开始我们可能从具体的例子入手,如 Python 中的 abs() 函数(用于计算绝对值)。然而,随着我们深入学习,函数的概念逐渐变得抽象,我们会接触到更高层次的概念,如高阶函数、类甚至元类。虽然这些抽象一开始难以理解,但通过逐渐建立概念“语义波”中的上下切换,函数最终会从抽象变得具象。

5. 间隔学习的力量:如何通过合理安排学习时间提升编程技能

我们都知道,考试前熬夜复习是不明智的,因为第二天可能会忘记大部分内容。这一常识背后,反映了认知心理学中的一个重要现象——间隔效应。研究表明,如果我们能将学习和练习分散到不同的时间、不同的日子,甚至不同的周进行,学习效果会更好。

那么,为什么间隔学习会如此有效呢?这与我们的长期记忆和工作记忆之间的关系密切相关。

当我们练习解决问题时,其实是在锻炼两种重要的技能:

第一,我们需要将问题中的信息与解决方案(例如,编写特定的循环代码)联系起来;

第二,我们要灵活运用这些方案来解决实际问题。

要理解第一个技能,我们需要激活大脑中通向长期记忆相关概念的神经路径。如果我们不断重复练习同一种类型的问题,比如各种循环题目,这些神经路径就会始终处于激活状态。虽然这种集中练习看似有助于加深记忆,但它会限制我们辨识和解决新问题的能力。实际上,不合理的练习会使我们只能在明确知道要用哪个概念的情况下才能成功解题。相对而言,交替练习不同类型的问题(例如循环和条件判断)则可以帮助我们更全面地理解概念,但要让神经路径恢复正常状态依然需要时间。

因此,合理安排间隔练习,对于充分利用学习时间至关重要。此外,大脑还需要适当的休息,以巩固新学到的信息,进而在面临新的问题时运用自如。

与长期以来的学习原则相悖,密集型编程训练营通常要求学员在连续的时间内进行高强度的练习。尽管这种方式并不理想,但研究表明,很多学习者往往倾向于在尽可能短的时间内集中练习。

对于那些只能通过密集训练营学习编程的学员来说,运用间隔学习的研究成果,可以帮助他们最大化学习效果。

为了有效安排一天的学习时间,学习者应将每个学习周期控制在 90 分钟或更短。超过这个时间,集中注意力会变得更加困难。此外,每段学习后至少要休息20分钟。在休息期间,可以选择散步或静坐,避免做其他工作、无目的地上网或与人闲聊。

适当的休息有助于加速信息的巩固,而这一过程也会在睡眠中继续进行。

在学习的某个阶段,有几种策略可以提高学习效率。

首先,建议将不同类型问题的解决顺序打乱,这样可以激活长期记忆中的多种概念。然而,尽管这种方法能提高学习效果,但也需要投入更多的努力。

另一个有效的策略是在学习过程中定期休息,每 2 到 5 分钟就休息 10 秒钟,这样也有助于巩固记忆。

6. 在信息泛滥时代,深入学习的重要性:为何记住知识依然不可或缺

互联网彻底改变了获取编程知识的方式。在这之前,语法或 API 只能从参考书中查找,而现在只需几次点击便可轻松获取。近年来,生成式 AI 工具如 ChatGPT、Codex 和 GitHub Copilot 甚至能自动生成代码片段,且大多数情况下准确无误。

因此一个问题随之而来:如果互联网能在几秒内提供所需知识,学习这些细节或任何知识是否还有必要?

学习的本质是将知识存储在长期记忆中,并在不同知识块间建立联系。

若大脑中缺乏深入学习所得的知识,这些知识片段便无法相互连接,进而限制了大脑的理解能力与抽象思维能力。例如,每次编写数据库连接代码时,如果总是直接查找现成代码而不去深入理解,就难以掌握数据库连接的实际原理。

这也是初学者与高级开发者在依赖互联网或 AI 时的显著区别:前者对这些细节缺乏深入学习,因此缺乏记忆连接;后者掌握了系统的知识结构,只需在遗忘时查询细节 。

研究表明,通过互联网搜索信息的记忆效果往往不如传统阅读。一项研究发现,通过互联网获取的信息相较于从实体书中获得的信息,记忆效果更差 。另一项研究则发现,相比先思考再搜索,直接依赖互联网搜索答案对信息记忆效果较差。这说明,依赖搜索可能减少了通过回忆来加强记忆的机会 。

此外,认知负荷问题也不容忽视。互联网搜索信息需要将注意力和工作记忆从当前任务切换到搜索任务,导致额外的认知负荷。

搜索信息时需要评估筛选内容,或处理 AI 生成的建议。

相对而言,直接从记忆中调用知识不仅能更快获取信息(就像计算机“缓存”比从硬盘读取数据更快),还能避免任务切换和信息筛选中的无关认知消耗。

因此,即便互联网能够在短时间内提供大量信息,但记住信息本身仍然具有诸多优势,尤其是在提高信息获取效率以及减少认知负担方面。

7. 编程问题解决:特定领域技能的重要性与通用能力的误区

在编程领域,解决问题被视为核心技能。然而,认为这种技能可以普遍应用于软件开发的不同方面(如设计、调试)的观点却是错误的。很多人误以为解决问题是一种通用技能,实际上并非如此。

尽管人类具备一些基本的推理能力,但这些通用能力远不及在特定领域内发展起来的专业技能高效,例如编程中的调试能力。

我们所学到的往往是特定领域的解决方法,而非通用的解决问题技能。

比如,学习编程问题解决、规划国际象棋策略、设计图案的技能彼此独立,且难以转移。研究表明,学习国际象棋对其他学术和认知技能影响极小,音乐教学和其他认知训练的效果也是如此。正因为这种难以转移的特性,所谓的“大脑训练”在提升通用智力方面效果有限。

一个罕见的例外是空间技能的训练。空间技能指我们能在脑海中构建物体的形象(如俄罗斯方块的形状)并进行心理操作(如旋转它)。研究发现,训练空间技能可以提高多个领域的学习能力,甚至在软件开发中也表现出促进作用,这可能是因为编程过程中经常涉及抽象的空间思维与操作。因此,尽管空间技能训练在一定程度上有助于提升跨学科表现,

但对于编程来说,最有效的提升方式依然是直接练习编程问题,而非通过学习国际象棋或其他认知训练来提升能力。

在招聘中,这一点尤为重要。企业往往会在面试中使用脑筋急转弯题目(如“如何称量一架大型喷气飞机”)来筛选候选人,但这种方法并未有效评估编程能力。谷歌在2013年就发现,解决脑筋急转弯和编程问题之间没有明显的联系。相比之下,直接评估候选人的编程能力才是最有效的方式。

8. 高级开发者的挑战:知识迁移、工具使用与教学盲点

对于开发者来说,专业知识和技能的深入掌握固然带来许多益处,但在积累的过程中,也会伴随着一些独特的障碍。

工具使用上的差异

在编程中,高级开发者通常会借助版本控制系统、集成开发环境(IDEs)等工具来提升效率。然而,对初学者和高级开发者的影响是不同的。前者往往被工具繁多的选项所困扰(这是因为过多的信息会导致“认知负荷”增加),并因此受益于直观的提示和引导。 而这些对后者来说则成为一种阻碍,分散他们的注意力,甚至降低效率,这种现象称为“专家反转效应”:对初学者有帮助的提示,对专家反而是负担。

知识迁移的挑战

软件开发者通常需要掌握多种语言,但在不同编程语言间迁移知识时可能会产生误解。例如,在 Java 中,方法只要签名匹配即可覆盖父类方法,但在 C++ 中,方法不仅需要签名匹配,还需要被声明为“虚拟”(virtual)才能实现重写。

语言间语法相似而语义不同的特点,常在知识转移时形成障碍,让软件开发者容易产生错误理解。

高级开发者的“盲点”问题

高级开发者往往承担指导初学者的任务,然而缺乏教学经验的开发者难以察觉初学者的思维方式与自身的差异。这种“专家盲点”导致专家难以从初学者的角度解释问题。后者可以通过仔细倾听初学者的理解,并以此为基础调整解释,以便克服此问题。

隐性知识的困境

高级开发者的许多知识已经高度自动化,难以通过语言解释清楚。这种“隐性知识”让高级开发者凭直觉行动,解释时常常只会说“我就是知道”。

这种情况下,初学者学习时更适合使用“脚手架式教学”,或向水平略高但仍是新手的同伴请教。这样不仅能帮助初学者,也为高级开发者提供机会,重新关注并言语化这些隐性知识。

9. 编程成功的真实因素:天赋与实践的辩证关系

学习编程的成功通常被认为是天赋与练习结合的结果。一些人相信天赋至关重要,而另一些人则持“1万小时理论”观点,认为成功仅靠练习。然而,这两种极端观点都不准确,天赋和练习对学习编程的影响各有不同。

尽管存在许多试图预测编程天赋的研究,但很少有能够可靠预测编程能力的因素。例如,性别、年龄、专业、种族、数学成绩、先前编程经验和对计算机科学的态度等,都未被证实能有效预测编程能力。

20 世纪 60 年代,编程天赋测试一度风行,但如 Robins 总结的那样,这些测试的准确性不高,最终被淘汰。

关于实践经验的作用,研究结果不一致。例如,在Stack Overflow上,年长程序员的声誉通常较高 。但一项研究表明,职业早期的程序员中,经验年数与编程任务成功的关系较弱 ,表明在早期,天赋可能比经验对成功更重要。

此外,通用智力和工作记忆容量在编程初期略有影响,但主要预测学习速度,而非绝对能力。

空间推理能力,作为通用智力的子指标,是编程成功的中等预测因素,并且同样适用于科学和数学等领域 。然而,随着经验的增长,这些影响往往减弱,显示智力并非成为优秀程序员的必然条件。

综上所述,编程能力的长远预测十分困难,程序员可以来自任何背景,且智力等因素在经验面前不再显著。故而,试图找到评估编程潜力的捷径是不现实的。

10. 编程能力的本质:从心态到学习策略的全面分析

编程能力的两极分化观念在长久以来的理解中占据了重要位置,即认为“要么能编程,要么不能”。围绕这一点,产生了多个相互竞争的理论,其中“学习的连续性动力”理论更有说服力,认为每一学习主题都建立在之前的知识基础上,因此落后往往难以追赶。而“极客基因”的概念,即天赋决定能力的观点,缺乏实证支持。

最近的研究揭示,编程能力差异主要来源于个人的先前经验差异,即使在同一个学习环境中,不同学习者也可能具有不同的知识积累,使他们在学习连续性上各不相同 。

心理学家还研究了固定心态成长心态对学习的影响。

固定心态认为人的能力固定不变,因此当遇到困难时,可能认为自己不适合该任务。

成长心态则认为能力可通过练习提高,从而鼓励在困难面前坚持不懈。这种思维使得教师和学生在面对新挑战时能够有效地克服挫折,并持续努力 。

值得注意的是,要转变一个人的心态并不容易,且普遍存在两种关于成长心态的误解。

第一种误解是认为应该奖励努力而非成果;但如果缺乏进展,单纯称赞努力并不会帮助学习者。有效的努力才值得表扬。

第二种误解是认为一旦采纳成长心态,就会一直保持。然而,遇到挫折时,人们常会转向固定心态。因此,要通过实践和积极应对挫折来保持成长心态 。

此外,目标取向对学习行为也有显著影响。积极取向的学习者往往追求卓越,尝试挑战和寻求帮助;而消极取向的学习者则偏重避免失败,可能不计划、不求助,且更易回避挑战和焦虑。

错误在学习过程中是不可避免的,通过营造无严重后果的学习环境,可以引导学习者形成积极取向,专注于进步而非失败。

在学习或指导中,认识到成长心态的价值固然重要,但这种心态也需要培养。鼓励成长心态不仅是口头上让他人“保持积极心态”,更要通过实际反馈帮助学习者理解自己努力的成效,鼓励进步、容忍错误。

对学习者而言,怀疑进展时,可以回顾自己的提升历程,记住成长心态并非一成不变。在沮丧时,短暂休息、反思方法,再重新投入能更好地应对困难。

总结

在快速变化的软件开发领域,开发者需要持续学习以保持专业竞争力。学习编程和其他技能的过程中,记忆的存储方式尤为关键。

  • 编程能力无法通过性别、种族等刻板印象或替代指标评估。
  • 大量阅读代码有助于提高编程效率。
  • 高级开发者并非总是适合教授初学者。
  • 学习需要分阶段和间隔,密集式学习效果不佳,而间隔重复法非常有效。
  • 离开问题一段时间可能有助于找到解决方案。
  • 即便可通过互联网或生成式 AI 找到答案,学习仍然不可或缺。
  • 通过具体示例将抽象概念落地。
  • 培养积极心态,专注于追求成功,相信自己能力可改变,有助于提高学习效果和毅力。

进一步阅读:推荐以下书籍扩展对学习的理解:

  1. 《为什么学生不喜欢学校?》 丹尼尔·T.威林厄姆,解释记忆和大脑工作原理。
  2. 《程序员超强大脑》 费莉安·赫尔曼斯 (Felienne Hermans),应用学习概念于编程学习。
  3. 《学习如何发生:教育心理学中的重要作品及其实践意义》 保罗·A. 基尔施纳 / 卡尔·亨德里克,解读重要教育心理学研究及其实践应用。