学习编程难吗?多年教学后的答案

当你听到"编程"这个词时,你会想到什么?

也许脑海中浮现的是屏幕上滚动着密集、难以理解的文本行?复杂的命令、符号和其他字符,如同古代象形文字一般令人费解?

我当了几年编程老师,其中四年全职在训练营任教。

我见过各种背景、各个年龄段和人生阶段的学生走进我们的门开始学习编程。

我也亲眼目睹了AI的崛起,我们稍后会谈到这一点。

所以我认为我对上述问题有很好的视角,如果你正在为自己决定学习编程是否适合你,我会尽力回答这个问题。

1、入门

我在教初学者时注意到的一件事是,挣扎在代码之前就开始了。

学生不总是在变量或函数等编程概念上卡住。通常,他们卡在周围环境上:安装工具理解IDE(代码编辑器)是什么导航文件系统创建和保存文件,以及弄清楚所有这些部分如何连接。

很容易把这些当作基础技术知识而忽略,但对许多初学者来说,这是他们的第一个真正的障碍。

如果他们缺乏这些,学习编程对他们来说会难得多

在开始之前,你不需要成为技术奇才,但你应该能够比普通用户更舒适地使用电脑。我还建议学习一些基本的终端命令,因为终端经常被用来导航项目、运行程序、安装工具和排查问题。

这就是为什么我并不总是赞同一些科技网红推广的"直接开始编程"的建议。

经验丰富的程序员通常会把更广泛的编程环境视为理所当然,但对初学者来说,所有这些可能模糊成一个令人困惑的工作空间。

2、编程很奇怪

教不同类型的学生也意味着要处理各种各样的"包袱"。我是以最善意的方式使用这个词。

他们从各种地方带来这些东西:日常语言、数学、学校练习、以前的工作、日常隐喻以及一些关于编程到底"为了什么"的有趣信念。

问题是,编程从所有这些领域借鉴,同时又改变了规则。

让我们看一个简单的编程例子:赋值。

在许多编程语言中,这样的语句是完全正常的:

let a = 2;

它涉及一个变量a,它是值的某种容器。对初学者来说,这似乎足够简单。变量a现在存储了值2

好吧,这都没问题,直到初学者遇到这样的东西:

a = a + 1;

对纯粹用数学思维思考的人来说,这看起来很奇怪。

a怎么可能等于a + 1

在数学中,这个语句似乎是不可能的。然而在编程中,等号不仅仅是说两个东西已经相等。它在执行一个操作。它的意思是:取a中当前存储的值,加1,然后将新结果存回a中。

所以如果a之前是2,那么在这行运行之后,a变成3。有道理吧?

初学者并不总是因为概念本身复杂而困惑。他们困惑是因为符号看起来熟悉但在编程语言中的行为不同。学习编程可能意味着忘记一个含义并用另一个含义替代。

我本质上是一个学者,所以我在这方面读了不少文章。有趣的是,苏塞克斯大学的学者Benedict du Boulay早在1986年就在他的文章《学习编程的一些困难》中提出了类似的观点。发表在《教育计算研究期刊》上,这篇文章探讨了初学者为什么在编程上挣扎,包括有用的类比有时如何误导学习者。

上面的小例子很好地呼应了du Boulay的更广泛的观点之一。

看来有三种重要的错误类型,编程教师应该注意。首先是类比误用导致的错误。这些错误是当学习者试图从类比中提取超出合理范围的结构或关系时产生的。例如,学生经常认为既然变量像一个"盒子",它可以容纳多个值。

du Boulay接着举了一个经典例子:交换值。我想在这里展示它,因为它很好地捕捉了问题,虽然我会使用JavaScript而不是Boulay最初的1980年代Pascal语言。

想象我们有两个变量:

let a = "tea";
let b = "coffee";

一个初学者可能认为交换它们应该像这样简单:

a = b;
b = a;

但这不会按预期工作。

一旦a = b运行,两个变量都包含"coffee"。a的原始值"tea"已经被覆盖。当第二行运行时,a中不再有"tea"可以复制回b中。

正确的版本需要一个临时变量。临时变量提供了存储a副本的地方。

let temp = a;
a = b;
b = temp;

