谌卫军
摘要:提出一种基于能力培养的程序设计课程教学方法,将程序设计过程分为3个步骤:问题分析、算法设计和编码。针对问题分析提出案例教学方法,以案例的形式阐释问题分析的过程和技能;针对算法设计提出编程模式的概念,这是自顶向下设计技术的一种具体实现;针对编码设计并实现一个功能强大的在线训练系统,为全面提高学生的动手实践能力提供技术上的保证。
关键词:程序设计;案例教学;编程模式;在线训练系统
0 引言
随着信息技术的不断发展,计算机被广泛应用于各行各业。熟练掌握一门计算机程序设计技术已经不仅仅是计算机专业学生的基本要求,而是所有大学生尤其是理工科学生需要掌握的一种技能。在多年的教学实践中,笔者深刻地体会到程序设计类课程与传统课程有很大区别,而现有的一些教学方法和教学理念也存在某种误区。
首先,大部分选修程序设计课程的学生都是大一新生,以前从未接触过编程,因此不太了解程序设计的特点,不知道如何学,可能还是沿用中学时代的学习方法,容易走弯路。笔者在每个学期的第一堂课都会进行一项调查,将班上所有学生按照编程基础分类,从调查结果看,大部分学生在选修该课程之前没有任何编程基础,不知道应该怎么学。事实上,从历届学生平时的提问也可以看出,他们经常问的问题是标识符的意义、运算符的功能、for语句中的表达式能否使用嵌套的表达式等。学生主要将注意力放在了编程语言的语法细节上,以为每一个知识点都非常重要,而在实际的编程过程中,这种语法细节没有太大意义。
其次,在讲授程序设计类课程时,一些教师的教学理念和教学方法也存在误区。一般来说,程序设计类课程主要讲授两个方面的内容:编程语言的语法知识和实际的编程技能。其中,编程技能最重要,学生学习程序设计课程的最终目的就是在碰到一个实际的编程问题时,能够设计出相应算法并编写出正确代码,最终解决这个问题。然而,在实际教学过程中,一个常见的现象就是教师把教学重点放在了编程语言的语法知识上。在课堂上,教师会详细讲授每一个语法细节,然后用一些小例子演示语法的使用方法;在平时练习和期末考试中也采用传统的考核方式,用选择题、填空题和问答题等题型考查学生对语法知识点的掌握情况。
总之,对于程序设计类课程,由于各个环节都可能存在一些不足,容易导致学生陷入眼高手低、纸上谈兵的误区。事实上,在教学过程中,笔者最常碰到的问题就是学生对C语言的语法非常熟悉,然而一旦要编程解决一个实际问题就无能为力。
1 相关工作
国外一些研究表明,在学习程序设计时最重要的技能是问题分析和求解,这是一种思维层面的、抽象的技能,也恰恰是学生所欠缺的,而且这种技能不像具体的语法知识只要简单地传授即可,它需要培养和训练。文献[1]指出很多学生尤其是大一新生最缺乏的就是问题分析与求解能力,而对于教师而言,讲授语法知识比较简单,因为这些知识都是固定的,是一条条的规则,但要想让学生提高分析问题、解决问题的能力,难度就会大很多。文献[2]指出在一门计算机课程中,学生的薄弱之处就在于问题分析和求解技能,因此课程的重点必须放在这种能力的提高上。文献[3]通过采访计算机科学系的5位教师,发现大部分学生都想当然地认为自己具有问题分析和求解能力,而不能发现自己在程序设计中的弱点。
那么如何提高学生的问题分析和求解技能呢?文献[1]提出一种自顶向下的设计技术,基本思路是把待求解的问题用一组类似于英语的伪语言指令描述,然后一步步地优化、细化该程序。文献[4]中也指出在编程过程中,自顶向下的方法非常重要,应该把一个大问题分解为若干个可以管理的小问题,分别求解每个小问题,然后将结果综合在一起,从而得到原始问题的求解方案。
笔者认为自顶向下的设计技术毫无疑问是一个非常实用、有效的方法,但问题在于如何具体实现。对于程序设计来说,最主要的是如何才能把一个复杂问题分解为若干子问题,然后将它们组合在一起。问题的分解本身就是一种技能,学生可能知道要分解,但并不知道该怎么分解。此外,对于分解后的子问题,有些学生可能还是不知道该如何解决。
在程序设计过程中,除了问题分析和求解技能外,还有一项重要技能就是代码编写。文献[5]指出学生在编程时会把自然语言中的一些用法不恰当地体现在编程语言中,从而导致程序出现各种问题。文献[6]指出编程的难点并不在于编程语言的语法,事实上,学生即使精通语法,也仍有可能无法写出正确的代码。为了提高学生的编程能力,主要的方法就是加强训练。
2 教学目标和理念
基于多年的一线教学经验,笔者对程序设计课程进行了教学改革,基本目标是通过教学内容、教学方法、训练方法和教材等多方面的改革,帮助学生在学完该课程后能够切实提高编程技能,解决实际编程问题。换言之,不能把目标局限在掌握低层次的简单语法知识上,而是要瞄准高层次的抽象思维方式以及如何提高学生的能力和素质,这才是最重要的。
在教学理念上,要坚持以学生为主体,采用启发式教学,充分调动学生的主观能动性和创造性,鼓励他们自己写出算法。事实上,程序设计类课程为学生提供了一个灵活、可自由发挥的平台,这个平台上没有权威,也没有标准答案,对于任何一个程序设计问题都存在着不同的解法,“条条道路通罗马”。因此,学生可以充分发挥自己的想象力,运用所掌握的基础知识设计出各种与众不同的解决方案,而这也正是创新能力的体现。
总之,笔者认为上述教学目标和教学理念符合现代教育教学的客观规律,符合高校的人才培养目标。
3 教学方法
基于多年的教学经验以及对程序设计课程的思考和理解,笔者提出一种基于能力培养的程序设计课程教学方法。程序设计类课程教学框架如图1所示,该框架源自笔者对程序设计过程的理解,即编程模型。
图1中,计算机程序设计可以看成是把一个文字形式问题的描述转换为相应的源代码。整个过程可以分为3个步骤,即问题分析、算法设计和编码编写。由于每一个步骤涉及不同的技能,因此需要采用不同的教学方法。具体来说,在问题分析环节使用案例教学的方法;在算法设计环节使用编程模式的概念;在编码环节设计并实现一个在线训练系统。endprint
3.1 问题分析
问题分析是程序设计的第l步。一般来说,一个编程问题的描述就是一段自然语言句子,如果学生没有受过良好的训练,就不知道如何分析问题,如何在这些句子中找到有用的信息。因此,问题分析能力是程序设计中的一项重要技能,但是学生却很难获得这方面的帮助。一方面,大量的编程书籍主要是介绍编程语言的语法,很少有材料讨论如何分析问题;另一方面,通常的程序设计课程也不讲这些内容,认为这种分析问题的能力与生俱来。实际上,学生的最大问题并不是看不懂题目,而是不知道该做什么和如何做。
如何解决这个问题?基本思路是把问题分析方法也作为课程内容的一部分,要有意识、有针对性地向学生讲授这部分内容。在具体实现上,笔者采用案例教学法,在课程讲义中集成20多个编程案例,通过案例的形式向学生展示问题分析的技能。所谓案例并不是传统意义上的一个个简单的编程小例子,也并不是附属于某个语法、为了阐释某个语法的使用方法而引入的,案例必须经过精心设计,具有独立、完整的内容。引入案例的目的并不是为了解释语法,而是为了向学生阐释某一类编程问题的分析方法和解决方法。一般来说,一个案例需要具备以下4个特点:
(1)具有一定规模,同时考查多个知识点;
(2)具有完整的内容,包括问题分析、算法设计、编码测试、题后讨论等多个环节;
(3)具有一定难度,富有挑战性;
(4)生动有趣,能吸引人。
例如,笔者的课程讲义中有一个案例是“猜数字游戏”,问题描述是“编写一个程序,由电脑随机产生一个数字不重复的四位数,由玩家猜,每猜一次,电脑将显示形如*A*B的结果,其中A代表位置正确数字也正确,B代表数字正确但位置不正确,如2A2B,表示有两个数字和位置都正确,两个数字正确但位置不正确,总共有10次机会”。这个案例来源于真实的游戏,一些手机、PDA等终端设备上都有该游戏。该案例既具有趣味性,又有一定难度,富有挑战性。
对于每一个案例,笔者不是简单地列出源代码,然后为学生解释,而是着重于问题分析和解题的思路。以“猜数字游戏”为例,如何从编程的角度对其进行问题分析呢?所谓问题分析,就是对问题描述进行仔细研究,明白它的真正含义,然后抽取出需要解决的问题,将大问题分解为小问题,引导学生建立这样的观点:先不要想怎么做,而是先想清楚需要做什么?需要解决哪几个问题?对于上述例子,经过问题分析,实际上需要解决3个技术问题:
(1)如何随机产生一个数字不重复的四位数?
(2)对于一个四位数,如何将它的每一位数字拆分出来?
(3)对于玩家猜测的一个四位数,如何计算相应A和B的数量?
总之,对于每一个编程案例,笔者都会进行问题分析,讲清思路演变的过程,久而久之学生就慢慢地掌握了这项技能。
3.2 算法设计
经过问题分析之后,学生就知道了需要做什么并会将大问题分解为几个小问题,接下来就要进行算法设计,即如何解决这些问题。算法设计也是程序设计中的一项重要技能,是解决问题的关键步骤,但是一方面,大部分学生以前没有任何编程基础,不懂算法设计;另一方面,在通常的程序设计课程中,学生又得不到这方面的训练。这样导致的结果就是当学生拿到一个题目以后,虽然能够看懂,但是完全没有思路,不知道如何下手。
为了解决这个问题,笔者提出编程模式的概念。这个概念来自于中国武术中的“套路”,即对于一名武术选手,他平时的工作就是学习和练习各种各样的套路,然后在与其他选手进行比赛时快速作出决定,在何种情形下应该使用何种套路。这正是一个新程序员在面对新的编程问题时应有的思路。因此,可以对一些常用的算法思路进行归纳和抽象,得到编程模式。
编程模式具有如下3个特征:
(1)独立性:编程模式独立于具体的编程问题,它是一组相似问题的归纳和概括;
(2)可重用性:一个编程模式可以应用在不同的编程问题中,可重用性是编程模式最重要的特征;
(3)抽象性:一个编程模式是一个算法的抽象,它的实现独立于具体的编程语言,换言之,无论是C、Java还是其他编程语言都能使用。
典型编程模式的例子包括计算一组数据之和、寻找一组数据中的最大值或最小值、计算一组数据中每一项的出现频率等。以“频率计算”编程模式为例,它可能出现在不同的编程问题中。以下是一些例子。
(1)在一个电视选秀节目中,观众将通过手机投票的方式评选出十大歌手,请编写一个程序,帮助组委会统计每一位歌手的得票数;
(2)编写一个程序,统计在莎士比亚的所有作品中每一个英文单词的出现次数;
(3)有一种文本加密方式是字母映射,即将一个英文字母映射为另一个英文字母,这样原本有语意的句子就变成了一个杂乱无章的字符串,但这种加密方式可以通过统计字符出现的频率破解,请编写一个程序,统计在英文文本中26个字母的出现频率。
以上这些编程问题表面上似乎各不相同,但实际上它们能够使用相同的编程模式求解。有了编程模式以后,当学生再碰到一个新的编程问题时,虽然从表面上看该问题是新的,以前没有见过,也不会做,但是可以采用上述自顶向下的分析技术将它分解为若干子问题,而每个子问题可以用以前曾经学过的某个编程模式解决,最后再将它们综合在一起即可,这样学生分析问题、解决问题的能力就得到了提高。
笔者提出的编程模式概念实际上是国内外研究者提出的自顶向下设计技术的一种具体实现。通常的自顶向下技术只强调了要分解,但对于如何分解、分解到何种程度、分解以后的子问题如何解决等问题则没有明确说明。笔者的改进主要体现在两个方面:一是使问题的分解更具有可操作性,分解的原则或目标就是该子问题的大小合适,学生能够解决;二是对于分解以后的子问题,学生能够用以前学过的某个编程模式解决,这就提高了学生解决问题的能力。endprint
3.3 代码编写
在算法设计完成后,最后一个步骤就是编码,即使用某种编程语言将该算法转换为相应的源代码。然而,对于毫无编程经验的学生来说,这并不是一件很容易的事情。事实上,即使学生已经想到一个很好的算法,他也仍然有可能无法写出正确的代码,根本原因就是缺乏实践以及足够量的编码训练。
为了解决这个问题,笔者所在的团队设计并实现了一个功能强大的在线训练系统,为全面提高学生的自学能力和动手实践能力提供技术_上的保证。笔者始终认为,对于程序设计类课程,学生必须在练中学、用中学。如果单靠学生自己摸索、尝试,那么效率会很低。因此,有必要为学生提供一个良好的训练平台,协助和促进他们进行实践。该平台以任务驱动的方式发布编程问题,学生只需登录任何一台联网的电脑,就可以实现在线阅读题目、编写程序、编译链接、运行、调试、提交程序,然后系统会自动对学生提交的源代码进行验证并立即返回结果。由于这种反馈是实时的,因此学生可以在系统的帮助下一步步完善自己的程序,这样就大大提高了学习效率,并且由于是在线训练系统,无需人工干预,因此学生可以在任何时候学习任意长的时间,这样,只要学生愿意,就能够得到足够量的编码训练。
在线训练系统除了编码训练之外,还能让教师将课程讲义发布在网站上,学生可以下载或在线阅读讲义。此外,学生还能在网站上发表文章,讨论问题;利用即时通信软件相互交流。
4 实施效果
笔者的教学方法主要落实在两门程序设计类课程上,一门是为软件专业本科生开设的专业基础课计算机语言与程序设计,另一门是给全校本科生开设的选修课计算机程序设计基础。经过近十年的教学实践,笔者根据各方面的反馈情况,不断进行更新和完善,目前教学已进入较为成熟和稳定的阶段,也取得了一些成果。
在专家评价方面,主讲教师的教学理念得到专家认可,曾经多次获得教学方面的奖项。在学生评价方面,学生一直对相关课程给予较高评价。我们在历年的教学评估中均进入了全校的前20%并多次进入到全校的前5%。
5 结语
计算机程序设计是大学生尤其是理工科学生必须掌握的一项基本技能,如何讲好该课程,如何切实提高学生的分析问题、解决问题的能力,是每一位任课教师需要认真思考的问题。笔者提出的基于能力培养的程序设计课程教学方法,就是在这个方面的一种尝试。未来的工作包括进一步完善案例教学和编程模式的概念,构建案例库,提出更多、更实用的编程模式,完善在线训练系统,引入更多的功能,如代码相似度检查、学生在线活动数据分析等。
参考文献:
[1]Riley D D.Teaching problem solving in an introductory computer science class[C]∥Proceedings of the 12th SIGCSE technical symposium on computer science education.New York:ACM.1981:244-251.
[2]Henderson P B.Anatomy of an introductory computer science course[C]∥Proceedings of the 17th SIGCSE technical symposium on computer science education.New York:ACM,1986:257-263.
[3]Ismail M N,Ngah N A,Umar I N.Instructional strategy in the teaching of computer programming:a need assessment analyses[J]. The Turkish Online Journal of Educational Technology,2010,9f21:125-131.
[4]Maheshwari P.Teaching programming paradigms and languages for qualitative learning[C]∥Proceedings of the 2nd Australasian Conference on Computer Science Education.New York:ACM.1997:32-39.
[5]Bonar J,Soloway E.Preprogramming knowledge:a major source of misconceptions in novice programmers[J].Human-Computer Interaction,1985,1(2):133-161.
[6]Ris R.Teaching eiffel as a first language[J].Journal of Object-Oriented Programming,1996(9):30-41.
[7]Chen W J,Li X,Lju W D.Teaching computer programming to non-computer science students[C]∥Proceedings of the 3rd Asian Conference on Education.Katahira:IAFOR Publications,2011:784-795.
[8]Chen W J,Li X,Liu w D.Teaching computer programming courses using programming patterns[C]∥Proceedings of the 20 1 2 3rd Intemational Conference On E-Business and E-Government.WashingtonD C:IEEE Computer Society,2012:606-609.
[9]shi K L,Chen W J,Zhang L,et al.Kaleidia:a practical e-learning platform for computer programming courses[C]∥Proceedings of the Canada International Conference on Education.Toronto:Infonomics Society,2012:103-108.
(编辑:宋文婷)endprint