Hella Haanstra en Martijn Stegeman
Welkom bij de cursus programmeren voor beta's en gamma's! Met deze handleiding willen we (toekomstig) docenten en assistenten graag inzicht geven in hoe de cursus ontworpen is en hoe wij studenten begeleiden als we de cursus "in de klas" geven. De cursus is nu immers gepubliceerd voor een onlinepubliek, maar oorspronkelijk bedoeld voor studenten van de opleidingen Natuurkunde en Beta-Gamma bij de Universiteit van Amsterdam.
Er zijn vier modules die elk een ander onderwerp behandelen (meestal verbonden aan een bepaald wetenschapsgebied) maar vooral stukjes Python en technieken voor probleemoplossing aanleren. De volgorde van de modules is belangrijk: elke bouwt voort op de vorige.
Per module is er keuze tussen twee of drie verschillende onderwerpen. In principe moet het mogelijk zijn één van de onderwerpen te kiezen en dan hetzelfde te leren als bij een ander onderwerp. Studenten die het vak online volgen, mogen dan ook zelf kiezen welke ze doen. Overigens valt er vaak nog wel wat te halen uit het volgen van meerdere varianten van dezelfde module: een extreem geval is module 2, waar in de ene variant strings worden behandeld en in de andere technieken voor numeriek integreren.
De cursus bestaat uit de volgende onderdelen:
- uitgebreide pagina's met uitleg over Python-structuren, met oefeningen
- korte filmpjes met demonstraties van enkele technieken
- opdrachten waarin met specifieke technieken wordt geoefend
- korte mini-docu's over wetenschappers die veel programmeren
Met deze materialen zouden studenten redelijk zelfstandig door de stof heen moeten kunnen.
Als we de cursus aan eerstejaarsstudenten geven, werken we met verplichte aanwezigheid en de hulp van studentassistenten. Zeker met de beperkte tijd die we hebben, is het vervelend als een student nét even iets mist en daardoor niet verder kan. Assistenten, die de cursus al uitgebreid gezien hebben, kunnen studenten snel verder helpen.
De cursus staat voor 3 europese studiepunten (EC) en moet ongeveer 80 uur aan werk opleveren, dus 20 uur per module. Het verplichte practicum behelst daarvan maar liefst 16 uur. We vinden dat met name fijn voor eerstejaarsstudenten, die nog niet weten dat voor het leren programmeren veel uren gemaakt moeten worden.
Er zijn vier voornaamste onderdelen waar we hulp mee bieden in de klas:
-
Probleemdecompositie. Dit is het begrijpen van de opdrachttekst, en het opdelen van het probleem in steeds kleinere stukjes. In hoeveel stappen dat opdelen gaat, is van te voren onbekend en echt een onderwerp van oefening voor de studenten. De bedoeling is dat de opgedeelde stukjes uiteindelijk zó klein worden, dat ze min of meer direct naar een Python-opdracht te vertalen zijn.
-
Procesondersteuning. Dit zijn de kleine interventies die bij lesgeven altijd een rol spelen. Soms heeft een student net wat informatie over het hoofd gezien - een simpele verwijzing kan dan helpen. Op een heel ander niveau is het ondersteunen van studenten bij de onvermijdelijke momenten van frustratie die met het programmeren gepaard gaan. In dat geval helpt het vaak om te adviseren even weg te lopen van de computer, te pauzeren, en later met een frisse blik weer aan de slag te gaan.
-
Debugging. Dit is een wezenlijk onderdeel van de cursus en moeilijk uit theorie aan te leren. Tijdens het programmeren is het normaal om allerhande fouten te veroorzaken. Soms door het verkeerd begrijpen van een commando, soms door het maken van een flauwe tikfout. Afhankelijk van het probleem geeft "de computer" een al dan niet begrijpelijke foutmelding. Het leren lezen van de foutmeldingen is sneller te leren met een expert aan de zijde. Ook het leren van een aantal algemene strategiën voor foutopsporing gaat het beste op het moment dat zich een concreet, zelfveroorzaakt probleem voordoet.
-
Vraagstelling. Soms kennen studenten nog niet de juiste woorden om hun probleem uit te leggen. De meest abstracte hulpvraag die we tegenkomen is "Het werkt niet". Soms gaat het dan om studenten die denken dat op dat moment de docent aan de slag moet om het probleem op te lossen, maar de meeste studenten begrijpen wel dat ze dan zelf nog iets te leren hebben. Het doel is immers zelfstandig leren programmeren en dus ook fouten oplossen! Op zo'n moment gaan we dus vragen terugstellen aan de student, zoals "Wat zie je dat er niet werkt?".
Ons allerbelangrijkste principe is dat we studenten nooit een oplossing aanreiken, maar helpen deze zelf uit te vinden. Dat is namelijk waar het precies om gaat bij programmeren: niet het kennen en reproduceren van oplossingen, maar het toepassen van bekende technieken op nieuwe problemen. Ooit komt het er moment dat de docent niet meer terzijde staat, dus de focus ligt op zelfstandigheid kweken.
Misschien een voor de hand liggende opmerking, maar we willen graag zorgen dat alle studenten tijdens een practicum met de begeleider gesproken hebben --- ook als het goed gaat. Dat betekent dat de tijd voor elke student enigszins beperkt moet worden. Als het te lang duurt, dan moeten naar de volgende student (we houden meestal een absoluut maximum van 10 minuten aan, maar liever 5!). Als we dit even uitleggen, dan wordt het altijd wel begrepen. Voor de docent is het soms moeilijk om een student in het diepe te laten zwemmen. Bij sommige van onze programmeervakken organiseren we nog een "extra practicum" om enkele studenten er weer helemaal bovenop te helpen.
Gesprekstechnieken 1
-
Complimenteer de student op een duidelijke manier. Kies voor 'heel goed antwoord!', 'zeker weten' of 'precies', etc. Probeer 'ok', 'hmm', 'uhu' te vermijden. Ook als de student een langdradig antwoord geeft, probeer iets te vinden waar je positieve feedback op kunt geven.
-
Laat je feedback betrekken op het specifieke antwoord van de student. Bijvoorbeeld als de student een
for
-loop voorstelt terwijl eenwhile
-loop misschien handiger is, antwoord iets in de trant van: 'heel goed, je ziet dat er een vorm van herhaling nodig is'. -
Probeer voort te bouwen op het antwoord van de student. Als het antwoord dat de student geeft niet helemaal naar wens is, probeer het dan mee te nemen in je volgende vraag. Iets als 'je hebt goed gezien dat je de String moet opdelen, wat is de volgende stap?' werkt motiverend.
-
Probeer 'ja, maar...' te vermijden. Dit is een logische reactie op een (deels) fout antwoord, maar kan heel erg demotiverend werken. Probeer duidelijk te scheiden wat goed was en wat fout was en beloon daar ook naar. Je kunt ook de vraag stellen 'hoe ben je daarop gekomen?'; dit is tevens een vraag die je kunt stellen als het antwoord wel goed is!
-
Maak geen aannames over wat studenten al weten. Een student kan soms met zelfs het makkelijkste probleem in de knel zitten en dan is het erg frustrerend als er wordt gezegd 'probeer eens wat harder na te denken'. Toets wat de student wel weet en bouw daarop voort. Stel open vragen en laat de student zelf het probleem oplossen, probeer niets voor te zeggen!
We werken graag met een feedbacksysteem waar studenten gericht gewezen worden op de meest essentiele verbeterpunten. We gebruiken daarvoor twee onderdelen: becijfering en geschreven feedback.
Becijfering gebeurt met vier verschillende factoren2:
-
Scope. In hoeverre is een serieuze poging gedaan om de verschillende onderdelen te implementeren? We moeten aan de ingeleverde code kunnen zien dat de meeste elementen voor de oplossing aanwezig zijn. De oplossing hoeft echter niet te werken! Daarvoor is het volgende criterium.
-
Correctness. In hoeverre voldoen de geprogrammeerde oplossingen aan de exacte specificatie in de opdrachten? Voor dit criterium kunnen we test-tools gebruiken. De studenten krijgen ook toegang tot deze tools. Belangrijk: als iemand de volle punten voor correctheid krijgt, dan ook voor scope! Andersom geldt dat absoluut niet.
-
Design. In hoeverre is de code elegant geschreven, dus: overzichtelijk, efficient, logisch, prettig leesbaar? Eenvoud is hier een belangrijk aspect. Veel oplossingen van beginnende programmeurs zijn nog onnodig complex, zelfs al is het antwoord volledig correct. Als een student aardig gaat, dan is dit een heel interessante factor om feedback over te geven. Een andere mogelijkheid is om studenten (van vergelijkbaar niveau) elkaars oplossingen te laten bespreken.
-
Style. In hoeverre is de code goed en snel leesbaar, dus: commentaar aanwezig, indentatie op orde, variabelen met herkenbare namen? Al in module 1 worden studenten verwezen naar de "stijlgids", waarin enkele belangrijke stijlaspecten worden uitgelegd. Het besef dat leesbaarheid belangrijk is, wordt niet altijd meteen opgemerkt. Daarom is ook dit een onderdeel van de beoordeling.
De reden om deze vier factoren apart te becijferen is de feedbackwaarde: als een student een deel van het werk niet serieus heeft kunnen proberen, dan is scope laag en moeten we direct op zoek naar de oorzaak. Niet proberen aan het begin van de cursus betekent namelijk doorgaans dat het einde ook niet gehaald wordt. Daarna is correctheid heel belangrijk: in veel gevallen is het belangrijk dat een programma een exact antwoord oplevert, en randgevallen mogen daarbij niet over het hoofd worden gezien.
Met name voor design en style becijferen we zo:
- 5 Perfectie. Alles klopt precies, niets meer aan te verbeteren.
- 4 Zeer goed. Een of twee kleinigheden.
- 3 Goed. Een of twee wat grotere problemen of systematische problemen.
- 2 Redelijk. Nog diverse verbeteringen mogelijk.
- 1 Slecht. Een onwaarschijnlijk resultaat.
En voor de aardigheid geven we dan ook de formule die we gebruiken om naar een opdrachtscore te komen:
scope * (3*correctness + 2*design + 1*style)
De score is dus een gewogen gemiddelde van 3 aspecten, vermenigvuldigd met scope. De reden is dat als een student maar de helft van het werk heeft gepoogd te doen (zichtbaar), dat ook echt maar de helft van de score wordt behaald. Over het algemeen geeft deze formule cijfers die aan de hoge kant zijn voor studenten die goed meekomen.
Probeer bij het becijferen het niveau van de individuele student mee te nemen. Vergelijk de student met zichzelf: in hoeverre heeft de student de feedback van voorgaande weken toegepast en is hij of zij vooruitgegaan? Vergeet niet ook positieve feedback te geven! Dit wordt vaak vergeten omdat er eerder punten afgetrokken worden voor fouten dan punten gegeven voor correcte code. Feedback wordt veel prettiger verwerkt als ook de positieve punten worden aangestipt.
Geef feedback op het proces, niet op de student. Dit is ook al kort genoemd bij gesprekstechnieken voor het computerpracticum. Directe feedback op de persoon is veel minder effectief dan feedback op het proces3. Geef daarom in de feedback goed aan waarom iets goed of minder goed is. Bied daarbij tips aan, zodat de student de volgende keer de knelpunten beter kan aanpakken. Tijdens de wekelijkse bespreking van de feedback kun je de feedback wat meer toelichten.
Voor programma's is het mogelijk om automatische plagiaatcontrole te doen. Met deze controle wordt de vraag beantwoord in hoeverre inzendingen van verschillende studenten op elkaar lijken. De interpretatie van de resultaten is echter geen sinecure en wordt volledig aan de docent overgelaten. Dat is maar goed ook, want het verschil tussen samenwerkende studenten en studenten die toevallig op een zeer soortgelijke oplossing zijn gekomen, is niet groot. Toch kan het ten minste nuttig zijn om de studenten op te merken die als het ware ongemerkt teveel op elkaars scherm hebben gekeken. De meestgebruike tool hiervoor is MOSS van Stanford University, die gratis te gebruiken is voor docenten.
Succes met het geven van dit mooie vak! Als je aanpassingen doet, leuke tips hebt of anderzins wil bijdragen, stuur ons gerust een mail.
Copyright 2017 Martijn Stegeman.
Dit werk valt onder een Creative Commons Naamsvermelding-GelijkDelen 4.0 Internationaal-licentie.
Footnotes
-
A. Hadwin and S. Wilcox, "A handbook for teaching assistants," Instructional Development Centre Queens University, Kingston, Ontario, K7L 3N6, 1999--2000. ↩
-
Ontleend aan David J. Malan, "CS50 grading", 2016. http://www.cs50.tv/ ↩
-
J. Hattie and H. Timperley, "The power of feedback," Review of Educational Research, vol. 77, no. 1, pp. 81–112, 2007. ↩