这个例子很有用,因为它展示了编程中顺序执行的严格性。

计算机不会保留学习者的整体意图。它不会想"他们可能想要交换这两个值。"它只是按顺序执行每条指令。如果前面的指令覆盖了一个值,那个值就消失了,除非程序员故意把它存储到其他地方。

这是经验丰富的开发者几乎不再注意的事情之一,但对初学者来说,这可能是一个真正的思维转变。

在正常交流中,人们不断推断我们的意思。如果我们解释时稍微顺序不对,另一个人通常可以填补空白。计算机不能这样做。它只是遵循指令的结构而不是指令背后的意图。

确实,注意我是如何将变量描述为"桶"的。du Boulay对这样的类比持批评态度。它们可以有用,因为它们给学习者一个具体的东西来想象,但它们也可能误导。一个真正的桶可以同时容纳几样东西,而一个简单的编程变量通常一次只容纳一个值。

所以在编程中,小细节真的很重要。

再看标点符号的例子,在编程中,小符号如括号、引号、逗号、冒号、缩进和分号可以完全改变代码的含义。

对初学者来说,这可能感觉荒唐。一个小标记怎么能破坏整个东西?

这与普通写作非常不同。在文章中,缺少一个逗号可能使句子有点别扭,但读者通常可以恢复原意。编程则宽容得多。

这就是为什么我坚信,初学者在变量、赋值或标点上挣扎,不是简单地"不擅长电脑"。他们在学习一个全新的符号系统,而这是一件困难的事情。

我很喜欢du Boulay将学习编程比作学习使用玩具积木套装(如Meccano)的类比。

学习编程就像学习使用玩具积木套装(如Meccano)来建造机构,但好像在一个黑暗的房间里,只能用非常有限的方式看到你创作的内部运作。
对不熟悉工程学的人来说,这种套装中的许多部件看起来很奇怪。虽然学习者可能对整套东西的整体用途有一些大致概念——造汽车和起重机等——但他或她可能没有意识到表面上不相似的机构如何被分解为类似的小块,以及套装中部件的形状如何适合构建这些标准块。

3、好的"包袱"

让我们把注意力转向我经常看到学生带到课堂上的一些好的"包袱"。

当学生来自某些领域时,有些人似乎更快地掌握编程,可能因为他们以前的学科已经"训练"了某些心智肌肉。

你可能听说过解决问题和其他认知技能是编程的重要组成部分。

例如,建筑师和结构工程师似乎经常有一点领先。我通常把这归因于他们的空间意识。

空间意识是理解和与你周围环境互动的能力。这是你感知结构、模式以及系统中不同组件之间关系的能力。人们常说,下棋、解谜甚至玩电子游戏等活动可以帮助增强空间推理能力。

这在编程中很重要,因为代码库不仅仅是指令的平面列表。它是一个由类、相互关联的函数、共享数据、依赖关系、可见和隐藏的假设以及随时间做出的决策组成的网络。能够理解这些部分如何相互关联,以及改变一个部分可能如何影响整体,可以说是有效编程中最关键的技能之一。

从这个意义上说,编程感觉有点像在物理环境中导航。它需要一种心理映射,类似于建筑师在AutoCAD中工作时使用的空间思维。

有研究支持这一点。研究表明空间技能与STEM领域(包括计算机科学)的成功之间存在正相关。例如,Sorby 2009年的研究发现,接受过空间训练的学生在工程制图和微积分课程中表现更好。所以并不特别令人惊讶的是,之前有其他STEM领域经验的学生在学习编程时也更有可能展现出才能。

Caughman和Weigel(2022)的另一项研究发现,生物学学生对数学和计算机科学的态度密切相关。换句话说,看到数学思维价值的学生也更有可能看到计算思维的价值。

但我要明确,这不是决定性的。远非如此。还有一个更大的因素在起作用。

我已经无数次说服那些快要放弃的学生坚持到底。

纯粹的决心是下一种能让你走得很远的好"包袱"。

这很重要,因为编程并不总是像,比如说,艺术课那样,努力和结果之间的关系几乎可以立即看到。在编程的早期阶段,你可能花几个小时努力工作,却几乎没有什么可展示的,只是与绝望建立了一段更亲密的关系。

