0%

Een programma over bestanden verdelen · oefening

Kies een startpunt

Het project heeft nu drie bestanden. Twee zijn modules die dingen definiëren en verder niets doen, en één is anders.

main.py is het startpunt: het bestand dat je uitvoert om het programma te starten. Dit project heeft er één en dat heeft een taak die de andere bestanden niet hebben. Grotere projecten kunnen meerdere startpunten voor verschillende toepassingen bieden.

Waar een startpunt voor dient

Een startpunt beantwoordt één vraag: wat doet het uitvoeren van dit programma eigenlijk?

Al het andere in een project is een mogelijkheid. models.py beschrijft wat een vraag is. scoring.py kan een score omzetten in een letter. Geen van beide bepaalt hoe het programma draait. De keuzes staan in het startpunt: welke quiz, welke cursist, wat er wordt afgedrukt en in welke volgorde.

Dat maakt het het meest specifieke bestand in het project en het minst herbruikbare, wat precies goed is. Daarom hoort het ook kort te zijn. Als main.py twintig regels telt, kun je ze lezen en weten wat het programma doet. Bij tweehonderd regels zit de vorm van het programma verborgen in hetzelfde bestand als de details.

De vorm

Try it

Drie dingen, in deze volgorde:

  1. Imports, die zeggen waaruit het programma is opgebouwd.

  2. Een functie main() die de onderdelen verbindt.

  3. De uitvoercontrole, die main() alleen aanroept als dit bestand wordt uitgevoerd.

Het werk in main() zetten in plaats van op het hoogste niveau is nuttig, ook al zou alleen de controle al voorkomen dat het bij importeren wordt uitgevoerd. Een functie kan vanuit een test worden aangeroepen, twee keer worden aangeroepen of later andere argumenten krijgen. Code op het hoogste niveau kan alleen één keer gebeuren, op één manier.

Waarom zet je het verbinden van de onderdelen in main() in plaats van rechtstreeks onder if __name__ == "__main__":?

Welk bestand is __main__

Slechts één bestand is tijdens een uitvoering __main__: het bestand dat je startte. Elk ander bestand heeft de eigen modulenaam, ongeacht hoe het werd geïmporteerd.

Dat heeft een praktisch gevolg dat het kennen waard is. Als models.py onderaan een demo achter een uitvoercontrole had, zou het uitvoeren van main.py die niet starten, omdat models in die uitvoering niet __main__ is. models.py rechtstreeks uitvoeren zou dat wel doen. Elk bestand kan een eigen demo bevatten zonder de andere te storen.

Een project lezen via het startpunt

Als een project zo is ingericht, is de snelste manier om het te begrijpen het startpunt openen en de imports lezen.

from models import Attempt, Question, Quiz
from report import report_lines
from scoring import grade_letter, percentage

Drie regels en je weet dat het programma een domein, een rapportagelaag en scoreregels heeft, nog voordat je één functie leest. Dat is de opbrengst van het hele hoofdstuk: de structuur is documentatie die niet kan verouderen, omdat die het programma zelf is.

De oefening

main.py wordt een echt startpunt. Het krijgt de scoremodule erbij en behoudt alleen wat bij het uitvoeren van het programma hoort.

Opdracht

Maak van main.py een echt startpunt.

Importeer wat het nodig heeft: Attempt, Question en Quiz uit models, en grade_letter en percentage uit scoring.

Houd build_quiz() en report_lines(attempt) voorlopig hier; de volgende les geeft het rapport een eigen plek. Breid report_lines uit zodat die een tweede regel teruggeeft die "Grade: <letter>" luidt, met de twee scorefuncties in plaats van zelf de berekening te doen.

main() verbindt de onderdelen en drukt af. Niets anders in het bestand mag bij het importeren worden uitgevoerd en het bestand eindigt met de uitvoercontrole.

Bij het uitvoeren moeten de scoreregel en de regel met de letterbeoordeling worden afgedrukt.