2.5 KiB
2.5 KiB
Task 13 — Storage-Factory und StorageType
Rückblick Task 12: Storage-Abstraktion
Ihr habt storage.py mit einer abstrakten Basisklasse Storage und einer
konkreten JsonStorage eingeführt. Die wichtigsten Punkte:
- ABC und
@abstractmethod: Eine Klasse, die vonABCerbt und eine@abstractmethoddefiniert, kann nicht direkt instanziiert werden — Python wirft einenTypeError. Eine Unterklasse muss alle abstrakten Methoden implementieren, sonst gilt sie selbst als abstrakt. - Warum
store()einenstrzurückgibt: Der Aufrufer bekommt einen Identifier zurück (Dateipfad, Tabellenname, URL), ohne zu wissen, welches Backend dahintersteckt. Das ist nützlich fürs Logging und für Tests. StorageError: Eine eigene Exception macht den Code robuster —main.pymuss nurStorageErrorkennen, nicht alle möglichenOSError-,psycopg2- oder sonstigen Backend-Fehler.
Aufgabe
In main.py steht aktuell:
storage = JsonStorage(output_dir=config["storage"]["output_dir"])
Das bedeutet: Will man später ein anderes Backend verwenden, muss main.py
angefasst werden. Ausserdem muss main.py wissen, welche Klasse (JsonStorage,
PostgresStorage, ...) zu welchem Config-Wert gehört.
Ziel ist eine Factory-Funktion build_storage(cfg), die diese Entscheidung
übernimmt — main.py übergibt nur die Config und bekommt ein fertiges
Storage-Objekt zurück.
Konkret:
- Füge in
storage.pyeineStorageType-Enum hinzu:
class StorageType(StrEnum):
JSON = "json"
POSTGRES = "postgres"
- Schreibe eine Factory-Funktion
build_storage(cfg: dict) -> Storageinstorage.py, die anhand voncfg["type"]den richtigen Storage instanziiert. Verwende dafür einmatch-Statement. - Passe
config.yamlan — derstorage-Abschnitt bekommt eintype-Feld:
storage:
type: json
params:
output_dir: ./data/results
- Ersetze in
main.pydie direkte Instanziierung durch:
storage = build_storage(config["storage"])
Fragen zum Nachdenken:
- Was ist der Vorteil eines
match-Statements gegenüber einerif/elif-Kette — und ab wann lohnt sich das? - Was passiert, wenn jemand in
config.yamleinen ungültigentype-Wert einträgt (z.B."mongodb")? Wie solltebuild_storage()damit umgehen? - Warum übergeben wir
paramsals**paramsan den Konstruktor — und was ist der Vorteil gegenüber einzelnen Parametern?