我在必修的入门编程课程中有一些计算机科学专业的学生,他们将编程语言视为一组魔术,必须对其进行浇铸才能达到某种效果(而不是将其视为表达解决方案思想的灵活媒介) 。
他们倾向于从以前看起来相似的作业中复制粘贴代码,而不考虑问题的实质。
是否有一些练习或类比使这些学生更加自信,他们可以并且应该理解他们编写的每段代码的结构和含义?
我在必修的入门编程课程中有一些计算机科学专业的学生,他们将编程语言视为一组魔术,必须对其进行浇铸才能达到某种效果(而不是将其视为表达解决方案思想的灵活媒介) 。
他们倾向于从以前看起来相似的作业中复制粘贴代码,而不考虑问题的实质。
是否有一些练习或类比使这些学生更加自信,他们可以并且应该理解他们编写的每段代码的结构和含义?
Answers:
您可以向他们展示一系列练习,每个练习都基于上一个练习,同时增加一些额外的元素或扭转问题,或者从不同的角度调查问题,这揭示了先前解决方案的弱点,需要一种新的,不同的方法。这迫使他们思考,分析,修改和试验每种解决方案,而不仅仅是复制粘贴现成的代码。
尽管不是严格的编程任务,但另一种可能性是要求他们估算各种事物。例如,每秒有多少水流经密西西比河三角洲?这样的问题没有固定的答案,尤其是因为一个人需要做出一些假设才能达到令人信服的(范围)值。而且-尽管可以对许多“经典”问题的答案进行谷歌搜索-您仍可以轻松地组成尚未在网上找到的新问题。
这两种练习的示例都可以在Jon Bentley的《Programming Pearls》中找到。此外程序员修炼有一些很好的挑战。
第三种任务是向他们提供一些代码(其中包含(一个或多个)错误),他们必须找到并修复这些错误。这再次迫使他们使用他们的分析技能和程序实际工作方式的原因。
Billy ONeal的评论反馈:
“一系列练习”的问题在于,对较早的练习有疑问的学生完全无法参加其余的练习。
您是对的,尽管我觉得这更多是关于将课程难度设置为正确水平/将相似技能水平的学生分组在一起的普遍问题。而且,可以将学生分成小组,在其中他们需要讨论和辩论问题和解决方案,并共同解决问题。如果有人不了解,其他人可以提供帮助(此设置也将提高团队合作技能)。而且,如果有人试图变得懒惰,而让其他人去做所有的工作,那肯定会被老师注意到(他应该走来走去,监督和指导学生,而不是在角落里的笔记本电脑上玩魔兽世界;-)
还可以调整练习以适应具有不同技能水平的学生。初学者可以慢一些,有经验的可以更快一些。
您正在与学生的平衡行为作斗争,因为他们需要关心您的科目以及获得及格分数的需求。许多学生认为:
一旦学生感到自己的时间或成绩处于危险之中,即使是对一个有趣的学科,他们也会停止学习,直接跳到“我不在乎,只给老师正确的答案”。您的学生试图通过尽可能少地思考问题并通过复制和粘贴来解决问题,从而开辟道路(或他们认为)。
这是我关于如何处理此问题的建议:
&&
-尽管我怀疑它也可以按位操作成功。
我想到的几件事:
给他们分配作业,他们实际上必须解释别人(您)编写的代码。理解先前的代码,或者更确切地说,缺乏代码既是造成货物崇拜编程的最大原因,也是最大的危险。要求他们使用注释,必要时逐行注释,以简明的英语(或您使用的任何一种人类语言)解释您的程序。
只有在他们解释了代码之后,才要求他们对其进行修改以进行某些更改。例如,如果您给他们提供了一个对降序进行排序的排序功能,请让他们使其升序排序。或更苛刻的要求。但是请确保这是需要理解给定代码的内容。
如果愿意,可以在代码中放入一些复活节彩蛋。一两行根本没有用,甚至根本与问题无关。给他们一个暗示,即存在这样的行,并为那些删除行的人加分。
然后只有这样,您才能给他们分配作业,以便他们自己从头开始编写一段代码。此时,他们应该对什么是真正的代码有更好的理解。他们甚至可能会觉得自己做起来容易一些。
基本思想是编程不仅是编写代码,而且还在阅读代码。阅读代码也应该教。
用另一种方式看。这种狂热的现象是技能获取的德雷福斯模型的新手阶段。这就是我们学习的方式。当我第一次学习编程时,我所做的只是从Compute的后面输入代码页面!杂志。重复是关键。婴儿通过复制父母听到的声音来学习说话。我们学到的一切都是通过模仿。我们只需要教我们如何从模仿变成精通。
您遇到的问题是您的学生没有重复任何东西,而是从Internet复制它们。这样做有一些好处,但是收益很小。实际输入代码的行为使我产生了理解。我开始看到键入内容的模式,并且对自己的工作有所了解。
一种选择是将您的实验室构建为代码dojo。让学生轮流对同一个问题进行配对。选择一个大约需要10到15分钟才能解决的问题。在一些实验中重复该问题,并随着班级水平的提高而对该问题进行新的调整。也许通过让学生看着您编写解决方案并让他们重复来开始实验。每次迭代切换对。
为了给您的考试做准备,有一个代码kata,每个学生在课程其余部分的学期中解决所有问题。不仅要关注正确性,还要关注形式和创造力。我认为这比带回家作业更深入地了解如何编程。
我过去曾经教过入门课程,现在回想起来:
一些学生认为编程是出于不同的原因。我记得曾经有个好孩子,对我的所作所为大为熏陶:
我相信这不是一个孤立的问题,但是同一班上的其他学生可能有类似的行为或对问题的处理而没有表现出来,所以我一直在向全班讲话。
花了一些时间来解释诸如确定性之类的东西,这对他们来说意味着在相同的环境中使用相同的数据和代码,它们将具有相同的结果(消除“随机性”),
由于解决问题的能力取决于学生的行为,而不是其他任何事情,因此应该将注意力放在解决问题上,而不是找到正确的咒语,
他们处于教育环境中,因此精心设计问题以提供学习经验,其结果是学习如何编程(或在某些情况下,例如系统管理员的课程,程序如何工作,这是不同的),而不是给我一个解决方案。(“世界不需要另一个计算器,这是一种练习”),因此可以使用可用的材料(例如:提供的注释)解决其问题,
我认为它在“代码完成”中:“即使复制和粘贴,代码也属于您”。如果有人这样做,那它就不应是货船式的。每行都必须向我(单独)或向另一名学生(相同)或全班解释。
您的学生在课程开始时是否以正确的“抽象程度”开始?例如,一项无需编写任何代码即可将其介绍给主要编程结构(如循环和条件)的作业?
当我开始编程时,我们的第一个作业称为“ 机器人瑞克 ”。我们有一张纸,上面有一个城市的航空地图,上面有很多有趣的地方,例如银行,杂货店等。我们有一个叫做“里克”的家伙,并且有“迈出一步”,“向左看”, “看起来正确”,“过马路”,我们可以使用“重复”和“如果有的话就做某事”之类的东西。(这不是100%,因为我找不到此任务。)想法是Rick只能使用他得到的东西,而他必须到达地图上的其他地方。
这是一个有趣的练习,它向您介绍了一些基础知识(有时对新手来说最难掌握)。没有一个很好的答案可以解决这个问题(它是一种游戏),也没有从中复制和粘贴的解决方案。这样的事情也可能使您可以更多地发挥他们的创造力,而不会用代码吓倒他们。
最后,您的想法是从抽象开始,然后走向具体。他们无法复制粘贴摘要。他们必须了解它才能解决问题。
while not at-corner do take-one-step end
不“回填”变量和数据类型的情况下从实际代码过渡到实际代码。抱歉,我对反思的反应似乎有些苛刻。
您要他们做的是在Bloom的Taxonomy的认知领域演示分析和综合,而他们目前仅在演示应用程序。
不幸的是,这是一种“牵马入水”的情况。当您仍然难以理解时,分析和综合也非常困难。如果没有适当的理解,分析和综合活动将比学习活动更像杂草。
我个人的观点是,除了编程类入门中的应用程序以外,别无所求。这是学生们第一次接触到这些概念,因此就像在要求孩子写论文之前教孩子阅读一样。这些更高阶的技能将在以后的课程中学习。
if
语句的工作方式,并能够在继续之前从头开始编写自己的语句。使认知部分起作用,然后继续进行应用。
您是否考虑过为他们提供一些代码?不管需要什么简单的脚手架,例如一个空的main函数(我都不知道您使用的是哪种语言)。可以编译,运行并且什么都不做的东西。然后,他们可以开始自信地添加代码,以确保至少部分代码可以正常工作。
实际上,这在“现实世界”中非常普遍。许多IDE和其他工具都使用典型的库/模板/配置文件来创建空项目。
任何形式的货运邪教心态(包括货运邪教本身)都是由于对所涉及的技术缺乏基本了解。
不应将货物崇拜式编程视为一种有问题的习惯,而应将其视为程序员所面临的潜在混乱的症状。
更重要的是,从根本上来说,认为学生缺乏理解只是学生缺乏自信的产物是错误的,不能解决根本的问题。
取而代之的是,该学生的复制粘贴编程风格应该是一个危险信号,告诉您该学生对他所希望做的事情的复杂性感到不知所措。
他本能地将过去的工作用作构建当前项目的基础,并试图以先前解决的问题为基础来构建解决方案。我们都在一定程度上做到了这一点,但是我们大多数人都是通过使用从过去的工作中获得的知识作为我们的基础来做到这一点的。相反,这位学生正在使用作品本身,这意味着他并不真正了解自己正在使用的模块。在他的理解范围内,他分解了工作,并且将大代码块视为原子单元,因为他不了解它们的工作方式。他只知道他们在做什么。
在编程世界中,我们很少真正为出现的每个解决方案创建新项目。大多数时候,我们会修改旧的。
将您对项目的想法从每个作业的一个解决方案更改为整个学期的一个解决方案。每个作业都基于先前的作业。
项目:建造电梯系统
关键是您是在先前的分配上建立的,而不是为新任务回收旧的分配。
考虑使用需要最少样板代码的高级语言。
对我来说,通常是大型框架或冗长的语言中的样板代码,感觉像魔术一样,阻碍理解。
我在CS入门编程课程中亲自教过ML。多年以来,Lisp在麻省理工学院教授编程入门。两者都是绝佳的选择。他们拥有的一些好处是
我对80年代的新手程序员的问题做了一些研究。根据我今天与新手程序员的经验,并没有太大的改变。新手对计算机的实际功能没有有用的思维模式。他们诉诸魔咒,因为机器本身就是魔咒。
编程需要将自然简单的任务分解为不自然的小步骤。由于新手在日常生活中不会处理如此精细的粒度,因此他们很难弄清楚应该使用哪些小步骤,尤其是在不清楚机器可以使用哪些小步骤时。但是,即使他们设法弄清楚了这一点,他们仍然面临着通过远程控制神秘机的编程语言(一种伪装成准自然语言的非自然语言)的语法和有限的语义。
由于他们无法在问题的逻辑解决方案与机器功能之间建立联系,因此他们专注于满足语言要求。第一个目标是写一些可以编译的东西。第二是调整该程序-不管它实际做什么-防止它崩溃。然后,如果他们有时间,精力和兴趣,他们将尝试使程序产生类似于问题所需结果的结果。一路上,他们可能会不小心产生编写良好的代码。
确实学会编程的新手很可能会成功,因为他们推断出了有用的计算机思维模型,而不是因为有意为其提供了一个模型并将其内部化。
您可以问他们有关需要书面答复的代码段的问题吗?就像“这段代码在做什么?” “程序员为什么要这样解决?” “还有更好的方法吗?”等等?
这实际上会使他们思考问题,这是他们甚至无需接触代码即可完成的工作。
与JoelFans想法类似,是让他们使用您创建的伪代码(语言)在纸上进行初始分配。您可以根据需要添加结构,而不必担心魔术盒。
我要假设“货运邪教”是指他们插入了认为必要的内容,但实际上对解决问题没有任何作用。
如果是这种情况,您总是可以在基于简洁的评分中添加一些因素-将来在程序中留下不必要或多余的代码可能会出现问题,因为它可能会破坏或使维护变得更加困难。
在英语课堂上的写作练习中,对他们的判断也类似。没人会想要那些随机切线出现的东西,或者只是到处乱逛而已。
当我参加汇编课时,如果他想让我们编写速度,大小或内存使用量的代码,老师会告诉我们每一个练习,如果您没有接近优化他所要求的内容,他会打勾。对于。
...
如果它们是从以前的类似分配中复制并粘贴代码,并且实际上是解决新问题的方法……那么,那只是代码的重用,除非他们对代码的重用性做出了错误的假设。 ,我认为他们这样做是完全合理的。(例如,从文件中读取内容,作为输入的支撑……所有可以重复使用的模块化部件。如果您不希望它们这样做,则需要使练习变得不同。
不幸的是,这就是许多人大脑运作的方式。因此,请进入这种了解,有些人您无法“治愈”这一点。有很多人无法在编程所需的心理精度水平上工作。有些人根本不是为它设计的。我并不是说要放弃学生,而是要假设如果不是每个人都接受了,你就会失败。
在不了解更多有关班级背景的情况下,我想将更多的注意力放在这些有问题的学生身上,这是最基本的结构- 简单的 if / thens,循环等。简单的例程可以打印出奇数,十分之一的数字等。每行超过10行代码。如果他们是“魔术思维”,他们显然还没有掌握这些基础知识。让他们执行许多不同的简单例程,直到他们掌握正在发生的事情。有人提到将代码写在纸上-我认为这也是执行这些简单例程的好方法。
您也可以考虑让他们学习流程图。对于某些人来说,能够看到算法的流程,然后查看其与代码的连接方式,可能会对他们将代码连接至流程有所帮助。
理想情况下,在第一堂课中,从完全抽象的内容开始:让他们(作为一个小组,由您作为领导者)从清单中写出有关如何进行杂货店购物的说明,并逐步分解高级说明直到他们得到启示。
告诉他们这些指令将由字面意义上的机器人执行,该机器人不知道如何推断事物。但是,这必须是一个非常动手的活动,您需要负责指导它们。
Alistair Cockburn在http://alistair.cockburn.us/Shu+Ha+Ri上讨论了Shu-Ha-Ri的概念及其在编程中的应用。我认为牢记您的学生在这个连续体中的位置可能很重要。首先,这将有助于减轻您的一些挫败感。当您第一次开始学习某些东西时,复制/模仿是一种很自然的回应和接受的方式。其次,它可以帮助您获得一些有关如何前进的想法。例如,您可能要考虑选择可以以多种方式解决的问题(循环与递归,控制台与Web / gui),然后明确让他们首先以一种方式解决它,然后以另一种方式解决-他们可以学习的好处关于合法的代码重用,组件化,创建可重用的库等。
我见过的另一种成功的方法是让一系列项目相互构建,在完成分配任务后的每一步都提供一个默认的工作版本,以防止人们落后。该过程的每个步骤都应引入一些新内容。我会告诉您,这在设计类中比在编程类中做起来容易,但是仍然应该可行。一件好事是,您明确地给了他们一个良好的(希望)实现,以便在每个步骤中与他们进行比较。将此比较作为一项任务公开,即对照自己的努力对自己的代码进行迷你代码审查。您可能希望将此作为几种额外的信用选项之一。
尽管我通常对“注释”并不了解,但是您可能希望将代码文档作为成绩项之一。让他们为每个项目生成一个“操作理论”文档,其中描述了他们的方法,每个组件的安装方式以及它们如何共同解决问题。通常,我希望代码自己完成很多工作,但这会促使他们放下思想上的限制并付诸实践。
最后,您可能想要发挥创造力,并让您的学生复习彼此的代码并进行评估。施加同伴压力为您工作。允许它成为评分最高的代码(和文档)的等级或额外的学分。
只是一个快速建议。每当我遇到需要解决或调试的编程问题时,我都喜欢看我的代码和“玩计算机”,在我的脑海中,我会跟踪变量及其值以及每行运行时的期望值。因此,如果我从某个地方复制了一些代码,除非它本身是完整的,而我只需要引用它,我喜欢一行一行地去了解到底发生了什么。本质上就是玩电脑。VBA调试器从本质上使此任务更容易,但让您的学生在纸上完成它可能会给他们一些基础知识。这条线实际上是做什么的?
我在大学期间教授入门编程。这是一门简陋的课程,所有的老师都做到了,我认为我们做得很好。我们遵循共同的文本并进行了共同的考试,但是我们每个人都有适合自己的课堂方法。从那以后已经有很长的时间了,但是偶尔我会教一些孩子编程,整个过程是差不多的。
我这样做的方法是从底部开始,尽可能具体。学生所知道的是一种结构。他们已经有很多概念。我将在这些概念的基础上进一步构建概念,并删减可能形成的适得其反的概念。同时,我让他们边做边学。
我用一台Intel 8008芯片,一些EPROM和一些电路构建了一台小型计算机。当I / O芯片连接到一对扬声器时,我已对其进行编程以使其具有一点二重奏效果。我将解释这个小程序是如何工作的,并带有一个内部循环来计数计数器。那将是一个延迟。然后它将切换输出位并再次执行。它将执行一段时间,然后切换到另一个延迟,给出另一个音高,依此类推。内存芯片上有一个小计时器,如果我在一个计时器输入的下面塞了一条电容引线,程序将缓慢运行。班级可以听到演讲者的点击声,点击声,点击声...我希望班级理解计算机一次只做一件非常简单的事情。然后,我将摘下电容器导线,然后发出“音乐”。(掌声)
然后,我为一个非常简单的十进制计算机构建了一个模拟器,该计算机具有1000个存储单元,每个单元都有一个带符号的4位十进制数字。它具有非常简单的操作码,例如“添加到累加器”,“如果为负则跳转”,等等。我会让他们用这种“机器语言”写一些小程序,例如加两个数字或加一个数字列表。然后他们可以单步观看它的运行,或者按住Enter键以观看它“快速”运行。
这样做的目的是要提出一个概念,即计算机只能执行非常少量的不同基本操作,并且它们一次只能执行一次。这是为了抵消他们的印象,即计算机很复杂,并且它们同时执行所有操作,并且讨价还价。
从那里开始,我们以“真正的”语言(BASIC :)进行编程,从非常简单但有趣的程序开始,直到条件,循环,数组,文件,合并等等。目的是要设置足够的技能,以便他们可以自己选择一个项目,因为这是使编程有趣的唯一原因-可以使用它。我会提出一些项目构想,然后他们会从那里采纳。我会要求提出书面意见,然后提出进度报告,以免将报告推迟到最后一分钟再引起恐慌。我认为项目是最好的部分,因为它们是在自己的力量下学习的。
最初基于对计算机的功能的非常具体的了解,使得以后更容易讲授概念,否则它们将是真正的减速器,例如数组或指针(在以后的课程中)。我们倾向于赞美“抽象”这一奇妙的东西,但是它需要建立在一个具体的基础上,而不是在空中。
一个自学成才的程序员,我相信动画在了解代码的作用方面是最具挑战性的。当程序包含执行抽象操作的算法和数学转换时,了解数学在任何给定时间点(除非您是天才)的唯一方法是需要了解代码本身的执行。
如果我的天真想法不正确,请纠正我。您想做的是not
阻止学生使用“设计模式”,而是找到一种方法来确保他们了解CnP是什么?然后挑战学生操作动画。为了调整动画中的输出,必须了解每个步骤中发生的情况。出于您所说的关注,我想一个精心构思的动画项目会在学生“明白”后以明显的方式体现出来-当他们意识到您所不期望的转换或调整了某些相关的,相互依赖的变量时。
在不了解您所从事的教学限制和目标下,我不能说动画是完整的答案。我应该冒险猜想,动画专业以外的整个动画课程都是不可能的。几个项目可能仍然会带来一些巧妙而美妙的事情,这还不错。
在另一个音符上,我读了一篇报纸文章(是的,纸!),这是针对高中水平的编码奥林匹克运动会的 -wot-wot-竞争学院前程序员。关于他们所面临挑战的描述是我记得曾经读过的最纯净的编码。根据良好实践标准对竞争对手进行评判。对于这些竞赛,学生必须既要计划解决方案,又要手工编写问题需要在时限内完成的基本“设计模式”。因此,解决有关CnP编程问题的方法是测试学生是否可以编写与CnP'n相同的“代码块”!
我确定这是在《纽约时报》上。快速搜索未找到它。一个类似的例子是ACM的国际大学编程竞赛。该竞赛强调快速编程:“团队竞赛中的快速编程是一项非常古怪的技能,并不是很多求职者都将其放在简历的顶端。” 因此,我建议从实际问题中抽象出来就是答案。
也,
使用技术上不错的编程语言来授课,但这种语言太晦涩,无法找到要复制的任何现有代码。
我怀疑这种行为是因为人们相信程序是魔术,更可能是由于懒惰和缺乏动力。
因此,我认为您作为老师的工作是为了激发学生的动力-真正有动力的学生不会削减并粘贴解决方案(仅适用于有期限和底线的工作程序员才能见面...)
教子程序。让他们采用以前分配的代码,并将其转换为子例程。教他们有关功能文档的知识,以帮助他们了解子例程的实际作用。
切勿给他们类似的任务。
或者,更疯狂的是,从一开始就向他们学习TDD。它推动编写(而不是复制,编写)大量代码(即测试),这些代码实际上有助于制定所要解决的问题。
我发现对班上的人们有很大帮助的事情是,在他们可以选择的主题上编写一个小型项目。
当我开始编程时,对我来说也很困难,而且我确实在课堂上做了很多抄写。然后在家里,因为我想成为一名游戏程序员,所以我开始制作一些小游戏,并且发现它们变得更容易制作。即使他们要难得多,但还是我们在课堂上看到的东西。只是因为它对我感兴趣。
我班上的其他一些人的考试比例从40-50%上升到90-100%,因为他们做的完全相同。