JaBudget Repository
JaBudget Repsoitory definiert die Schnittstelle zu Persistenzsystemen.
AccountRepository
Um die Schnittstelle einfach zu halten, bezieht sich das Erzeugen / Ändern / Löschen von Entitäten immer auf eine Entität.
Alternativen
- Es gibt Methoden zum Beeinflussen von mehreren Entitäten auf einmal. Dabei wird ein Response-Objekt Konzept notwendig, da innerhalb einer Aktion sowohl Fehler als auch Erfolg möglich sind.
Das Repository geht immer davon aus, dass valide Entitäten geliefert werden. Werden nicht valide Entitäten geliefert, darf das Repository eine (beliebige?) RuntimeException werfen.
Alternativen
- Bei nicht validen Entitäten wird eine konkrete RuntimeException geworfen, die auch Fehler-Information enthält. Um den Client noch stärker zu involvieren könnte auch eine CheckedException verwendet werden.
- Bei der Verwendung eines Response-Objekt Konzepts kann anstelle der Exception ein einfacherers Fehlerobjekt verwendet werden, da bei Validierungsfehlern nur die Ursache, aber nicht der Ort der Validierung (Stacktrace) relevant ist.
Entitäten erzeugen / ändern
Ein grundlegendes Konzept ist, dass die geänderten Daten wieder zurückgeliefert werden, damit der Client eine Referenz zum Weiterarbeiten hat, ohne eine neue Anfrage machen zu müssen.
Alternativen
- Es wird nichts zurückgegeben: Der Client kann sich die Daten über die zum Anlegen gewählte ID holen. Dies spart den Transfer (Verringerung des Datenvolumens), wenn der Client "fire and forget" macht. Bedeutet eine zusätzliche Anfrage (Erhöhung der Verarbeitungsdauer), wenn der Client das Ergebnis bekommen möchte.
- Es wird nur die ID zurückgegeben: Da die ID clientseitig erzeugt wird, kein signifikanter Unterschied zum oberen Punkt.
- Der Client teilt mit, ob er ein Ergebnis erwartet (z.B. über ein Request-Objekt / eine separate void Methode). Dies erhöht den Implementierungsaufwand und verschiebt die Verantwortung in Richtung des Clients.
Beim Ändern von Entitäten wird davon ausgegangen, dass der Client sich bewusst für eine Entität zum Ändern entschieden hat. Ist diese nun nicht im Zustand, dass sie geändert werden kann, ist dies ein "Fehler", der über das Werfen einer Ausnahme mitgeteilt wird. Der Client wird über die Ausnhame "gezwungen" sich mit der Möglichkeit des falschen Zustands auseinander zu setzen.
Alternativen
- Da beim Ändern das geänderte Objekt zurückgegeben wird, kann bei fehlerhaftem Zustand das korrekte Objekt bzw. ein leeres Objekt zurückgegeben werden. Dies verschiebt die Verantwortung in Richtung des Clients sich um den impliziten Fehler zu kümmern.
- An Stelle der Ausnahme wird mit einem Response-Objekt gearbeitet. Dieses enthält zu.B. einen Rückgabewert und gegebenenfalls die Entität. Eine einfacheste Version kann auch mit einem Optional arbeiten und über die Abwesenheit der Entität implizit mitteilen, dass irgendein Fehler aufgetreten ist. Ein Response-Objekt vermeidet das "Durchreichen" von Checked-Exceptions bzw. das Dokumentieren von möglichen Unchecked-Exceptions.
create
Persistiert eine neue Instanz eines Entities. Gibt das persistierte Objekt zurück.
Wirft eine DomainException mit DomainFailure DUPLICATE_ENTITY falls ein Entity mit gleicher ID existiert.
Alternativen
- Sollte die Entität mit gleicher ID und gleichen Daten vorhanden sein, wird dies nicht als Fehler gewertet.
update
Aktualisiert eine bestehende Instanz eines Entities. Gibt das persistierte Objekt zurück.
Wirft eine DomainException mit DomainFailure MISSING_ENTITY falls ein Entity mit gegebener ID nicht existiert.
Alternativen
- Erzeugt die Entität, die nicht vorhanden ist. Dies birgt die Gefahr, dass ein Client eine Entität löscht, die ein Anderer noch in Bearbeitung hat und dann persistiern möchte. Hier kommt es zum Konflikt, welche Aktion "wichtiger" ist, das Löschen oder das Bearbeiten und Ändern. Dies kann nur im Client aufgelöst werden, da es eine fachliche Entscheidung ist.
replaceAll
Löscht alle vorhandenen Entitäten und ersetzt sie duch die gegebenen. Diese Methode ist für Importe / Migrationen gedacht.
Alternativen
- Über findAll und anschließendes create / update / delete den Austausch aller Entitäten vornehmen. Dies hätte den Vorteil, dass ein Auditing stattfinden kann. Dies hat den Nachteil, dass ein Importer eine Vergleichslogik implementieren muss.
Entitäten lesen
Beim Lesen von Entitäten besteht immer die Möglichkeit, dass die gesuchte(n) Entität(en) nicht existieren. Dies ist kein Ausnahmefall, daher wird dafür keine Ausnahme geworfen, sondern eine leere Antwort gegeben.
Alternativen
- Bei potentiell großen Mengen zum lesen von Enitäten kann die Ergebnismenge nicht dem gewünschten entsprechen. Eine Einschränkung auf eine maximale Anzahl, seitenweise Abfrage oder Segmentierung kann die Ergebnismenge einschränken.
- Anstelle der (potentiell) leeren Antwort kann ein Response-Objekt zurückgegeben werden, welches gegebenenfalls auch weitere Informationen z.B. zur Gesamtmenge oder Seitenanzahl beim Lesen von Mengen liefern kann.
findAll
Liefert ein Set mit allen vorhandenen Entities zurück. Die Entities haben keine natürliche Ordnung und es gibt keine doppelten Entitäten, daher wird ein Set verwendet. Sind keine Entitäten vorhanden, wird ein leeres Set zurückgeliefert.
Alternativen
- Anstelle der vollständigen Entitäten werden nur die IDs der Entitäten zurückgegeben, um die Ergebnisgröße einzuschränken.
findById
Liefert eine einzelne Entität anhand ihrer Id zurück. Wird unter der Id keine Entität gefunden, ist das gelieferte Optional leer.
Entitäten löschen
delete
Beim Löschen von Entitäten besteht immer die Möglichkeit, dass die gesuchte Entität nicht existiert. Dies wird nicht als Ausnahmefall gesehen, daher wird dafür keine Ausnahme geworfen. Das Löschen einer nicht vorhandenen Entität wird als Erfolg angesehen.
Alternativen
- Anstelle der booleschen Antwort kann ein Response-Objekt zurückgegeben werden, welches gegebenenfalls auch weitere Informationen liefern kann (z.B. dass die Entität zum Löschen bereits nicht mehr vorhanden war).
Um eine Möglichst einfache Schnittstelle zu haben, reicht es aus, zum Löschen die ID der Entität zu liefern.
Alternativen
- Anstelle der ID wird die gesamte Entität geliefert. Damit bietet sich die Möglichkeit, bei abweichenden Daten das Löschen nicht durchzuführen und den Clienten zu befragen, ob auch die geänderte Instanz gelöscht werden soll. Das Übertragen der gesamten Entität erhöht aber das Datenvolumen.
- Anstelle der ID wird eine Entitätshülle geliefert, die die ID enthält. Dies ist problematisch, da Entitäten immer valide sein sollen und somit die Pflichtfelder der Entität auch übertragen werden müssten.