Programme planen, bauen und testen · Übung
Baue und teste einen Teil nach dem anderen
Ein Plan kann immer noch groß wirken, wenn du jeden Schritt gleichzeitig umsetzen möchtest. Baue stattdessen einen kleinen, funktionierenden Teil.
Für diese gezielte Punkteberechnung gehen wir davon aus, dass jede eingegebene Antwort bereits nicht leer ist. Das Ergebnis "missing" aus der vorigen Lektion gehört zum späteren Schritt für Eingabe und erneutes Fragen. Hier kann sich die Punkteberechnung auf den Vergleich gültiger Antworttexte konzentrieren.
Das Quizprogramm muss die Groß- und Kleinschreibung sowie umgebende Leerzeichen ignorieren. Beginne mit dem kleinsten wiederverwendbaren Verhalten:
def clean_answer(text):
return text.strip().lower()
Prüfe es sofort:
assert clean_answer(" BLUE ") == "blue"
Baue dann den nächsten Teil:
def answers_match(given, expected):
return clean_answer(given) == clean_answer(expected)
Prüfe diesen unabhängig:
assert answers_match(" BLUE ", "blue") is True
assert answers_match("blue whale", "whale") is False
Verwende ihn erst dann in der Schleife zur Punkteberechnung:
def score_responses(responses):
score = 0
for response in responses:
if answers_match(response["given"], response["expected"]):
score += 1
return score
Kleine Prüfungen grenzen Fehler ein
Wenn die endgültige Punktzahl falsch ist, aber beide Prüfungen der Hilfsfunktionen erfolgreich sind, liegt das Problem wahrscheinlich in der Schleife zur Punkteberechnung. Wenn die Prüfung der Bereinigung fehlschlägt, gibt es noch keinen Grund, in der Schleife nach Fehlern zu suchen.
Jeder fertige Teil verkleinert den Bereich, den du untersuchen musst.
Baue in der Reihenfolge der Abhängigkeiten
Beginne mit Funktionen, die nicht von deinen anderen Funktionen abhängen:
clean one answer
compare two cleaned answers
count matching response records
format the score
So entsteht eine natürliche Reihenfolge. Spätere Funktionen können sich auf früheres Verhalten stützen, für das bereits Belege vorliegen.
Halte das Programm ausführbar
Nach jeder kleinen Änderung:
Führe die gezielten Prüfungen aus.
Führe ein Beispiel von Anfang bis Ende aus.
Speichere oder bewahre den funktionierenden Stand.
Füge das nächste Verhalten hinzu.
Eine halbstündige Neufassung mit nur einem abschließenden Durchlauf schafft viele mögliche Fehlerursachen auf einmal. Häufige kleine Durchläufe machen die Fehlersuche weniger aufwendig und erheblich weniger dramatisch.
Funktionsgerüste können einen Platz freihalten
Während der Planung kann ein Funktionskörper vorübergehend pass enthalten:
def score_responses(responses):
pass
So kannst du die Grenze der Funktion benennen und den Aufrufer skizzieren. Ersetze das Gerüst, bevor du dich auf sein Ergebnis verlässt. Ein Gerüst markiert unfertige Arbeit und ist keine erfolgreiche Umsetzung.
Eine Quizpunktzahl hängt vom Bereinigen von Text und vom Vergleichen bereinigter Werte ab. Welche Reihenfolge beim Aufbau liefert die klarsten Rückmeldungen?
Aufgabe
Baue eine Quizpunkteberechnung in der Reihenfolge ihrer Abhängigkeiten.
Implementiere
clean_answer(text)so, dass es umgebende Leerraumzeichen entfernt und die Groß- und Kleinschreibung ignoriert.Implementiere
answers_match(given, expected)so, dass esclean_answerverwendet und einen booleschen Wert zurückgibt.Implementiere
score_responses(responses)so, dass es für jedes übereinstimmende Paar aus"given"und"expected"einen Punkt zurückgibt.
Behalte die gezielten Zusicherungen nach jeder Funktion bei. Arbeite von oben nach unten: Bringe eine Funktion und ihre Prüfungen zum Laufen, bevor du zur nächsten übergehst. Behalte die vorbereiteten Antworten und die abschließende Ausgabe bei.
Die Antworten enthalten absichtlich Leerzeichen, Unterschiede in der Groß- und Kleinschreibung und eine falsche Antwort. Die endgültige Ausgabe muss lauten:
Score: 2/3