Vorschläge zur Präzisierung der zenralen Interfaces
Momentan existieren 3 verschieden Interfaces:
Ich schlage folgende Anpassungen/Präzisierungen vor
RawDataSourceInterface
class RawDataSourceInterface(ABC):
@abstractmethod
def fetch(self) -> io.StringIO:
raise NotImplementedError
Änderungen:
- Streichen des Konstrukturs aus dem Interface. Da Implementierungen des Interfaces wahrscheinlich abweichende Initialiserungsverfahren und -parameter benötigen, würde ich das handling vollständig den realisierenden Klassen überlassen
-
fetch_file
->fetch
: Auch wenn Rohdaten (momentan) häufig als Dateien vorliegen, kann sich das ja ändern. EineRawDataSource
, die über einen Aufruffetch_file
z.B. Daten aus dem Netz holt, käme mir etwas seltsam vor. - Ich würde Vorschlagen den Rückegabewert hier zu typisieren (den type hint zuzufügen). Für die Nutzer des Interaces ist das eine relevante Information. Welcher Typ sinnvollerweise verwendet wird kann sicher kontrovers diskutiert werden, hier ist es ein
tempfile.TemporaryFile
Objekt. Ich denke nicht, dass das die beste Lösung ist und würde stattdessen einen in-memory text stream a laio.StingIO
vorschlagen. Diese sind in (fast) allen Kontexten einsetzbar, in denen auchfile
- Objekte zum einsatz kommen, betriebssystemunabhängig und eben in-memory.
ParserInterface
class TransformerInterface(ABC):
def __init__(self, datastore: DatastoreInterface, source: RawdataSourceInterface):
self.datastore = datastore
self.source = source
@abstractmethod
def transform(self, *args, **kwargs):
raise NotImplementedError
Änderungen:
- Ich hatte noch nie was für 'dependency injection' übrig, wenn die Übergabe als Konstrukturargumente denselben Zweck erfüllt. Sicher Geschmacksache macht das Interface aber kleiner...
-
load_data
scheint mir nicht nötig zu sein. Da jeder Transformer ohnehin auf einemRawdataSourceInterface
sitzt, scheint mir ein explizite load-Methode redundant (wenn load im Sinne von extract) - Begrifflichkeit: parser -> transformer `
DatastoreInterface
class DatastoreInterface(ABC):
@abstractmethod
def store(self, value: Sequence[Value]) -> None:
"""Save a new value to the datastore"""
raise NotImplementedError
Änderungen:
- Initialisierung und Verbindungsaufbau sind sehr implementierungsspezifisch und zudem für die Nutzer des Interfaces nicht relevant (wenn ich einen
Datastore
initialisiere, möchte ich mich eigentlich nicht um den Verbindungsaufbau explizit kümmern müssen, oder?) - Die
store
- Methode sollte auch mehrereValue
s auf einmal schreiben können und so bulk inserts (zumindest konzeptionell) anbieten.