Programma’s plannen, bouwen en testen · oefening
Bouw en test één onderdeel tegelijk
Een plan kan nog steeds groot aanvoelen wanneer je elke stap tegelijk probeert te implementeren. Bouw eerst een klein werkend deel.
Neem voor deze gerichte scoreberekening aan dat elk ingevoerd antwoord al niet-leeg is. Het resultaat "missing" uit de vorige les hoort bij de latere stap voor invoer en opnieuw proberen. Hier kan de scoreberekening zich richten op het vergelijken van geldige antwoordtekst.
Het quizprogramma moet hoofdletters en spaties aan de buitenkant negeren. Begin met het kleinste herbruikbare gedrag:
def clean_answer(text):
return text.strip().lower()
Controleer het meteen:
assert clean_answer(" BLUE ") == "blue"
Bouw daarna het volgende onderdeel:
def answers_match(given, expected):
return clean_answer(given) == clean_answer(expected)
Controleer dat afzonderlijk:
assert answers_match(" BLUE ", "blue") is True
assert answers_match("blue whale", "whale") is False
Gebruik het pas daarna in de scorelus:
def score_responses(responses):
score = 0
for response in responses:
if answers_match(response["given"], response["expected"]):
score += 1
return score
Kleine controles beperken de zoekruimte bij fouten
Als de eindscore verkeerd is maar beide controles van hulpfuncties slagen, zit het probleem waarschijnlijk in de scorelus. Als de opschoningscontrole mislukt, heeft het nog geen zin om de lus te debuggen.
Elk voltooid onderdeel verkleint het gebied dat je moet onderzoeken.
Bouw in de volgorde van afhankelijkheden
Begin met functies die niet van je andere functies afhangen:
clean one answer
compare two cleaned answers
count matching response records
format the score
Zo ontstaat een natuurlijke volgorde. Latere functies kunnen vertrouwen op eerder gedrag waarvoor al bewijs bestaat.
Houd het programma uitvoerbaar
Na elke kleine wijziging:
voer de gerichte controles uit;
voer één voorbeeld van begin tot eind uit;
sla de werkende toestand op of bewaar die;
voeg het volgende gedrag toe.
Een half uur herschrijven gevolgd door één uitvoering aan het einde levert veel mogelijke oorzaken tegelijk op. Regelmatig kleine delen uitvoeren maakt het debuggen goedkoper en een stuk minder dramatisch.
Tijdelijke functies kunnen een plek vrijhouden
Tijdens het plannen kan een functieblok tijdelijk pass bevatten:
def score_responses(responses):
pass
Zo kun je de grens benoemen en de aanroeper schetsen. Vervang deze tijdelijke invulling voordat je op het resultaat vertrouwt. Ze markeert onafgemaakt werk en is geen geslaagde implementatie.
Een quizscore hangt af van tekst opschonen en opgeschoonde waarden vergelijken. Welke bouwvolgorde geeft de duidelijkste feedback?
Opdracht
Bouw een quizscoreberekening in de volgorde van afhankelijkheden.
Implementeer
clean_answer(text)zodat de functie witruimte aan de buitenkant verwijdert en hoofdletters negeert.Implementeer
answers_match(given, expected)zodat de functieclean_answergebruikt en een booleaanse waarde teruggeeft.Implementeer
score_responses(responses)zodat de functie één punt teruggeeft voor elk overeenkomend paar"given"en"expected".
Behoud de gerichte asserties na elke functie. Werk van boven naar beneden: zorg dat één functie en de bijbehorende controles slagen voordat je naar de volgende gaat. Behoud de voorbereide antwoorden en de laatste afdrukinstructie.
De antwoorden bevatten bewust spaties, verschillen in hoofdletters en één verkeerd antwoord. De uiteindelijke uitvoer moet zijn:
Score: 2/3