面向对象程序设计课程定位的探索和实践
2019-05-24段世红万亚东
段世红,姚 琳,何 杰,万亚东,齐 悦
(北京科技大学 计算机与通信工程学院,北京 100083)
0 引 言
在当今的信息化世界,绝大多数软件系统都是采用面向对象技术来构建的。因此,掌握面向对象的分析与设计方法,精通支持面向对象的编程语言,深入把握面向对象软件系统开发的技术及工具平台,已经成为本科阶段计算机专业培养软件开发者必备职业技能的关键目标。计算机专业的基础骨干课程很有用,但由于课时的限制,在课堂教学中偏重于理论,或者偏重于编程语言的语法细节,学生缺乏软件开发经验,对主流软件开发技术知之甚少,用之不熟,导致就业竞争力不佳。因此需要一门课程来告诉学生:一个有用的软件到底是如何开发出来的?
面向对象程序设计课程是专业基础课,大多在计算机及相关专业的大一第一学期开设,学时比较多,通常要求以“熟悉一个面向对象的程序语言”为主要目标,讲述语法的各种细节。但是这门计算机专业的必修入门课程并没有给学生带来深刻的印象,在实际应用中学生不会使用学过的语法或忘记语法规范,枯燥地语法讲述和界面程序的简单化无法调动学生的学习积极性,最终学生在课程中收获不多,抱怨不少。本文针对课程的学习需求,基于目前课程出现的问题,对如何定位面向对象程序设计课程进行了探索和实践。
1 基于Bloom分类法探索面向对象的程序设计课程的定位
在教学过程中,为了知识扩展,培养学生的思维能力,大多数情况下会选择采用增加难度而非提高复杂程度的方法[1]。复杂度和难度这两个概念常常被混淆,美国人苏珊与其著作《脑与学习》[2]一书中指出:复杂度和难度是两种完全不同的心理操作过程:复杂度描述大脑处理信息时所运用的思维过程;难度描述一个人在同一复杂程度内完成学习目标所需要付出的努力。
本文研究并应用了教育学中著名的Bloom分类法[3]来提高学生的思维能力。Bloom分类法是1956年创立的一种教育目标分类体系,它将人类思维的复杂程度划分为6个水平,2001年该思维模型得到改进,从简单到复杂依次为:知识、理解、应用、分析、评估和创造。如图1所示。
通常,人们会认为在复杂度和难度中,与人本身固有的能力有更密切关系的是复杂度[4],因为很容易达到这样的共识:只有本身能力较强的人,才能完成分析、评估及创造这样更高的层次的任务。其实,这是一种误解,这种误解也带来了一系列的教育问题。Bloom分类法提出的结论是:真正与人本身固有能力关系最大的是难度,而不是复杂度。假设一个班级中的学生划分为3类,一类是学得快的,一类是平均水平的,还有一类是学得慢的。在教学中,教师一般会根据“平均水平的学生”需要的学习时间来安排课时。就会出现以下3种情况:
(1)学得快的学生:能提前完成学习任务,其余的时间可以用来对概念进行分类;
(2)平均水平的学生:刚好完成老师布置的学习任务;
(3)学得慢的学生:只学习了部分内容,还需要用额外的时间才能完成给定的任务。
在Bloom的分类法中,学得慢的学生不必去学习非重要的内容,从一开始就将重点集中于关键的问题和重要的信息上,降低与人本身固有能力密切相关的学习难度,让学生把更多的时间放在分析、评估和创造能力的训练上。
因此在课程定位和内容安排上,如果能充分应用Bloom分类法的研究成果,就能让课堂上更多的学生取得更大的成功。
1.1 面向对象的程序设计课程的问题分析
目前,面向对象程序设计课程的目标通常被定义为:能够掌握一门面向对象的程序设计语言。所以课程的内容安排也围绕学习程序语言展开,主要讲述面向对象的程序设计语言的语法。从语言的字符集、基本数据类型的描述开始,讲述基本程序结构、函数、数组等,最后讲述面向对象概念的语法支持(类和对象,继承和多态等)。学生在课堂上会学习全套的程序设计语言的语法,并对每个语法点安排上机小任务进行练习。学习和考核的重点实际上停留在Bloom分类的最底层:记忆—知识上。本节会分析几个常见的课堂讲述的逻辑问题,因为教学目标是学习面向对象程序设计语言,因此内容的安排上会强调语言的语法细节,结果会增加学习的难度,学生的掌握程度不高,也无法有效地学以致用[4-5]。
在面向对象的语法学习中,多态是个很重要的概念,对应的语法规则是比较容易理解的,但是什么时候用多态,怎么用却是非常不好掌握的。为了实现“学习一种面向对象的程序设计语言”的教学目标,多态这节的教案内容常常包括如下步骤:
步骤1:什么是多态? 主要是讲述静态联编对应的静态多态,和动态联编对应的动态多态。
步骤2:动态多态是怎么定义的?主要讲述virtual关键字用来定义虚函数,实现动态联编。
步骤3:阅读下例所示的程序代码main.cpp,并说明运行结果,以及哪些是动态多态?这个题目主要是要求学生记忆动态多态实现的基本语法规范,即用基类的指针或者引用访问同名覆盖的函数,函数必须是虚函数。所以用基类的指针只能访问基类定义的函数;vf2函数不同参数的定义实际会形成名字隐藏,不是重载。
例:虚函数的正确使用[7]。分析以下程序,编译时哪个语句会出现错误?为什么?将有错误的语句屏蔽掉以后,程序运行结果如何?其中哪些调用是静态联编,哪些是动态联编?
上述3个步骤依次加深了多态的语法讲述,都属于图1中的知识层概念。但是学习的效果并不好,学生最后无法正确地给出程序的分析。vf2()没有同名覆盖的函数,很多学生,甚至一些参考书上都将bp->vf2()的调用说成是静态联编,虽然运行的结果是对的,但是程序的运行逻辑是错的。这样的语法讲述,知识点都覆盖了,但是对学生而言,掌握难度太大,而且没有和实际应用结合起来,所以会一直疑惑:为什么要学多态,什么时候能用多态。
综上,在课程定位为掌握面向对象的语言时,课程的内容就围绕语法知识的细节展开,难度不断加深,但是并没有向复杂性上扩展,部分学生会觉得越来越困难吃力,而且还会觉得没有用,也用不起来。
1.2 面向对象的课程教学目标探索:不重语言重开发
在分析了之前课程讲述中的问题,授课目标被重新定义为:如何用面向对象的方法开发一个真正有用的软件,就是如何写面向对象的程序。所以授课的内容会覆盖复杂度不同的多层知识,降低了难度,增加了实用性。以下是针对新目标进行的多态分析教学内容修正。
多态的使用不是一朝一夕就能体会和应用的。教案在讲述了基本的多态概念后,就扩展到理解层讲述多态的实现原理,并以银行账号查询为例说明使用多态究竟带来了什么好处。
步骤1:什么是多态?主要是讲述静态联编对应的静态多态,和动态联编对应的动态多态。这部分主要是知识概念的讲解。
步骤2:动态多态是怎么定义的,实现的原理如何?这个问题在讲述定义动态多态关键字virutal的基础之上,理解动态联编的实现机制,包括虚表的建立,查表过程。通过工具(cl /d1 reportSingleClassLayoutDD main.cpp)就可以查看上节例程main.cpp对应的虚表,在理解虚表的基本原理之后,学生就能够回答如例1所示的问题,而不只是凭借记忆答题。
步骤3:什么时候用动态联编?这是从应用层面上理解动态多态,在之前的课堂教学中,学生知道动态多态的概念,但是无法理解多态所带来的好处,因此学生无法主动用多态的思想去设计程序。为了将概念和方法落脚在应用中,这个环节讲述两个例子。一个是账户管理系统,主要功能是建立一个父类Account,两个子类(储蓄账户savingAccount,信用卡账户creditAccount),不同子类账户的某些操作的接口是相同的,为了书写的方便,用父类指针或者引用可以访问不同子类账户,就可以在循环里完成不同子类账户的调用,但是实际会根据调用的账户类完成接口相同的不同功能实现;第二个例子是跟学生一块阅读MFC的框架,在了解MFC的运行顺序和程序机制的同时,体会静态成员、动态多态在框架设计中的应用。
课程定位提供了教案内容调整的依据,目前的课程教案增加了复杂度,但是降低了难度,让更多的学生接受度提高,也扩展了学生的知识体系。
2 面向对象的程序设计课程的实践
面向对象程序设计课程的目标设定为“掌握如何用面向对象的方法开发一个真正有用的软件”。因此在课程内容的设计上,从实际软件开发的需求出发,介绍“真正”使用的开发技术、软件开发流程,不再深究语法的细节,而是关注如何开发程序。
2.1 课程内容
之前,面向对象的程序设计课程围绕着“程序语言”,讲述语言的基本要素,数据类型,基本结构和自定义的各种数据类型、函数,以及对面向对象的四大概念(抽象、封装、继承和多态)的语法支持。讲述的语法点很庞杂,要求学生记忆相应的语法规则和使用要点,但是之前的问卷调查反映出学生学习难度挺大(因为需要大量记忆,且常常对程序实现中出的错误束手无策),最终学生仍表示没有学会编程,拿到其他课程中需要解决的实际需求,无从下手;语言的讲述不联系计算思维的培养,是没有办法培养出程序开发的技术人才的。课程新的定位目标是“学会开发有用的程序”,不再依赖某一种面向对象的程序语言的语法规则学习,而是强调在面对实际问题时的计算思维的能力和程序设计方法,这样程序语言的讲述就成为计算思维培养的手段,实现程序设计方法的工具。
课程内容的安排见表1,以解决问题为出发点,给出解决问题的方案和程序语言实现的语法支持。编程的语言选择有很多,但是面向对象的程序设计课程在新的教学目标下,将以不变应万变,换句话说,核心课程内容将试图抽取传达“编程之魂”,聚焦程序设计思维的建立。从表1中可以看出,教学内容的设置,是基于抽取编程灵魂设置的,不再是纯粹的语法学习,而是要完成相应程序的基础元素的学习,具有了基本的编程思维,这样学生在之后的实际应用中,会知道如何对新的问题给出自己的程序解决方案。上述课程内容的安排在指定课时中是无法完成的,会在程序设计实践课程中,或者以慕课、微课的形式与学生交流。
表1 新目标下的面向对象课程内容安排
2.2 面向对象程序设计课程的实践扩充
面向对象程序设计课程最终要让学生落脚到编写程序中[6],所以课程后续安排了程序设计实践I和程序设计实践II,并配合其他课程为学生提供了一个学习体系,如图2所示。
图2 面向对象程序设计的课程体系
我们在程序设计实践I中要安排多个专项练习,将学生在面向对象程序设计课程中遇到的难点和重点提炼出来,在简单讲述的基础上完成大量的程序编写训练,完成一个较完整的程序综合练习:比如哈利波特书籍的检索等,并最终用3个小时的上机编程考试,检验学生的编程能力。程序设计实践II安排了两个独立的编程联系,要求学生能够建立账户类的管理系统,以及空战类游戏,以程序演示和设计测试文档的形式确认学生的编程能力提高。增加更多的实践环节,从图3所示的数据中可以看出,效果还是不错的。实践之前的编程能力测试中的程序共7道,难度等级是(3道)I和II(4道),平均成绩是30分,其中1706班的成绩最好,为36分;在实践课程后又进行了编程能力测试,这次程序共8道,难度等级为III的有3道,II的有4道,I的有1道。这次考试1706班的成绩分布如图3(b)所示,平均成绩是60.7,成绩提高了68%。图3还给出了累积概率统计的结果,可以看出不同分数段的学生分布情况,实践之后的平均成绩虽然还有待提高,但是高分的人数增加了,低分的人数减少了,课程的实践扩充有效地提高了学生的实际编程技能。
3 面向对象的程序设计效果分析和总结
本文前两节阐述了教学中的新思维方式,面向对象的程序设计课程不仅仅是授课,而是要培养“工程师”该具有的实实在在的技能。本门课程是培养学生在软件开发活动中的“单兵作战”技能,也是从开发实践出发,学习面向对象的方法和语言实现,能够完成后续课程中的实践任务,也会将后续各种专业课程的知识依次融入,帮助学生在学习中构建出一个比较完整的知识体系,培养能满足软件开发工作需求的职业技能。
图3 面向对象程序设计实践内容的效果
2016年开始,北京科技大学计算机专业新的大纲要求大一第一学期就开设面向对象程序设计课程。在教学实践中,将授课目标从“学会面向对象的程序语言”,转变为“学会用面向对象的方法去写程序”。不再用整堂课的时间讲述语法和各种细节,而是从实际的一个目标需求出发,有针对性地讲述使用语言解决问题时需要的关键语法、方法和技术,讲述的内容覆盖了知识、理解和应用。认真学习过这门课程的学生反映收获较大,不仅掌握了程序语言的基础语法,也了解业界使用的主流开发工具和软件技术,并且知道如何在实际的程序编写中解决实际较复杂的问题。
本文为了确认教学效果,发放了调查问卷,也对试卷和后续课程程序设计实践I的编程任务的完成进行了分析和总结,见表2,其中2016—2017年度的授课主要更新了面向对象程序设计方法的讲述,2017—2018年度增加了计算思维培养的部分实例。针对学生的编程能力,课程效果明显提高了。
表2 课程效果问卷调查统计表%
4 结 语
试图通过语言的学习来建立编程能力,结果会将更多的精力用在理解语言的语法细节上,只见树木不见森林。本课程的目标是从具体的语言中独立出来,剥茧抽丝,取其灵魂,聚焦于程序设计思维的建立,重点放在理解语言语法背后的思想,并初步具备灵活使用这些思想解决实际问题的逻辑思维能力。本文从教学目标和教学内容上分析了可行的方案,并在实践中应用,获得的教学数据表明,以编写程序为目标的面向对象的程序设计课程能让学生拥有比较扎实的程序开发能力。