是的,我确实相信有些人拥有某种天赋。编程界的贝多芬,如果你愿意的话。但在我遇见和教过的所有人中,他们只占极小的比例。事实上,如果编程只依赖罕见的天才,我们几乎不会有任何程序员!

这是因为,通过坚持参与这个过程,你会作为副产品发展出我们谈到的空间推理能力。

练习。接触。挣扎。重复。强调挣扎。这种体验并不总是令人愉快的。很少如此。但困难并不意味着无能。

这就是为什么我认为将编程与人类语言进行比较特别相关,尤其是学习外语时。

如果你曾尝试过,你会知道早期阶段感觉令人生畏。你不只是在记单词。你在学习语法、语法、语境、节奏以及那种语言独有的奇怪小规则。

你会担心犯错、被误解或不理解对方在说什么。

但这是正常的,对吧?你不会一开始就能流利地对话。慢慢地你会对语言的运作方式有感觉。

我反复向学生强调的一件事是,这段旅程不是线性的。它更像是一系列情感的起伏。

在第一个月,你可能感觉很好。你在写第一批代码,东西出现在屏幕上,你开始想,"这太棒了。我在飞翔。"

然后你开始学更复杂的JavaScript,突然就变成,"哦天哪。我在这里挣扎。"

然后,就在你开始掌握JavaScript、一切顺利的时候,你觉得我们会让你这么舒服吗?不。绝对不会。你开始学一个像React这样的框架,因为所有人都说这是正道。不用多久你就会想,"我讨厌React。"

但尽管当时感觉戏剧化,这从来不是世界末日。这就是过程的样子。你撞到一面墙,你努力通过它,你适应,然后下一个挑战出现。这不意味着你在失败。这意味着你在学习。

是的,它会很紧张。是的,很多情况下是你与你自己的较量。你需要纪律、耐心和毅力。

所以善待自己、对自己有耐心。挫败、低谷、突然"我讨厌React"的时刻,所有这些都完全正常。这是值得的。

一旦你打好了基础,你会惊讶于编程变得多么容易。甚至学习其他编程语言也会变得明显更容易。

如果可以的话,让我戴上教育学家的帽子,为可能正在读这篇文章的任何老师做一个简短的旁注。

我们确实需要注意我们如何谈论才能,更要小心关于谁"天生"擅长这个、谁不擅长的假设。

在你还没有得到公平机会之前就被判定出局,代价往往由代表性不足的群体承担:女性、有色人种和非传统背景的人,他们已经在为在科技界为自己争取空间而进行着艰难的斗争。

一旦学生开始相信自己不是那种"可以编程的人",这种信念可能比最初的困难更具破坏性。

有些人带着自信来。有些人来时已经吸收了技术不是为他们而建的观念。他们都属于这里。作为教师、导师甚至同伴,我们应该非常小心不要把起点与终点混淆。

4、你知道你的"为什么"吗?

另一个关键观察:在学生能够自信地专注于语法或解决问题之前,他们首先需要一种基本的目标感。

他们需要理解不仅是如何写代码,还有为什么代码很重要以及它能让他们做什么。

这是一个重要的观点,因为许多初学者不仅在编程的技术细节上挣扎。他们也在努力在这个学科中找到自己的位置,直到他们做到这一点,整个事情可能感觉很抽象和脱节。

所以问问自己,你为什么要学编程?

你想转行吗?创业吗?开发一个应用吗?自动化你的部分工作吗?制作网站吗?理解塑造周围世界的技术吗?或者你只是享受****解决问题并想要一个有挑战性的事情来提高自己?

没有一个单一的正确答案,但你应该有某种答案。

如果你难以表达你的"为什么",整个体验可能会感觉更困难。不是不可能,而是更困难。你的志向给了你在代码不配合的日子——正如我们已确定的,这绝对会发生——可以回归的东西。

在我的经验中,这在学生到达课程末尾的毕业项目时变得最明显。看到他们工作的可见成果时,他们通常开始更快地进步。当他们可以指着他们的作品说"那是我做的"时,有些东西改变了。

这就是为什么我认为一个自主项目是你在学习编程过程中可以做的最好的事情之一。

这是你深入你热衷的主题并创造独特属于你自己的东西的机会。

