Bachelor Informatica
Automatische feedback op de
leesbaarheid van de code als
gevolg van de positionering
Lukas Koedijk
8 juni 2018
orma
tica
—
Universiteit
v
an
Ams
terd
am
Samenvatting
Codekwaliteit is een belangrijk aspect van software. Om studenten een goede codestijl aan te leren is een tool ontworpen die feedback op codekwaliteit genereert. Codekwaliteit bestaat uit meerdere onderdelen; in dit onderzoek is gekeken naar de leesbaarheid van de code als gevolg van de positionering. Met de positionering wordt bedoeld dat stukken code op een logische plaats in het programma staan. Uit de literatuur kwamen vijf richtlijnen voor de positionering van code. Twee van de richtlijnen worden ge¨ımplementeerd in een tool. Deze tool geeft feedback op programma’s en is gemaakt aan de hand van de literatuur en evaluatierondes. In de evaluatierondes is gebruik gemaakt van studentassistenten en studenten. Bij de evaluatieronde met studentassistenten is gekeken naar wat zij fout rekenen om te bepalen op welke problemen de tool feedback moet geven. Ook is tijdens deze evaluatieronde gekeken naar hoe studentassistenten feedback geven om een idee te krijgen hoe de feedback die de tool genereert eruit moet zien. De evaluatieronde met studenten heeft als doel om de feedback van de tool te verbeteren. De feedback die de uiteindelijke tool geeft bestaat uit ´e´en voorbeeld per richtlijn waarvan ten miste ´e´en fout volgens deze richtlijn in het programma gevonden is en het aantal fouten per richtlijn.
Inhoudsopgave
1 Introductie 7 1.1 Context . . . 7 1.2 Doel . . . 7 2 Literatuur 9 2.1 Codekwaliteit . . . 9 2.2 Bestaande tools . . . 10 2.3 Feedback geven . . . 10 2.4 Samenvatting . . . 10 3 Onderzoeksvraag 11 4 Methode 13 4.1 Automatisch testen van de eisen . . . 134.2 Goede feedback genereren . . . 14
4.3 Samenvatting . . . 15
5 Evaluatie van de tool 17 5.1 Aantal variabelen test . . . 17
5.2 Resultaten aantal variabelen test . . . 17
5.3 Opzet evaluatieronde met studentassistenten . . . 18
5.4 Resultaten evaluatieronde met studentassistenten . . . 18
5.5 Opzet evaluatieronde met studenten . . . 19
5.6 Resultaten evaluatieronde met studenten . . . 20
5.7 Conclusie . . . 20
6 Conclusie 21 7 Discussie 23 Appendices 27 A Programma’s gebruikt in de evaluatieronde met studentassistenten 29 A.1 Montecarlo.py . . . 29
A.2 medicine.py . . . 30
A.3 histogram.py . . . 32
A.4 medicine.py . . . 33
A.5 afstand.py . . . 34 B Originele programma en resulterende programma’s van de evaluatieronde met
HOOFDSTUK 1
Introductie
1.1
Context
In het vakgebied van de informatica is het belangrijk dat studenten goed leren programmeren. Een belangrijk onderdeel van het leerproces van studenten is de feedback op het werk dat ze hebben ingeleverd (Hattie en Timperley, 2007). Deze feedback wordt vaak door studentassistenten gegeven en gaat zowel over de werking van de code als de codekwaliteit. In dit onderzoek wordt gekeken naar de codekwaliteit. Het onderwerp codekwaliteit gaat deels over hoe begrijpbaar de code is voor een ander. Dat de code begrijpbaar is voor een ander is belangrijk bij de mogelijke groepsopdrachten later in de carri`ere van de student zodat goed samengewerkt kan worden. Ook kost het onderhoud van programma’s die slecht leesbaar zijn meer tijd en geld (Collar Jr en Valerdi, 2006). Verder is een programma met een goede codestijl beter te onthouden dan een programma met een slechte codestijl en hierbij is het verschil in aantal regels dat wordt onthouden groter naarmate de persoon meer ervaring met de programmeertaal heeft (Shneiderman, 1976). Vanwege de kosten van onderhoud van slecht leesbare code en dat je niet makkelijk van een slechte codestijl afkomt is het belangrijk dat een goede codestijl al vroeg wordt aangeleerd. Daarom wordt bij inleidende programmeervakken veel aandacht aan codestijl besteed. De feedback met betrekking tot code wordt bij deze vakken handmatig door studentassistenten gegeven.
1.2
Doel
Het doel van dit project is om manieren te onderzoeken om deze feedback automatisch te kunnen produceren en daarbij vast te stellen wat er verstaan wordt onder een goede codestijl. Uiteindelijk willen we deze resultaten verwerken in een tool die automatisch feedback geeft op de leesbaarheid van code als gevolg van de positionering van de code in programma’s van beginnende programmeurs. Met de leesbaarheid van de code als gevolg van de positionering wordt bedoeld dat stukken code op een logische plaats in het programma staan. De tool kan door studenten gebruikt worden tijdens het programmeren nog voordat zij hun programma’s inleveren en gaat ervan uit dat de programma’s waar feedback op wordt gegeven in Python zijn geschreven.
HOOFDSTUK 2
Literatuur
2.1
Codekwaliteit
Stegeman, Barendsen en Smetsers (2014) hebben gekeken naar wat belangrijk is voor een goede codekwaliteit met name voor programmeeropdrachten voor beginnende programmeurs. Dit werd gedaan door eerst in de professionele literatuur te zoeken welke aspecten belangrijk zijn. Hierna werden met behulp van drie professoren deze aspecten gegroepeerd en elk aspect werd een prioriteit toegewezen binnen de groep. Stegeman, Barendsen en Smetsers (2016) hebben van deze groepen en aspecten een rubric gemaakt. Deze rubric werd getest, ge¨evalueerd en aangepast in drie iteraties waardoor er een uiteindelijke rubric uitkwam voor programmeeropdrachten voor beginnende programmeurs. Uit deze rubric is het onderwerp van dit onderzoek gekozen, namelijk het onderwerp layout met als sub-aspect dat de positionering van de code in een programma wel of niet geoptimaliseerd is voor de leesbaarheid van een programma.
Layout - en stijleisen van de code worden uitgebreid beschreven in het boek van McCon-nell (2004) in hoofdstuk 31. Ook worden er voorbeelden gegeven van code die een slechte codestijl heeft en hoe deze code kan worden aangepast om het leesbaarder te maken. Het boek vertelt over een fundamentele theorie die luidt dat de opmaak van de code de logica achter de code zou moeten laten zien. Andere criteria voor een goede codestijl zijn dat het goed leesbaar is en dat de stijl van de code goed tegen veranderingen kan. Deze drie criteria zijn bij elkaar de algehele regels om een goede codestijl te hebben, maar er worden in het boek ook meerdere kleinere onderdelen aangewezen die leiden tot deze regels. Een paar van deze onderdelen zijn het declareren van variabelen dichtbij waar ze gebruikt worden en de volgorde van declaraties moet logisch zijn, bijvoorbeeld geordend op type. Later in dit onderzoek wordt naar deze eisen gekeken om te bepalen wat de eisen over de leesbaarheid van een programma zijn.
Een ander boek waar later in dit onderzoek naar eisen over de leesbaarheid van een programma wordt gekeken is het boek van Martin (2009). In dit boek staan in hoofdstuk vijf een aantal eisen waaraan de code moet voldoen om een goede codestijl te hebben. Er wordt een vergelijking gemaakt tussen code en een krant, waarmee het boek wil aantonen hoe belangrijk de layout is en dat code die met elkaar te maken heeft bij elkaar staat zoals in een alinea. Andere eisen zijn dat de declaraties van variabelen in de buurt staan van waar de variabelen worden gebruikt, dat lokale variabelen bovenaan de functie staan en dat variabelen die in een hele klasse kunnen worden gebruikt bovenaan de klasse worden gedefinieerd. Verder moeten functies die elkaar aanroepen verticaal dicht bij elkaar gedefinieerd zijn en, waar mogelijk, functies die andere functies aanroepen boven de functie die wordt aangeroepen staan. Ook verteld het boek over het begrip affiniteit, wat er op neer komt dat sommige code dicht bij andere code moet staan, zoals functies die vergelijkbare operaties uitvoeren.
2.2
Bestaande tools
Ala-Mutka (2005) bespreken verschillende tools die feedback geven op programmeeropdrachten. In de paper wordt per onderdeel van een programma tools vergeleken. In dit onderzoek is gekeken naar het onderdeel codestijl waarbij tools worden vergeleken die automatisch de codestijl van een programma testen. E´en van de tools in het onderdeel codestijl is STYLE. STYLE wordt uitgebreid beschreven door Rees (1982), en is een tool om de codestijl van een Pascal programma te testen. Deze tool gebruikt voornamelijk harde waardes zoals het percentage commentaar dat een programma heeft. Een ander onderzoek dat kijkt naar de leesbaarheid van een programma staat in de paper van Buse en Weimer (2008). In deze paper wordt er gekeken naar de relatie tussen de kenmerken van een programma en de leesbaarheid van het programma. Een van zo’n kenmerk is het aantal wit regels per aantal regels in een programma. Beide tools kijken naar harde waardes die uit een programma te halen zijn om te bepalen hoe leesbaar een programma is. In dit onderzoek wordt gekeken naar een manier om de leesbaarheid van een programma te testen zonder gebruik te maken van dergelijke harde waardes, namelijk door gebruik te maken van een boomstructuur.
2.3
Feedback geven
Om te bepalen wat goede feedback is kan gekeken worden in de paper van Hattie en Timper-ley (2007). In deze paper wordt beschreven dat feedback belangrijk is voor het leerproces van studenten. Ook wordt in de paper uitgelegd dat feedback drie vragen moet helpen beantwoorden om goede feedback te zijn. Deze drie vragen zijn:
1. Wat is het doel waar de student naar toe moet? 2. Waar staat de student nu?
3. Hoe komt de student bij het doel?
2.4
Samenvatting
Uit de literatuur komen een aantal richtlijnen voor de leesbaarheid van een programma en een aantal voorbeelden van andere onderzoeken naar codestijl. Verder wordt in de literatuur naar verschillende tools gekeken die testen of een programma leesbaar is. Al deze tools bepalen of een programma leesbaar is aan de hand van harde waardes; deze methode wordt niet gebruikt in dit onderzoek om te bepalen of een programma leesbaar is. Tot slot staat in de literatuur dat bij goede feedback de student drie vragen kan beantwoorden.
HOOFDSTUK 3
Onderzoeksvraag
De onderzoeksvraag luidt: hoe kan er automatische feedback worden gegeven op de leesbaarheid van de code als gevolg van de positionering in een programma? Dit volgt uit het onderzoek van Stegeman, Barendsen en Smetsers (2016) waar een rubric werd gemaakt. E´en van de categorie¨en uit de rubric is layout, waar “het plaatsen van elementen in de code is wel of niet geoptimaliseerd voor de leesbaarheid” een onderdeel van is. Dat een programma niet geoptimaliseerd is voor de leesbaarheid kan komen door verschillende oorzaken. De oorzaak die in dit onderzoek wordt behandeld is de positionering van code in een programma. Het dicht bij elkaar plaatsen van stukken code die verwant zijn zorgt voor een betere leesbaarheid (Martin, 2009). Bij verwante code kan worden gedacht aan code die afhankelijk is van de uitkomsten van elkaar of functies die elkaar aanroepen.
Om te achterhalen wat relevante aspecten van positionering zijn in studentencode, hebben we gekeken in programma’s van studenten naar wat ons opviel over de positionering van code. Hierbij zijn twee voorbeelden gevonden waarbij de code niet is geoptimaliseerd voor de leesbaarheid. In het eerste voorbeeld wordt een variabele een waarde toegewezen tussen de declaratie van twee functies, maar de variabele werd pas na de declaratie van de functie gebruikt. Dit voorbeeld was in Python geschreven en een schematische weergave hiervan is in codefragment 3.1 weergegeven.
def f u n c t i e ( ) : −−code−− s t a r t g e l d = 100 def s t a r t ( g e l d ) : −−code−− s t a r t ( s t a r t g e l d )
Listing 3.1: Voorbeeld code waar de plaatsing van de declaratie van startgeld niet op een leesbare plek staat, want startgeld wordt pas onder de functie start gebruikt
Bij het tweede voorbeeld wordt een variabele in een functie eerst gedeclareerd met een deel van de input. Hierna staat code waar deze variabele niet in wordt gebruikt en daarna wordt deze variabele alsnog gecast. Dit voorbeeld was in Python geschreven en een schematische weergave hiervan is in codefragment 3.2 weergegeven.
def f u n c t i e ( datum ) :
maandgetal = datum [ 4 : 6 ]
−−code −−(geen g e b r u i k gemaakt van maand g e t a l ) maandgetal = i n t ( maandgetal )
Listing 3.2: Voorbeeld code waar de plaatsing van de declaratie van maandgetal niet op een leesbare plek staat, want maandgetal wordt pas later in de functie gebruikt
Deze twee voorbeelden zouden twee mogelijke eisen kunnen zijn voor de optimalisatie van de leesbaarheid van code. De deelvraag die hieruit volgt is: wat zijn de eisen omtrent de positionering van de code in een programma waaraan de code moet voldoen om geoptimaliseerd te zijn voor de leesbaarheid ? Wanneer er eisen zijn gevonden moeten we onderzoeken hoe deze eisen automatisch getest kunnen worden en daarom is een deelvraag: hoe kunnen we de eisen van de leesbaarheid van code automatisch testen? Na het testen van de eisen willen we niet alleen de programmeurs vertellen welke eisen er wel of niet goed zijn maar er ook feedback op geven. Hierdoor luidt de volgende deelvraag: hoe kunnen we goede feedback genereren voor programma’s van beginnende programmeurs?
Eisen van de leesbaarheid van een programma
Om de deelvraag wat zijn de eisen omtrent de positionering van de code in een programma waaraan de code moet voldoen om geoptimaliseerd te zijn voor de leesbaarheid te beantwoorden is er in de literatuur gekeken. Uit de literatuur komen de volgende richtlijnen:
1. Declaratie van een variabele dicht bij het gebruik van die variabele (McConnell, 2004) 2. Volgorde van declaraties is logisch (McConnell, 2004)
3. Lokale variabelen in functie zijn bovenaan de functie gedeclareerd (Martin, 2009)
4. Variabele die in een hele klasse worden gebruikt bovenaan de klasse zijn gedefinieerd (Martin, 2009)
5. Functies die elkaar aanroepen zijn dicht bij elkaar gedefinieerd (Martin, 2009)
In dit onderzoek zal naar twee van deze punten gekeken worden. Het eerste punt waar naar wordt gekeken is of variabelen die veel worden gebruikt in een functie zo veel mogelijk bovenaan de functie worden gedeclareerd. Het tweede punt is of declaratie van variabelen die weinig worden gebruikt dicht bij het gebruik van die variabele staan.
HOOFDSTUK 4
Methode
4.1
Automatisch testen van de eisen
Bij de deelvraag: hoe kunnen we de eisen van de leesbaarheid van code automatisch testen moet er gekeken worden naar de twee gekozen richtlijnen. Bij deze twee richtlijnen moet er gekeken worden naar een relatie tussen afstanden van verschillende stukken code. Om deze relatie goed te kunnen bekijken is gebruik gemaakt van een “abstract syntax tree”, ook wel ast genoemd. Een ast is een boomstructuur waar een abstracte versie van de inhoud van een programma in staat, dus details zoals haakjes worden niet opgeslagen. In elk van de nodes staat ´e´en structuur, zoals bijvoorbeeld een while-loop. Door een ast te gebruiken kan er door de code heen worden gelopen en kunnen de richtlijnen worden getest.
De tool test de richtlijnen door over alle variabele declaraties heen te lopen. Per variabele wordt gekeken hoe vaak deze variabele wordt gebruikt. Wanneer een variabele naast de declaratie meer dan ´e´en keer wordt gebruikt, moet de tool checken of de declaratie van deze variabele bovenaan de functie staat. De tool checkt dit door van bovenaf door de regels te lopen en te kijken of elke regel een declaratie bevat. Wanneer er een node wordt gevonden die geen declaratie is en de declaratie van de gezochte variabele is nog niet geweest dan zegt de tool dat het bij die variabele fout gaat. Bij een variabele die naast de declaratie maar op ´e´en plek wordt gebruikt moet de tool checken of de declaratie van deze variabele dicht bij het gebruik van de variabele staat. De tool checkt dit door een dictionary te gebruiken met als key elke variabele die gebruikt wordt tussen de declaratie en het gebruik van de variabele waar de tool op dit moment naar kijkt. De waarde in het dictionary wordt op true gezet wanneer een variabele gebruikt wordt en op false wanneer een variabele gedeclareerd wordt. Op het moment dat de tool de regel van het gebruik van de variabele heeft gehad wordt naar de dictionary gekeken. Als in de dictionary nog variabelen de waarde false hebben staat de declaratie van de variabele niet dicht genoeg bij het gebruik en zegt de tool dat het hier fout gaat. Deze methode is als pseudocode te zien in codefragment 4.1.
v a r d e c l s = g e t v a r d e c l s ( s c o p e ) e r r o r = [ ] f o r v a r d e c l in v a r d e c l s : v a r u s e s = f i n d v a r u s e s ( v a r d e c l ) #c h e c k v a r d e c l a t t o p i f ( len ( v a r u s e s ) > 1 ) : f o r node in c h i l d n o d e s ( s c o p e ) : i f ( node != d e c l and node . l i n e n u m b e r < v a r d e c l . l i n e n u m b e r ) : e r r o r . append ( ( ” t o p ” , v a r d e c l ) ) #c h e c k v a r d e c l c l o s e t o u s e e l s e : c h e c k n o d e s = f i n d c h e c k n o d e s ( s c o p e , v a r d e c l , v a r u s e s [ 0 ] ) u s e d = {} f o r node in c h e c k n o d e s : i f ( node == d e c l ) : u s e d [ node ] = F a l s e e l s e : u s e d [ node ] = True f o r key in u s e d : i f ( not u s e d [ key ] ) : e r r o r . append ( ( ” c l o s e ” , v a r d e c l ) )
Listing 4.1: Pseudocode die laat zien hoe de tool checkt of een fout omtrent de richtlijnen in het programma staat
Wanneer alle variabelen gecheckt zijn kijkt de tool of per richtlijn minstens ´e´en fout in het programma staat. Als minsten ´e´en fout in het programma staat omtrent een richtlijn wordt voor die richtlijn feedback gegeven.
De tool die de richtlijnen test is geschreven in Python 3 en gaat ervan uit dat het programma die de tool checkt in Python 3 staat geschreven. Dit komt doordat de tool gebruik maakt van de ast module.
4.2
Goede feedback genereren
De deelvraag: hoe kunnen we goede feedback genereren voor programma’s van beginnende program-meurs kan worden beantwoord door te kijken naar hoe studentassistenten feedback geven. Dit wordt gedaan door in de evaluatieronde met studentassistenten aan studentassistenten te vragen of ze in maximaal drie punten feedback op het programma willen geven. Met de resultaten uit de evaluatieronde met studentassistenten en literatuur over feedback wordt de feedback gemaakt die de tool geeft.
Nu de tool feedback geeft moet deze feedback getest worden. Dit wordt gedaan in de evaluatieronde met studenten. In deze evaluatieronde wordt aan studenten gevraagd om een programma te verbeteren aan de hand van de feedback die de tool op het programma gegenereerd heeft. Na deze evaluatieronde met studenten wordt de feedback verbeterd en dit is de uiteindelijke prototype van de tool. Dit iteratief proces van de evaluatie is in figuur 4.2 weergegeven.
Probleem stelling Richtlijnen Prototype tool Uiteindelijke prototype en richtlijnen Evaluatie 1 Evaluatie 2
Figuur 4.1: De volgorde van het onderzoek met twee keer een evaluatieronde
4.3
Samenvatting
Uit de literatuur komen vijf richtlijnen omtrent de positionering van code in een programma waaraan de code moet voldoen om geoptimaliseerd te zijn voor de leesbaarheid. Van deze vijf richtlijnen worden twee richtlijnen ge ¨mplementeerd in een tool met behulp van de Python ast module. Wanneer de tool minstens ´e´en fout omtrent een richtlijn in een programma vindt moet voor die richtlijn feedback worden gegeven. Deze feedback is geconstrueerd door te kijken naar de literatuur over feedback en de resultaten van de evaluatieronde met studentassistenten. De feedback die hieruit komt wordt getest in de evaluatieronde met studenten.
HOOFDSTUK 5
Evaluatie van de tool
Tijdens de evaluatie van de tool worden keuzes in de tool getest. De eerste keuze die getest wordt is het aantal keer dat een variabele gebruikt moet zijn om als een veelgebruikte variabele te worden bestempeld. Deze keuze is belangrijk omdat aan de hand van hoe vaak een variabele voorkomt een andere richtlijn moet worden gevolgd. Om een goed aantal te kiezen is in de aantal variabelen test gekeken naar het aantal fouten voor twee verschillende aantallen. Om een nog beter idee te krijgen of dit een goed aantal is wordt in de evaluatieronde met studentassistenten het aantal fouten die de tool geeft vergeleken met wat studentassistenten fout rekenen.
Verder moet de tool goede feedback geven. Deze feedback wordt gemaakt door te kijken naar de feedback die studentassistenten geven op programma’s. Na deze ronde kan de tool feedback maken, maar deze feedback moet getest worden. De feedback van de tool wordt getest in de evaluatieronde met studenten waar gekeken wordt of studenten de feedback kunnen gebruiken om een programma te verbeteren.
5.1
Aantal variabelen test
Bij de twee richtlijnen die de tool test wordt een verschil gemaakt tussen veel of weinig gebruik van een variabele, maar er wordt niet beschreven hoe vaak een variabele moet worden gebruikt om bestempeld te worden als een veelgebruikte variabele. Om een idee te krijgen hoe vaak een variabele moet worden gebruikt om bestempeld te worden als veelgebruikt wordt in deze aantal variabelen test gekeken naar het verschil in fouten tussen het aantal twee en drie. Dus de tool checkt eerst of een variabele naast de declaratie meer dan twee of drie keer voorkomt in een programma. In deze test wordt door een groot aantal programma’s van studenten gelopen. Deze programma’s komen uit twee data sets en bestaan uit verschillende opdrachten zodat de programma’s gevarieerd zijn. Het aantal fouten per richtlijn wordt opgeteld en aan het eind geprint samen met het aantal programma’s.
5.2
Resultaten aantal variabelen test
De resultaten van de aantal variabelen test is te zien in tabel 5.1. Uit de tabel is te zien dat bij een waarde van twee de tool minder fouten vind als gevolg van een declaratie die niet bovenaan staat, maar meer fouten vind als gevolg van een declaratie die niet dicht genoeg bij gebruik staat. Ook is het totaal aantal fouten hoger. Aan de hand van deze resultaten leek het beter om de waarde twee te gebruiken, omdat anders studenten heel veel fouten in hun programma’s hebben staan en in dat geval het de vraag is of de studenten het wel goed geleerd wordt. Dit is een keuze in het onderzoek en moet getest worden in de evaluatieronde met studentassistenten. In deze
Tabel 5.1: Resultaten van de aantal variabelen test waarbij het aantal gaat over hoe vaak een variabele gebruikt moet worden om als veelgebruikt bestempeld te worden
Dataset 1 met aantal=2 Dataset 1 met aantal=3 Dataset 2 met aantal=2 Dataset 2 met aantal=3 Aantal programma’s 168 168 2386 2386
Aantal gevonden fouten vanwege een declaratie niet bovenaan
39 15 968 603
Aantal gevonden fouten vanwege een declaratie niet dicht genoeg bij gebruik
53 270 935 1859 Totaal aantal gevonden fouten 92 285 1903 2462
5.3
Opzet evaluatieronde met studentassistenten
In deze evaluatieronde wordt gekeken naar hoe studentassistenten feedback geven. Dit wordt gebruikt om de feedback van de tool te maken. Verder wordt in deze evaluatieronde gekeken naar wat de studentassistenten fout rekenen. Dit wordt vergeleken met wat de tool fout rekent om een idee te krijgen of het aantal dat onderscheid maakt tussen veel en weinig gebruik van een variabele goed is.
Tijdens deze evaluatieronde wordt door twee studentassistenten afzonderlijk van elkaar naar programma’s van studenten gekeken. Als eerste moet aan de studentassistenten gevraagd worden of het goed is om een geluidsopname te maken van de evaluatie. Ook moet uitgelegd worden hoe deze evaluatieronde in elkaar zit en wat van de studentassistenten verwacht wordt. Verder moet aan de studentassistenten duidelijk verteld worden wat de richtlijnen zijn waarop ze de programma’s van studenten gaan beoordelen en feedback op geven. Deze richtlijnen worden op een blaadje op tafel gelegd zodat de studentassistenten tijdens het geven van verbeterpunten naar de richtlijnen kan kijken. De richtlijnen zijn:
1. Variabelen die veel worden gebruikt in een functie moeten zo veel mogelijk bovenaan de functie worden gedeclareerd
2. Declaratie van variabelen die weinig worden gebruikt moeten dicht bij het gebruik van die variabele staan
Hierna wordt er aan de studentassistenten gevraagd om door de programma’s van studen-ten te gaan en alle verbeterpunstuden-ten in de programma’s op te schrijven aan de hand van hun interpretatie van de richtlijnen. Dit wordt gedaan door een papieren versie van het programma aan de studentassistenten te geven en ze op de code de verbeteringen te laten schrijven. Deze verbeteringen worden door de studentassistenten afzonderlijk van elkaar opgeschreven zodat we twee meetresultaten hebben. Wanneer een studentassistent verbeteringen geeft die niets te maken hebben met de richtlijnen wordt de studentassistent nogmaals op de richtlijnen gewezen. Ook kan er aan de studentassistent gevraagd worden waarom hij of zij een stukje code wel of niet wil verbeteren. Als de studentassistenten klaar zijn met het opschrijven van alle verbeteringen worden ze gevraagd om drie punten op te schrijven die hij of zij aan de student als feedback wil geven. Tot slot wordt nadat beide studentassistenten klaar zijn met het opschrijven van de drie feedback punten een discussie gestart met de vraag waarom ze die drie feedback punten hebben gegeven. Deze evaluatie wordt op 5 programma’s van studenten uitgevoerd. Deze programma’s zijn gekozen op het feit dat ze een variatie aan aantal verbeteringen hebben volgens de feedback
een variabele twee of meer keer gebruikt wordt te bestempelen als een veelgebruikte variabele. De studentassistenten gaven twee redenen waarom ze deze instanties niet fout rekenden. De eerste reden is dat de student een stappenplan volgt. Hierdoor vinden de studentassistenten dat de code een leesbare volgorde heeft en dus in dit geval geen feedback op het programma moet worden gegeven. De tweede reden is dat wanneer een variabele meerdere keren wordt gebruikt, maar al deze keren dat de variabele wordt gebruikt staat de variabele in dezelfde blok code. In dit geval zou volgens de richtlijnen de declaratie van de variabele zoveel mogelijk boven aan staan, maar de studentassistenten vonden dat wanneer de variabele in ´e´en blok code wordt gebruikt de declaratie zo dicht mogelijk bij de blok code moet staan. Verder gaven de studentassistenten heel algemene feedback wanneer ze gevraagd werden om in maximaal drie punten feedback te geven op het programma.
Aan de hand van deze resultaten is gekeken naar een manier om de tool te verbeteren zodat de tool de twee redenen die de studentassistenten niet fout rekenden ook niet fout rekent. Voor de reden dat het programma een stappenplan volgt is geen verbetering bedacht, omdat een stappenplan van de programmeeropdracht afhangt en daardoor moeilijk te checken is wanneer een student een stappenplan volgt. Bij de reden dat een variabele meerdere keren gebruikt wordt in ´e´en blok code is bedacht om te checken of een variabele alleen gebruikt wordt vanaf zijn eigen declaratie tot de volgende declaratie van andere variabele. Hierbij is de volgende declaratie niet de declaratie van variabelen die onder de declaratie van de variabele die gecheckt wordt staan, maar de declaratie van een variabele dat na code anders dan een declaratie staat. Het probleem van deze methode is dat er heel veel code tussen variabele declaraties kan staan. Ook wordt bij deze methode in het geval dat er veel variabele declaraties achter elkaar staan die berekeningen uitvoeren niet goed naar de volgorde van de variabele declaraties gekeken. Vanwege deze problemen is deze methode niet in de tool verwerkt.
5.5
Opzet evaluatieronde met studenten
Het doel van de evaluatieronde met studenten is om erachter te komen hoe bruikbaar de feedback die de tool automatisch genereert voor studenten is. Met bruikbaar wordt hier bedoelt of studenten aan de hand van de feedback een beter begrip krijgen over het onderwerp waarop de tool feedback geeft. Dit wordt getest door drie studenten aan de hand van de feedback die de tool geeft een programma te laten verbeteren. Deze studenten hebben beginnende programmeer kennis. Twee studenten waren bezig met de minor programmeren en de derde student had ´e´en programmeer vak gehad in het eerste jaar van de b`eta-gamma studie.
Ter voorbereiding van de evaluatieronde moet er een programma gekozen worden die de studenten gaan verbeteren. Dit programma is gekozen op het feit dat er veel fouten in staan wanneer er naar de volgende richtlijnen wordt gekeken:
1. Variabelen die veel worden gebruikt in een functie moeten zo veel mogelijk bovenaan de functie worden gedeclareerd
2. Declaratie van variabelen die weinig worden gebruikt moeten dicht bij het gebruik van die variabele staan
Het aantal van deze fouten in het programma wordt van te voren geteld om na afloop van de evaluatieronde een vergelijking te kunnen maken. Dit programma staat in appendix B. De feedback die de tool op dit programma genereert is te zien in figuur 5.1.
Tijdens de evaluatieronde worden de studenten achter een computer of laptop gezet. Op deze computer staat het programma in een editor zodat de studenten aanpassingen kunnen maken. Ook krijgen de studenten op een blaadje de feedback die de tool op het programma genereert. Hierna wordt aan de studenten gevraagd om aan de hand van de feedback het programma in de editor te verbeteren. Nadat de studenten het programma verbetert hebben worden het aantal fouten conform de richtlijnen geteld.
Figuur 5.1: De feedback die de tool genereert bij het programma van de evaluatieronde met studenten
staan kunnen de studenten goed gebruikmaken van de feedback. Wanneer dit verschil in fouten volgens de richtlijnen klein is kunnen de studenten niet goed gebruikmaken van de feedback om het programma te verbeteren.
Tijdens deze evaluatieronde wordt aangenomen dat er geen verschil is tussen het verbeteren van een student zijn eigen programma en het verbeteren van een programma van iemand anders. Ook wordt aangenomen dat de studenten niet zonder de feedback al de fouten uit het programma zouden kunnen halen. Verder wordt aangenomen dat het gekozen programma een representatief beeld geeft van een programma dat de studenten zouden kunnen hebben geschreven.
5.6
Resultaten evaluatieronde met studenten
De door de studenten verbeterde programma’s staan in appendix B. Alle studenten verbeteren alleen de twee voorbeelden die in de feedback staan. Naar de andere fouten in het programma wordt niet gekeken. Een student gaf aan dat een verbetering zou kunnen zijn als het aantal fouten per richtlijn in de feedback vermeld staat.
5.7
Conclusie
Naar aanleiding van de aantal variabelen test kiezen we dat het aantal keer dat een variabele moet worden gebruikt om bestempeld te worden als veelgebruikt twee is, omdat bij een aantal van drie de tool veel meer fouten vond. Aan de hand van de evaluatieronde met studentassistenten lijkt dit een goede keuze want de studentassistenten vonden minder fouten in de programma’s dan de tool.
Uit de evaluatieronde met studentassistenten kwam dat de studentassistenten algemene feedback gaven. Hierdoor is feedback gemaakt die maar op ´e´en fout per richtlijn feedback geeft. In de evaluatieronde met studenten bleek dat studenten alleen de twee voorbeelden verbeteren en niet verder in het programma gaan kijken om meer fouten te vinden. Aan de hand van dit resultaat is de feedback die de tool geeft aangepast, de tool laat nu ook het aantal fouten per richtlijn zien.
HOOFDSTUK 6
Conclusie
De deelvraag: wat zijn de eisen omtrent de positionering van de code in een programma waaraan de code moet voldoen om geoptimaliseerd te zijn voor de leesbaarheid is beantwoord door in de literatuur te kijken. In de literatuur zijn de volgende vijf richtlijnen gevonden:
1. Declaratie van een variabele dicht bij het gebruik van die variabele (McConnell, 2004) 2. Volgorde van declaraties is logisch (McConnell, 2004)
3. Lokale variabelen in functie zijn bovenaan de functie gedeclareerd (Martin, 2009)
4. Variabele die in een hele klasse worden gebruikt bovenaan de klasse zijn gedefinieerd (Martin, 2009)
5. Functies die elkaar aanroepen zijn dicht bij elkaar gedefinieerd (Martin, 2009)
In dit onderzoek is naar twee van deze punten gekeken. Het eerste punt is of variabelen die veel worden gebruikt in een functie zo veel mogelijk bovenaan de functie worden gedeclareerd. Het tweede punt is of declaratie van variabelen die weinig worden gebruikt dicht bij het gebruik van die variabele staan.
Om de deelvraag: hoe kunnen we de eisen van de leesbaarheid van code automatisch testen te beantwoorden is een tool gemaakt in Python. Deze tool maakt gebruik van de ast module om door het programma heen te lopen. De tool test de richtlijnen door over alle declaratie heen te lopen en vervolgens te kijken hoe vaak elke variabele wordt gebruikt. Wanneer een variabele veelgebruikt wordt moet de tool checken of de variabele bovenaan staat gedeclareerd. Dit wordt gedaan door vanaf bovenaan steeds naar de volgende node te gaan en te kijken of dit een declaratie is. Op het moment dat de node geen declaratie meer is en de declaratie van de variabele is nog niet geweest wordt dit als fout onthouden. Wanneer een variabele weinig wordt gebruikt moet de tool testen of de declaratie zo dicht mogelijk bij het gebruik van de variabele staat. Dit wordt gedaan door alle regels tussen declaratie en gebruik van de variabele langs te gaan en te kijken of de variabelen die daar tussen worden gedeclareerd op een andere regel daartussen worden gebruikt. Als dat niet het geval is wordt dit als fout onthouden. De deelvraag: hoe kunnen we goede feedback genereren voor programma’s van beginnende programmeurs is beantwoord door te kijken naar de literatuur over feedback en evaluatierondes. Goede feedback kan gegenereerd worden door per richtlijn eerst in ´e´en regel de richtlijn uit te leggen. Vervolgens het aantal fouten van de richtlijn te vermelden en tot slot een voorbeeld te geven waar deze richtlijn fout gaat. Een voorbeeld van feedback die de tool genereert is te zien in
Figuur 6.1: De feedback die de tool genereert bij het programma van de evaluatieronde met studenten
De drie deelvragen beantwoorden de hoofdvraag: hoe kan er automatische feedback worden gegeven op de leesbaarheid van de code als gevolg van de positionering in een programma. Automa-tische feedback kan worden gegeven op de leesbaarheid van de code als gevolg van de positionering in een programma door een tool in Python te schrijven. Deze tool test twee van de vijf in de literatuur gevonden richtlijnen door gebruik te maken van de ast module. Als de tool ten minste ´e´en fout omtrent een richtlijn in het programma vind wordt feedback geprint. Deze feedback legt eerst de richtlijn uit en vervolgens wordt het aantal fouten omtrent deze richtlijn verteld. Tot slot staat in de feedback een voorbeeld waar in het programma dit fout gaat.
HOOFDSTUK 7
Discussie
In dit onderzoek worden verschillende aannames gemaakt waar rekening mee moet worden gehouden. Bij de aantal variabelen test wordt aangenomen dat de dataset representatief is voor een programma van een beginnende student. Deze aanname houd geen rekening met de mogelijkheid dat de opdrachten, die in de programma’s zijn verwerkt, een bepaalde structuur hebben waardoor extra fouten in de programma’s voorkomen.
In de evaluatieronde met studentassistenten worden twee studentassistenten die op de UvA werken gebruikt om te kijken naar waar en hoe zij feedback geven. Hierdoor is het resultaat van de evaluatieronde met studentassistenten niet heel representatief. Deze studentassistenten geven waarschijnlijk anders feedback dan studentassistenten van andere universiteiten. Maar toch geeft dit een beeld van hoe studentassistenten feedback geven en vanwege de iteratie in dit onderzoek is het resultaat van de evaluatieronde met studentassistenten vooral een goed beginpunt voor de feedback. Deze evaluatieronde had ook nog beter kunnen verlopen omdat de studentassistenten ook gingen kijken naar fouten die in het programma staan maar die niet betrekking hadden tot de richtlijnen. Ook is het mogelijk dat studentassistenten over een mogelijk fout heen lezen. Een mogelijke verbetering is om een specifiek stukje code aan te wijzen en aan de studentassistenten te vragen of dit wel of niet conform de richtlijnen is.
Bij de evaluatieronde met studenten wordt aan studenten gevraagd om een programma aan de hand van de feedback te verbeteren. Hier wordt aangenomen dat studenten andermans programma net zo verbeteren als hun eigen programma. Ook is in deze evaluatieronde geen controlegroep die het programma verbetert zonder de feedback van de tool. Tijdens deze evaluatieronde bestond de mogelijkheid dat de student ook zonder de feedback het programma zou kunnen verbeteren. Een mogelijkheid om dit beter te doen is om voordat de studenten de feedback krijgen te vragen welke verbetering zij zouden maken aan het programma.
Vervolgonderzoek
In een vervolgonderzoek kan gekeken worden naar de richtlijnen die uit de literatuur kwamen maar niet in de tool zijn verwerkt. Ook kan gekeken worden naar het implementeren van de richtlijnen voor andere programmeertalen.
Om de tool die in dit onderzoek is ge¨ımplementeerd te verbeteren kan in een volgend onderzoek een evaluatie iteratie worden toegevoegd. Deze evaluatie moet met een grote groep studenten worden gedaan waarbij de ene helft een opdracht verbeterd met gebruik van de feedback van de tool en de andere helft zonder deze feedback. Hierdoor ontstaat een controlegroep waarmee de groep die de feedback van de tool wel heeft kan worden vergeleken.
Bibliografie
Ala-Mutka, Kirsti M (2005). “A survey of automated assessment approaches for programming assignments”. In: Computer science education 15(2), p. 83–102.
Buse, Raymond PL en Westley R Weimer (2008). “A metric for software readability”. In: Proceedings of the 2008 international symposium on Software testing and analysis. ACM, p. 121–130.
Collar Jr, Emilio en Ricardo Valerdi (2006). Role of software readability on software development cost. Tech. rap.
Hattie, John en Helen Timperley (2007). “The power of feedback”. In: Review of educational research 77(1), p. 81–112.
Kernighan, Brian W en Phillip James Plauger (1978). “The elements of programming style”. In: The elements of programming style, by Kernighan, Brian W.; Plauger, PJ New York: McGraw-Hill, c1978.
Martin, Robert C (2009). Clean code: a handbook of agile software craftsmanship. Pearson Education.
McConnell, Steve (2004). Code complete. Pearson Education.
Rees, Michael J (1982). “Automatic assessment aids for Pascal programs”. In: ACM Sigplan Notices 17(10), p. 33–42.
Shneiderman, Ben (1976). “Exploratory experiments in programmer behavior”. In: International Journal of Computer & Information Sciences 5(2), p. 123–143.
Stegeman, Martijn, Erik Barendsen en Sjaak Smetsers (2014). “Towards an empirically validated model for assessment of code quality”. In: Proceedings of the 14th Koli Calling international conference on computing education research. ACM, p. 99–108.
Stegeman, Martijn, Erik Barendsen en Sjaak Smetsers (2016). “Designing a rubric for feedback on code quality in programming courses”. In: Proceedings of the 16th Koli Calling International Conference on Computing Education Research. ACM, p. 160–164.
BIJLAGE A
Programma’s gebruikt in de evaluatieronde
met studentassistenten
A.1
Montecarlo.py
import random import numpy a s np import math def m o n t e c a r l o ( f , x1 , x2 , y1 , y2 ) : #y1=f ( x1 ) #y2=f ( x2 )#we nemen nu ymin en xmin a l s h e t minimum wat f aanneemt op ( x1 , x2 ) en h e t maximum idem ymax
ymin=min(map( f , np . a r a n g e ( x1 , x2 , 0 . 0 1 ) . t o l i s t ( ) ) ) ymax=max(map( f , np . a r a n g e ( x1 , x2 , 0 . 0 1 ) . t o l i s t ( ) ) )
#h e t g e b i e d wat we w i l l e n d e f i n i e r e n i s dan ( x1 , x2 )X( ymin , ymax ) \ s u b s e t Rˆ2
Gebied = [( x , y ) f o r x in np . a r a n g e ( x1 , x2 , 0 . 0 0 1 ) . t o l i s t ( ) f o r y in np . a r a n g e ( ymin , ymax , 0 . 0 0 1 ) . t o l i s t ( ) ]
#nu w i l l e n we k i j k e n waar f p o s i t i e f en waar f n e g a t i e f b l i j k t , g e e f dus een v o o r w a a r d e l i j k e e x p r e s s i e v o o r h e t t e k e n van opp
s i g n =0
i f math . f a b s ( y )<=math . f a b s ( f ( x ) ) : i f f ( x )>0 and y>0 and y<=f ( x ) :
s i g n=s i g n +1
i f f ( x )<0 and y<0 and y>= f ( x ) : s i g n=s i g n −1
#neem 100000 random p u n t e n u i t h e t g e d e f i n i e e r d e r e c h t h o e k i g e g e b i e d l=random . sample ( Gebied , 1 0 0 0 0 0 )
#d e f i n i e e r h e t i n t e g r a t i e g e b i e d d o o r t e k i j k e n naar waar y o n d e r de g r a f i e k l i g t ( we w i l l e n dus d a t de f u n c t i e de rand van h e t
i n t e g r a t i e g e b i e d w o r d t )
i f ( x , y ) in l and ( x , y ) in I n t G e b i e d : f g o e d . append ( ( x , y ) )
#nu i s v o l g e n s monte c a r l o h e t p r o d u c t van h e t g e b i e d x h e t a a n t p u n t e n g e l i j k aan h e t opp
opp=s i g n ∗ len ( f g o e d ) ∗ ( math . s q r t ( x2−x1 ) ∗ ∗ 2 ) ∗ ( ymax−ymin ) return opp
A.2
medicine.py
# m e d i c i n e . py # # Minor KI s e p t 2017 − f e b 2018 # I n l e i d i n g Programmeren # ## T h i s i s e x e r c i s e m e d i c i n e . py from Problem S e t 5 from # h t t p s : / / p r o g k i . mprog . n l / problem−s e t −5/ s i m u l e r e n . #
# C a l c u l a t e t h e number o f c u r e d p a t i e n t s , g i v e n t h a t t h e y a r e i n f e c t e d w i t h a
# v i r u s and a r e a d m i n i s t e r e d a m e d i c i n e a f t e r some t i m e . The v i r u s p o p u l a t i o n can b e s i m u l a t e d
# a t v a r i o u s t i m e s t e p s . V i r u s e s can d i e , r e p r o d u c e and mutate w i t h a g i v e n p r o b a b i l i t y . # A f t e r t h e m e d i c i n e i s a d m i n i s t e r e d , o n l y r e s i s t a n t v i r u s e s can r e p r o d u c e . import i n f e c t i o n a s i n f # r e s i s t e n t n u c l e o t i d e s e q u e n c e RESISTENT = ”AAA” # t i m e m e d i c i n e i s a d m i n i s t e r e d ADMINISTER TIME = 100 # r e t u r n True i f v i r u s c o n t a i n s r e s i s t e n t n u c l e o t i d e s e q u e n c e def i s R e s i s t e n t ( v i r u s ) : return v i r u s . f i n d (RESISTENT) != −1 # s i m u l a t e a v i r u s p o p u l a t i o n and r e t u r n t h e p o p u l a t i o n s i z e a t e a c h t i m e s t e p def s i m u l a t e ( v i r u s e s , m o r t a l i t y P r o b , mutationProb , maxReproductionProb , maxPopulation , t i m e s t e p s = 5 0 0 ) : # p o p u l a t i o n s i z e a t t = 0 p o p u l a t i o n s i z e = [ len ( v i r u s e s ) ] # c a l c u l a t e p o p u l a t i o n s i z e s b e f o r e m e d i c i n e i s a d m i n i s t e r e d f o r in range (ADMINISTER TIME) :
t = t i m e s t e p s
f o r in range (ADMINISTER TIME, t i m e s t e p s ) : v i r u s e s = i n f . k i l l ( v i r u s e s , m o r t a l i t y P r o b ) r e p r o P r o b = i n f . r e p r o d u c t i o n P r o b a b i l i t y ( v i r u s e s , maxReproductionProb , maxPopulation ) # g e t r e s i s t a n t and non r e s i s t a n t v i r u s e s r e s , n o n r e s = [ ] , [ ] f o r v in v i r u s e s : r e s . append ( v ) i f i s R e s i s t e n t ( v ) e l s e n o n r e s . append ( v ) # l e t r e s i s t a n t v i r u s e s r e p r o d u c e r e s p l u s c h i l d s = i n f . r e p r o d u c e ( r e s , mutationProb , r e p r o P r o b ) # g e t w h o l e p o p u l a t i o n v i r u s e s = n o n r e s + r e s p l u s c h i l d s p o p u l a t i o n s i z e . append ( len ( v i r u s e s ) ) return p o p u l a t i o n s i z e # r e t u r n number o f c u r e d p a t i e n t s a f t e r s i m u l a t i n g v i r u s e s and m e d i c i n e def e x p e r i m e n t ( n u m b e r O f P a t i e n t s ) : genomeLength = 16 s t a r t s i z e = 10 t i m e s t e p s = 500 maxPopulation = 1000 maxReproductionProb = 0 . 0 7 m o r t a l i t y P r o b = 0 . 0 5 mutationProb = 0 . 1 0 c u r e d = 0 # s i m u l a t e t h e v i r u s p o p u l a t i o n i n e a c h p a t i e n t and c h e c k f o r c u r e d f o r in range ( n u m b e r O f P a t i e n t s ) : # g e t p a t i e n t ’ s v i r u s e s v i r u s e s = [ i n f . g e n e r a t e V i r u s ( genomeLength ) f o r in range ( s t a r t s i z e ) ] # s i m u l a t e v i r u s p o p u l a t i o n p o p u l a t i o n s i z e s = s i m u l a t e ( v i r u s e s , m o r t a l i t y P r o b , mutationProb , maxReproductionProb , maxPopulation , t i m e s t e p s ) # p a t i e n t i s c u r e d i f t h e r e a r e no v i r u s e s l e f t a t t h e end i f p o p u l a t i o n s i z e s [ − 1 ] == 0 : c u r e d += 1 return c u r e d
print ( s i m u l a t e ( v i r u s e s , 0 . 8 , 0 . 5 , 0 . 9 , 2 0 0 ) ) print ( ”=” ∗ 8 0 ) print ( s i m u l a t e ( v i r u s e s , 0 . 2 5 , 0 . 1 , 0 . 5 , 1 0 0 ) ) print ( ”=” ∗ 8 0 ) print ( s i m u l a t e ( v i r u s e s , 0 , 0 , 0 , 1 0 0 ) ) print ( ”=” ∗ 8 0 ) print ( e x p e r i m e n t ( 1 0 0 ) )
A.3
histogram.py
# b e p a a l v o o r 1 0 . 0 0 0 e x p e r i m e n t e n de som van 100 r a n d o m g e t a l l e n # a l s de som k l e i n e r i s dan 40 o f g r o t e r i s dan 60 d o e t d i e n i e t mee # p l a a t s de d i s t r i b u t i e i n een h i s t o g r a m import random import m a t p l o t l i b . p y p l o t a s p l t # d e f i n e e r t de f u n c t i e def SomRandomGetallen ( ) : # e x p e r i m e n t 1 0 . 0 0 0 k e e r h e r h a l e n (N) N = 10000 e x p l i j s t = [ ] m i n d e r 4 0 = 0 m e e r 6 0 = 0 # b e p a a l d v o o r de 1 0 . 0 0 0 e x p e r i m e n t e n de som van 100 r a n d o m g e t a l l e n f o r c o u n t e r in range (N) : som = 0 f o r exp in range ( 0 , 1 0 1 ) : x = random . random ( ) som = som + x# de sommen d i e k l e i n e r z i j n dan 40 o f g r o t e r z i j n dan 60 worden e r u i t g e g o o i t i f som < 4 0 : m i n d e r 4 0 = m i n d e r 4 0 + 1 i f som > 6 0 : m e e r 6 0 = m e e r 6 0 + 1 # i n t h e l i j s t worden de r e s u l t a t e n g e p l a a t s t e x p l i j s t . append ( som ) return e x p l i j s t
#p r i n t ”40 i s %.4 f ” %p r o c e n t 4 0 #p r i n t ”60 i s %.4 f ” %p r o c e n t 6 0 # de f u n c t i e w o r d t g e p l o t t u s s e n 30 en 70 # o p g e d e e l t i n s t u k j e s van 50 ( b i n s ) p l t . x l i m ( 3 0 , 7 0 ) p l t . h i s t ( e x p e r i m e n t , b i n s = 5 0 ) p l t . show ( )
A.4
medicine.py
# m e d i c i n e . py # I n l e i d i n g programmeren # s i m u l e e r t en t e s t de w e r k i n g van een m e d i c i j n import i n f e c t i o n def main ( ) : print ( i s R e s i s t e n t ( ’AAA ’ ) ) l e n g t h = 4 v i r u s = i n f e c t i o n . g e n e r a t e V i r u s ( l e n g t h ) v i r u s e s = [ i n f e c t i o n . g e n e r a t e V i r u s ( l e n g t h ) f o r i in range ( 1 0 0 ) ] m o r t a l i t y P r o b = 0 . 1 mutationProb = 0 . 1 maxReproductionProb = 0 . 5 maxPopulation = 100 r e p r o d u c t i o n P r o b = i n f e c t i o n . r e p r o d u c t i o n P r o b a b i l i t y ( v i r u s e s , maxReproductionProb , maxPopulation ) o v e r l e v e n d e = i n f e c t i o n . k i l l ( [ i n f e c t i o n . g e n e r a t e V i r u s ( 4 ) f o r i in range ( 1 0 0 ) ] , 0 . 2 ) l i j s t = s i m u l a t e ( v i r u s e s , m o r t a l i t y P r o b , mutationProb , maxReproductionProb , maxPopulation , t i m e s t e p s = 5 0 0 ) print ( l i j s t ) def i s R e s i s t e n t ( v i r u s ) : # a l s AAA i n h e t v i r u s z i t r e t u r n True i f ’AAA ’ in v i r u s : return True e l s e : return F a l s e def e x p e r i m e n t ( n u m b e r O f P a t i e n t s ) : c u r e d p a t i e n t s = 0 # v o e r d e z e l o o p u i t v o o r h e t a a n t a l p a t i e n t e n f o r i in range ( n u m b e r O f P a t i e n t s ) : # g e n e r e e r 10 v i r u s s e n v i r u s = [ i n f e c t i o n . g e n e r a t e V i r u s ( 1 6 ) f o r i in range ( 1 0 ) ] # v o e r nu de s i m u l a t i e u i t r e s t = s i m u l a t e ( v i r u s , 0 . 0 5 , 0 . 1 , 0 . 0 7 , 1 0 0 0 , t i m e s t e p s = 5 0 0 ) # a l s e r u i t e i n d e l i j k 0 v i r u s s e n o v e r z i j n t e l d e z e p e r s o o n dan b i j g e n e z e n i f r e s t [ − 1 ] == 0 :def s i m u l a t e ( v i r u s e s , m o r t a l i t y P r o b , mutationProb , maxReproductionProb , maxPopulation , t i m e s t e p s = 5 0 0 ) : s i m u l a t e l i s t = [ ] s i m u l a t e l i s t . append ( len ( v i r u s e s ) ) # muteer v i r u s s e n 100 k e e r f o r i in range ( 1 0 0 ) : v i r u s e s = i n f e c t i o n . k i l l ( v i r u s e s , m o r t a l i t y P r o b ) r e p r o d u c t i o n P r o b = i n f e c t i o n . r e p r o d u c t i o n P r o b a b i l i t y ( v i r u s e s , maxReproductionProb , maxPopulation ) v i r u s e s = i n f e c t i o n . r e p r o d u c e ( v i r u s e s , mutationProb , r e p r o d u c t i o n P r o b ) s i m u l a t e l i s t . append ( len ( v i r u s e s ) )
# maak t w e e nieuwe l i j s t e n van v i r u s s e n d i e r e s i s t e n t en v i r u s s e n d i e non−r e s i s t e n t z i j n na 100 t i j d s s t a p p e n
r e s i s t a n t v i r u s = [ v i r u s f o r v i r u s in v i r u s e s i f i s R e s i s t e n t ( v i r u s ) ]
n o n r e s t v i r u s = [ v i r u s f o r v i r u s in v i r u s e s i f not i s R e s i s t e n t ( v i r u s ) ]
# run de r e s t van de s i m u l a t i e met a l l e e n de r e s i s t e n t e v i r u s s e n + run k i l l nog v o o r a l l e e n de non−r e s i s t e n t e
f o r i in range ( t i m e s t e p s − 1 0 0 ) : r e s i s t a n t v i r u s = i n f e c t i o n . k i l l ( r e s i s t a n t v i r u s , m o r t a l i t y P r o b ) r e p r o d u c t i o n P r o b = i n f e c t i o n . r e p r o d u c t i o n P r o b a b i l i t y ( r e s i s t a n t v i r u s , maxReproductionProb , maxPopulation ) r e s i s t a n t v i r u s = i n f e c t i o n . r e p r o d u c e ( r e s i s t a n t v i r u s , mutationProb , r e p r o d u c t i o n P r o b ) n o n r e s t v i r u s = i n f e c t i o n . k i l l ( n o n r e s t v i r u s , m o r t a l i t y P r o b ) # t e l g r o o t t e van r e s i s t e n t e en non−r e s i s t e n t e v i r u s s e n b i j e l k a a r op v o o r t o t a a l
s i m u l a t e l i s t . append ( ( len ( r e s i s t a n t v i r u s ) + len ( n o n r e s t v i r u s ) ) ) return s i m u l a t e l i s t i f n a m e == ” m a i n ” : main ( )
A.5
afstand.py
import random a s rnd import math a s mt def v i e r k a n t ( ) : a f s t a n d e n = [ ]f o r h in range ( 1 0 ∗ ∗ 4 ) : x = [ ] y = [ ] f o r i in range ( 2 ) : i = rnd . random ( ) x . append ( i ) i = rnd . random ( ) y . append ( i ) a f s t a n d e n . append ( mt . s q r t ( ( x [ 1 ] − x [ 0 ] ) ∗∗2 + ( y [ 1 ] − y [ 0 ] ) ∗ ∗ 2 ) ) #Het g e m i d d e l d e van d e z e l i j s t met a f s t a n d e n b e r e k e n i k d o o r a l l e
w a a r d e s #b i j e l k a a r op t e t e l l e n en t e d e l e n d o o r de l e n g t e van d e z e l i j s t . som = 0 f o r j in a f s t a n d e n : som += j
return som / len ( a f s t a n d e n ) print ( v i e r k a n t ( ) )
BIJLAGE B
Originele programma en resulterende
programma’s van de evaluatieronde met
studenten
B.1
Origineel programma
# E n c r y p t s a p l a i n t e x t w i t h a k e y ( number ) g i v e n by t h e u s e r import s y s def main ( ) : # i f t h e amount o f a rg u m e n t s i s n o t 2 , e r r o r i f len ( s y s . a r g v ) != 2 :print ( ” u s a g e : python c a e s a r . py key ” ) e x i t ( 1 ) # g e t u s e r i n p u t p l a i n t e x t = input ( ” P l a i n t e x t : ” ) print ( ” C i p h e r t e x t : ” , end=” ” ) # t h e argument g i v e n by t h e u s e r becomes t h e k e y key = i n t ( s y s . a r g v [ 1 ] ) # v a r i a b l e s d e c l a r a t i o n c a p i t a l l o w e r b o u n d = 65 c a p i t a l u p p e r b o u n d = 90 l o w e r c a s e l o w e r b o u n d = 97 l o w e r c a s e u p p e r b o u n d = 122 a l p h a b e t i c a l n u m = 26 c a p i t a l = 65 l o w e r c a s e = 97 # i t e r a t e s o v e r e v e r y c h a r a c t e r o f p l a i n t e x t f o r i in p l a i n t e x t : # c a l c u l a t e s c h a r i f i ’ t h c h a r o f p l a i n t e x t i s c a p i t a l
a l p h a b e t i c a l n u m ) + c a p i t a l ) ) , end=” ” )
# c a l c u l a t e s c h a r i f i ’ t h c h a r o f p l a i n t e x t i s l o w e r c a s e e l i f ord ( i ) >= l o w e r c a s e l o w e r b o u n d and ord ( i ) <=
l o w e r c a s e u p p e r b o u n d :
print ( ” {} ” . format ( chr ( ( ( ord ( i ) − l o w e r c a s e + key ) % a l p h a b e t i c a l n u m
) + l o w e r c a s e ) ) , end=” ” )
# i f i ’ t h c h a r o f p l a i n t e x t i s n o t p a r t o f t h e a l p h a b e t , l e a v e i t unchanged
e l s e :
print ( ” {} ” . format ( i ) , end=” ” ) print ( ” ” )
main ( )
B.2
Resultaat eerste student
# E n c r y p t s a p l a i n t e x t w i t h a k e y ( number ) g i v e n by t h e u s e r import s y s def main ( ) : # t h e argument g i v e n by t h e u s e r becomes t h e k e y key = i n t ( s y s . a r g v [ 1 ] ) # i f t h e amount o f a rg u m e n t s i s n o t 2 , e r r o r i f len ( s y s . a r g v ) != 2 :
print ( ” u s a g e : python c a e s a r . py key ” ) e x i t ( 1 ) # v a r i a b l e s d e c l a r a t i o n c a p i t a l l o w e r b o u n d = 65 c a p i t a l u p p e r b o u n d = 90 l o w e r c a s e l o w e r b o u n d = 97 l o w e r c a s e u p p e r b o u n d = 122 a l p h a b e t i c a l n u m = 26 c a p i t a l = 65 l o w e r c a s e = 97 # g e t u s e r i n p u t p l a i n t e x t = input ( ” P l a i n t e x t : ” ) print ( ” C i p h e r t e x t : ” , end=” ” ) # i t e r a t e s o v e r e v e r y c h a r a c t e r o f p l a i n t e x t f o r i in p l a i n t e x t :
# c a l c u l a t e s c h a r i f i ’ t h c h a r o f p l a i n t e x t i s l o w e r c a s e e l i f ord ( i ) >= l o w e r c a s e l o w e r b o u n d and ord ( i ) <=
l o w e r c a s e u p p e r b o u n d :
print ( ” {} ” . format ( chr ( ( ( ord ( i ) − l o w e r c a s e + key ) % a l p h a b e t i c a l n u m
) + l o w e r c a s e ) ) , end=” ” )
# i f i ’ t h c h a r o f p l a i n t e x t i s n o t p a r t o f t h e a l p h a b e t , l e a v e i t unchanged
e l s e :
print ( ” {} ” . format ( i ) , end=” ” ) print ( ” ” )
main ( )
B.3
Resultaat tweede student
# E n c r y p t s a p l a i n t e x t w i t h a k e y ( number ) g i v e n by t h e u s e r import s y s def main ( ) : # t h e argument g i v e n by t h e u s e r becomes t h e k e y key = i n t ( s y s . a r g v [ 1 ] ) # i f t h e amount o f a rg u m e n t s i s n o t 2 , e r r o r i f len ( s y s . a r g v ) != 2 :
print ( ” u s a g e : python c a e s a r . py key ” ) e x i t ( 1 ) # v a r i a b l e s d e c l a r a t i o n c a p i t a l l o w e r b o u n d = 65 c a p i t a l u p p e r b o u n d = 90 l o w e r c a s e l o w e r b o u n d = 97 l o w e r c a s e u p p e r b o u n d = 122 a l p h a b e t i c a l n u m = 26 c a p i t a l = 65 l o w e r c a s e = 97 # g e t u s e r i n p u t p l a i n t e x t = input ( ” P l a i n t e x t : ” ) print ( ” C i p h e r t e x t : ” , end=” ” ) # i t e r a t e s o v e r e v e r y c h a r a c t e r o f p l a i n t e x t f o r i in p l a i n t e x t : # c a l c u l a t e s c h a r i f i ’ t h c h a r o f p l a i n t e x t i s c a p i t a l i f ord ( i ) >= c a p i t a l l o w e r b o u n d and ord ( i ) <=
c a p i t a l u p p e r b o u n d :
print ( ” {} ” . format ( chr ( ( ( ord ( i ) − c a p i t a l + key ) % a l p h a b e t i c a l n u m
l o w e r c a s e u p p e r b o u n d :
print ( ” {} ” . format ( chr ( ( ( ord ( i ) − l o w e r c a s e + key ) % a l p h a b e t i c a l n u m
) + l o w e r c a s e ) ) , end=” ” )
# i f i ’ t h c h a r o f p l a i n t e x t i s n o t p a r t o f t h e a l p h a b e t , l e a v e i t unchanged
e l s e :
print ( ” {} ” . format ( i ) , end=” ” ) print ( ” ” )
main ( )
B.4
Resultaat derde student
# E n c r y p t s a p l a i n t e x t w i t h a k e y ( number ) g i v e n by t h e u s e r import s y s def main ( ) : # t h e argument g i v e n by t h e u s e r becomes t h e k e y key = i n t ( s y s . a r g v [ 1 ] ) # i f t h e amount o f a rg u m e n t s i s n o t 2 , e r r o r i f len ( s y s . a r g v ) != 2 :
print ( ” u s a g e : python c a e s a r . py key ” ) e x i t ( 1 ) # v a r i a b l e s d e c l a r a t i o n c a p i t a l l o w e r b o u n d = 65 c a p i t a l u p p e r b o u n d = 90 l o w e r c a s e l o w e r b o u n d = 97 l o w e r c a s e u p p e r b o u n d = 122 a l p h a b e t i c a l n u m = 26 c a p i t a l = 65 l o w e r c a s e = 97 # g e t u s e r i n p u t p l a i n t e x t = input ( ” P l a i n t e x t : ” ) print ( ” C i p h e r t e x t : ” , end=” ” ) # i t e r a t e s o v e r e v e r y c h a r a c t e r o f p l a i n t e x t f o r i in p l a i n t e x t : # c a l c u l a t e s c h a r i f i ’ t h c h a r o f p l a i n t e x t i s c a p i t a l i f ord ( i ) >= c a p i t a l l o w e r b o u n d and ord ( i ) <=
c a p i t a l u p p e r b o u n d :
print ( ” {} ” . format ( chr ( ( ( ord ( i ) − c a p i t a l + key ) % a l p h a b e t i c a l n u m
# i f i ’ t h c h a r o f p l a i n t e x t i s n o t p a r t o f t h e a l p h a b e t , l e a v e i t unchanged
e l s e :
print ( ” {} ” . format ( i ) , end=” ” ) print ( ” ” )