软工+C(6): 最近发展区/脚手架
教育心理学里面有提到“最近发展区”这个概念,这个概念是前苏联发展心理学家维果茨基(Vygotsky)提出的,英文名词是Zone of proximal development
,摘录维基百科上的介绍如下:
The zone of proximal development, often abbreviated as ZPD, is the difference between what a learner can do without help and what he or she can do with help.
该理论认为学生的发展有两种水平:一种是学生的现有水平,指独立活动时所能达到的解决问题的水平;另一种是学生可能的发展水平,也就是通过教学所获得的潜力。两者之间的差异就是最近发展区。教学应着眼于学生的最近发展区,为学生提供带有难度的内容,调动学生的积极性,发挥其潜能,超越其最近发展区而达到下一发展阶段的水平,然后在此基础上进行下一个发展区的发展。
为什么要提到最近发展区呢?这就要说到在班级博客教学中的一个重要的方面:点评。点评一般由教师/助教 构成,足够的点评覆盖率,持续跟进和及时反馈对学生来说是重要的,反馈让学生处于一种diff状态,diff状态带来学习中的“发展区”:已有知识、做法和新知识、做法之间的边界,此时学生会review这个边界。
既然点评是重要的,教师/助教应该做到持续跟进和及时反馈,但怎样做到这两点在实际中会遇到一些具体的问题。例如,软件工程的结对编程项目的一次作业周期是一周,如果大家都在截止日期最后1天才去点评,也许等发现问题的时候已经没有足够的时间及时发现题目设计上的问题,学生实践中的困难等。而且堆积到最后一天点评,也会有量大的问题。因此,我认为从环节发布开始,就可以每天固定一些时刻去做增量点评,并且在前1/2天及时发现环节设计上需要做设计变更的地方,教师/助教需要有意识的实施这个过程。
发现具体问题,就可以和相关的知识、方法联系上来。让学生在反馈中再次强化对知识、方法具体落地的认识。例如,助教发现git提交代码的编码规范、文件组织等工程问题:
“强烈建议大家在自己的代码中写明readme,介绍一下自己的这个工程中哪些是有用的代码,哪些是自己用来测试的代码,哪些文件夹都干什么的,大家也要将自己的文件命名为有意义的文件名,否则大家提交了很多代码,而我需要找来找去,也并不知道我想找的文件在哪里。不知道你们过了两周时间再看自己的代码,是否也会和我有同样的感受[微笑]。”
此时就可以顺手引入“编码规范/风格”的问题,事实上,无论是软件工程的学生,还是有经验的工程师,都会经常陷入:先写出一堆随意的代码,命名了一堆随意文件夹名字之后,再去review编码规范,此时才跟根据编码规范做整理(refactor),经过多次磨合后,一个团队的成员对这点都形成习惯后,才内化成一种肌肉记忆,上来就相对规范。
发现具体问题,可以通过设计/建立新的环节来落地。根据我个人目前的点评经验,及时的博客点评可以大概收获30%左右回复率,对有回复的博客给予恰当的改进意见,有较大比率会有改进行动。之所以说是要有恰当的改进意见/环节设计,是因为学生在很多地方存在对需求的理解误区,因此需要把误解/模糊的地方通过改进意见/环节设计 去具体化。
例如,在一次结对编程单元测试这个环节,虽然题目经过设计,助教也做了单元测试模版,但是在沟通中还是出现了漏洞,大家在四则运算计算模块的单元测试应该针对:add/sub/multi/div, 还是针对:calc(string exp)这点上出现理解不一致,在点评中只有少部分学生改进了实现,实现并针对calc做了单元测试。
在这个例子中,单元测试处于课程的第四次:
- 四则运算初步(个人)
- 四则运算模块化(结对)
- 词典案例分析(个人)
- 四则运算单元测试(结对)
经过分析,其实当时主要是模块化的那次没有直接要求做成支持混合四则运算的,担心学生没有解析混合四则运算的算法基础,到了单元测试的时候,学生就默认以上一次为基础做单元测试,教师/助教在设计单元测试模版的时候也忽视了这个潜在的风险点。
这个问题在之前其他学校采用四则运算这个题目的时候也出现过,我觉的可以在第2次的时候就要求实现calc(string exp)的接口,算法的话,如果学生基础缺失,可以直接在题目里提示会用到的算法,理由是软件工程的课程不是算法课程,在实际开发中,如果一个方面的算法问题有现成的方案,也会至少大家是直接去看相关算法来写做为第一个版本。并且在四则运算这个个人项目环节不是要求大家能自己发明基础的算法,而是能在知道大概用哪些算法的基础上开发版本后,能在后续需求变更中持续满足新的需求,此时实际上才会有创造解决新问题的“算法”部分的事情。
软件工程课程的学生会发现,软件工程课程不会有专门的时间教编程语言/数据结构/算法/数据库这些前置或者后置课程。但是实际开发中,这些又是程序的重要构成部分,我们说软件=程序+软件工程,程序的部分又分核心模块/应用模块。实际开发中,核心模块使用的算法一般也都是从已有的开始做第一个版本来迭代,因此,我们可以遵循两个原则:
- 保持核心模块的接口要求,不做降级要求。
- 提供实现核心模块所需要知道的上下文,关键词,例如可能会用到的数据结构/算法。
对四则运算的算法模块,可以增加:
- 关键字:中缀表达式,后缀表达式,逆波兰表达式,栈,调度场算法
- 参考链接:
在软件开发中经常需要创造和寻找越来越好用的轮子,而在教学环节中需要常常造梯子,搭建好足够支撑学生在自己水平上往前几步练习知识和技能的脚手架,然后在过程中逐渐减少脚手架的支撑,最后达成独立完成的能力。
Instructional scaffolding is a learning process designed to promote a deeper level of learning. Scaffolding is the support given during the learning process which is tailored to the needs of the student with the intention of helping the student achieve his/her learning goals.
梯子/脚手架理论(scaffolding)是由认知心理学家Jerome Bruner受最近发展区的概念启发提出的,当学习一个新概念的时候,脚手架需要考虑设计合适的任务/模版/指南/建议/训练。有时候,我们会在某个环节里欠考虑一些因素,导致提供的任务/模版/指南/建议/训练一定带有某种“壁垒”,如果我们观察/记录/分析,找出这些壁垒,在迭代中改进设计,可以有效消除这些壁垒。