如果你没有想法,简单地问问自己,"我试图解决什么问题?"和"我可以做什么不同的事情?"最好的应用通常是那些解决你自己或你社区中特定问题或需求的应用。考虑与你产生共鸣的事情,以及你如何可能用技术来解决它们。也许是你比任何人都更了解的问题领域。要有创业精神。

你也可以考虑你有兴趣工作的行业。你的作品集是向潜在雇主展示技能的好方法。通过将项目集中在你想要工作的行业上,你可以使自己成为更有吸引力的候选人。

另一个值得考虑的很酷的事情是你想学习或加深知识的工具或技术。你的个人项目可能提供一个绝佳的机会来获得这些技术的实践经验,并再次让你更有市场竞争力。

我见过学生构建智能菜单系统、虚拟街机、本地羽毛球俱乐部计分工具、盲打练习游戏、未来火星殖民地投票系统、AI食谱生成器、识别废物和团结社区的应用,以及动漫和漫画发现工具。有太多酷的想法了。

5、房间里的大象:AI

好吧,我们终于到了讨论的这个节点,老实说我一直在回避到现在。

但是,如果我们不谈论AI,就不能对今天学习编程进行诚实的讨论。

作为一个在2021年到2025年间全职教授编程课程的老师,我亲眼见证了这种变化。天哪,它变了。

学生使用AI来解释概念、修复错误、总结课程材料,有时甚至在完全理解练习要求之前就完成了整个练习。我很确定ChatGPT在这段时间内对我们的课程计划变得非常熟悉。

这一后果在我的同事之间引发了激烈的辩论,我坚定地站在"这不是我们简单地许愿就能消失的事情"这一阵营。

那艘船不仅已经开了;它在甲板上开了血腥的香槟酒吧!

问题不是学生是否应该使用AI。他们已经在用了。更好的问题是他们是否以支持学习的方式使用它。

AI可以给学生在卡住、疲惫或不好意思再问同一个问题时有地方求助。

这比听起来更重要,因为气馁是学生退出的最大原因之一,记住我说的关于需要坚持到底才能成功的话吗?

所以在磨砺中是有价值的。

学习编程的早期阶段注定是令人困惑的。不是因为困惑是高尚的、有趣的或某种伟大的成年礼,而是因为挣扎是学习发生的地方。如果AI太快地移除了每一刻摩擦,它也可能移除让那些想法得以积累的重复和挣扎。

一个好老师不会简单地交出答案,如果你是自学的,你也不应该这样对自己。如果你在上课或上大学,抛开道德和抄袭问题不谈,你仍然只是在欺骗自己。

因为这个原因,我建议在编程之旅的前三到六个月至少避免过度依赖AI。你不会通过把每个句子都通过Google翻译来学一门新语言,不要对编程这样做。

我稍微涉猎了一些关于AI在教育中的影响的新兴研究。例如,Becker等人(2023)提出使用AI来支持代码审查,让学生接触到解决问题的多种方式。这确实有用,因为编程问题往往有多种有效的解决方案。

我同意这一点。真的同意。但前提是你已经打好了不错的基础。

AI最好的用途不是"帮我写这个",而是"帮我理解发生了什么"。学生可能会问,"你能解释这个错误信息但不给我完整答案吗?"或者"你能给我一个提示吗?"或者"你能问我一些帮助我找出下一步的问题吗?"这样使用AI,AI成为工作的一部分,而不是假装工作已经完成的一种方式。

然后还有一个更残酷的真相。

在工作场所,开发者绝对会使用AI。当然会。但专业开发者的价值不在于他们能生成代码。他们的价值在于他们能评判代码。他们能阅读它、质疑它、测试它、改进它,并理解它是否真的解决了面前的问题。

我的意思是,如果你不知道自己在试图要求什么,你怎么可能知道如何有效地提示呢?

6、指尖上的整个世界

"等等!有了AI我怎么可能学会编程"——这是我听到太多次的借口。

但这个世界不缺不涉及AI的学习资源。

书籍。文档。课程。教程。YouTube播放列表。MDN。Codecademy。Odin Project。博客文章。GitHub仓库。Stack Overflow帖子。哦,我可以一直说下去!

资源不一定只是一门课程、一个视频或网站,它可以是一个人。

与其每次卡住时都使用AI作为助手,为什么不与一个学习伙伴配对?你们坐在一起,讨论问题,轮流打字,解释你认为发生了什么,并互相发现错误。当你向另一个人解释你的想法时,你被迫整理它。当他们问问题时,你注意到空白。当他们解释他们的想法时,你看到了通过同一个问题的另一条路线。

这就是结对编程,在它最好的时候,它给了你AI不能完全复制的东西:情谊。你坐在一起,讨论问题,轮流打字,解释你认为发生了什么,并互相发现错误。独自卡住和与他人一起卡住之间有真正的区别。

学习编程的行为不需要是孤独的努力。如果你还不认识其他学习者,去找他们。Meetup等网站上的本地活动对此很有用,Reddit、Discord、论坛和课程社区等在线空间也很有用。我自己参加了很多技术聚会,总是对那些愿意走出去、提问和向走得更远的人寻求建议的热心初学者印象深刻。

如果你能找到一个导师,那就更好了。导师不需要是某个坐在皮椅上引导你命运的伟大正式人物。有时只是比你领先几步的人,他们可以看你的代码,回答一个问题,推荐一个更好的资源,或者让你安心——你卡住的东西确实很难。

7、并非所有编程教育都一样

这种学习的民主化无疑是一件好事,但它也带来了一系列新问题。

拿我上面写的那一大堆学习材料来说。

好吧,现在提供给有志向的程序员的材料的广度和深度是巨大的。

难怪人们最终陷入了通常被称为教程地狱的困境。

多样性当然可以有用。但太多的多样性可能变得令人瘫痪。这类似于心理学家Barry Schwartz所说的"选择悖论",即丰富的选项并不总是让我们感到更自由。有时它只是让我们焦虑。

有些学习者在实践性、基于项目的教程中做得更好,他们可以构建东西并通过试错学习。其他人更喜欢更结构化的、基于讲座的课程,先解释理论然后让他们应用。有些人需要视觉材料。有些人需要重复。有些人需要在任何东西奏效之前有一个真实世界的问题。学科的复杂性、资源的质量和学习者以前的经历都起着作用。

问题是初学者并不总是处于评判他们正在使用的东西质量的好位置。

这就是教程地狱变得特别残酷的地方。学生挣扎了,他们不想"也许这个资源没有很好地解释这个概念",他们想"也许我就是不擅长这个"。所以他们放弃了这门课,换到另一门,然后另一门,然后又一门,总是希望下一个教程最终能让一切开窍。

有时问题不在学生。有时解释不好。有时课程跳过了步骤。有时导师假设了学习者没有的知识。有时格式就是不适合那个人。

所以,如果你想逃离教程地狱,你需要用有洞察力的眼光来对待它。弄清楚什么真正帮助你学习。花时间找到适合你思维方式的家教、课程、播放列表、书籍或网站。把那个搜索作为学习过程的一部分,而不是对学习的干扰。

但如果有一件事能比几乎任何其他东西更快地把你从教程地狱中拉出来,那不是又一门课程。

那是一个好老师。

我教了多年编程,所以是的,我可能有点偏见。但我看到了这带来的差异。一个好老师不只是解释事情。他们诊断。他们发现缺失的步骤。他们注意到隐藏在虚假自信下面的误解。

也有研究支持这一点。

Benjamin Bloom是一位著名的教育心理学家,不是程序员,但他做了一个在教育界引起巨大轰动的实验。我不确定教育界之外的人有多关心,但在那个世界里,这是大事。它被称为两个标准差问题。

在1980年代,Bloom和他的团队研究了芝加哥公立学校的学生。一组学生通过传统的教学方法学习:讲座、考试、小组工作和通常的课堂设置。另一组学习相同的内容,但接受一对一辅导。这些学生在即时反馈下解决问题,只有在展示了概念掌握之后才继续前进。

Bloom发现接受辅导的学生远远超过了传统课堂组的学生。改进大约是两个标准差,因此得名两个标准差。实际上,这就像把一个平均学生从第50百分位移动到大约第98百分位。

这是一个惊人的结果。

这几乎与旧的"骆驼有两个驼峰"想法完全相反,该想法认为有些人天生适合编程而另一些人不是。Bloom的发现指向一个非常不同的方向。它表明,在正确的支持、反馈和逐步掌握下,普通学习者可以表现出色。

问题当然是规模。这就是为什么Bloom称它为问题而不是简单的解决方案。我们知道辅导可以非常有效,特别是如果是个性化的,只是不是每个人都能获得的。

但在编程教育中,我们经常看到这个的版本。

成功的训练营之所以有效,往往是因为学生不是独自留在一堆视频和练习中。他们有实时讲座、指导练习和定制的反馈循环。即使是强加的截止日期也能产生很大差异。

这在学习者超过初学者阶段后变得更加重要。

8、从教程地狱到教程高原

我最近读了The Odin Project创始人Erik Trautman的一个观点,他很好地表达了这一点。在他的文章《为什么学编程这么该死的难》中,他描述了初学者如何从高密度的资源开始,但一旦他们超越了手把手教的阶段,有用的指导就更难找到了。他称这个阶段为"绝望沙漠"。

任何从初学者跳到中级的人都知道这一点。一开始,每个人都想教你变量、循环、函数和如何做一个待办事项列表。但后来,当你试图构建一个真实项目、调试一个困难的问题或做出架构决策时,初学者友好的资源突然变得稀少。

这是你知道自己够多从而知道自己不够多的阶段。教程太简单,但专业文档感觉太密集。你不再问"什么是变量?"你在问"为什么我的认证流程在生产环境中坏了?"当你几乎不知道该用哪些词时,这是一个更难Google的问题。

最终,如果你坚持下来,资源会回来。你变得舒适于阅读文档、搜索技术博客、观看更深入的视频教程和提出更好的问题。但中间阶段是残酷的,因为挑战的一部分不仅仅是找到答案。它是学习问题到底是什么。

这就是为什么好老师、导师和学习社区可以使学习编程比其他方式更容易。他们帮助你弥合初学者材料和独立解决问题之间的差距。

9、抽象程度的提高

如果你还在跟着我,那么恭喜你走到了这里。如果你允许的话,我想做最后一点我认为不够频繁被提出的观点。

如果有人告诉你AI是唯一的游戏改变者,他们在撒谎。或者只是在这个游戏中不够久。

帮助编程变得更容易接触的一个有趣原因是编程语言朝着更高抽象程度的演变。

在编程中,抽象是简化复杂系统的过程,减少信息和细节以关注更高层次的概念。从低级语言(如汇编语言,更接近机器语言)到高级语言(如Python和JavaScript,更接近自然语言)的进步体现了这种抽象程度提高的概念。

这种抽象趋势对新手程序员的学习体验产生了重大影响。高级语言抽象掉了内存管理等复杂的低级任务,这可能对初学者来说令人生畏。

这也不是一个新关注点。Kelleher和Pausch 2005年的调查追踪了专为降低新手程序员障碍而设计的编程语言和环境的悠久历史。所以虽然AI可能感觉像是最近最具戏剧性的变化,但它位于一个更长的故事中:几十年来编程变得越来越可访问,部分因为我们用来编写代码的工具已经改变了。

10、所以到底是难还是容易?

好吧,这取决于我们的意思。

我试图在这篇文章中保持诚实。学习编程可能不像以前那么困难了,原因我们已经看到了很多。工具更好了。语言更易接近了。资源无处不在。AI可以帮忙。社区存在。进入的途径比以往任何时候都多。

但你可能注意到几乎每个优势都伴随着一个缺点。

更多的资源可能意味着教程地狱。更容易获取的工具可能把复杂性隐藏到后来。AI可以支持学习,但它也可以替代学习所依赖的挣扎。高级语言可以使起步更温和,但它们不能消除需要清晰思考、耐心调试和构建正确的心理模型的需求。

所以是的,学习编程是难的。

但它以一种许多值得做的事情的难的方式难。

它不是难因为只有一种特殊的人能做它。

它难因为它要求你以不同的方式思考、容忍困惑、反复犯错,并坚持


原文链接:Is Learning to Code Hard? What Years of Teaching Taught Me

汇智网翻译整理,转载请标明出处