it-swarm.com.de

Greifen Sie auf mehrere Entitäten im Repository zu - saubere Architektur

Ich habe einen API-Aufruf, der eine Liste von Payments zurückgibt. Jedes Payment enthält ein User. Ich muss es aufrufen, die Ergebnisse in der Datenbank speichern, alle Zahlungen und Benutzer abrufen und sie alle an den Präsentator zurücksenden. Auf der Benutzeroberfläche enthält jede Zahlungszeile auch Informationen zum Benutzer. In meinem Fall sind die Entitäten Payment und User stark gekoppelt.

Meine Idee war es, PaymentRepository und GetPaymentsUseCase zu erstellen. Das Repository hat in diesem Fall Zugriff auf die Tabellen Payment und User, sodass beide abgefragt und in beide eingefügt werden können. Allerdings (korrigieren Sie mich, wenn ich falsch liege) besagen die Prinzipien der sauberen Architektur, dass jedes Repository für eine Entität verantwortlich sein sollte.

Aber in meinem Fall macht es wirklich keinen Sinn, diesen Aufruf zwischen zwei Repos zu trennen. Wenn ich mich dazu entscheide, sollten PaymentRepository und UserRepository nicht aufeinander zugreifen, sodass der Anwendungsfall beide aufrufen und Daten zwischen ihnen übertragen müsste, nachdem sie hin und her zugeordnet wurden. das sieht meiner meinung nach schrecklich aus.

Ist meine Lösung akzeptabel oder verstößt sie gegen die Prinzipien der sauberen Architektur? Wenn ja, gibt es Vorschläge, wie dies umgesetzt werden kann?

7
wise.potato

Ihr Repository unterbricht nicht das " saubere Architektur ", das Entitäten als Kern identifiziert, eine Abhängigkeitsinversion erfordert, jedoch keine Repositorys verwendet.

Ihr Repository scheint jedoch gegen die Clean-Code-Prinzipien zu verstoßen, insbesondere:

  • das Prinzip der Einzelverantwortung : Sie packen Dinge zusammen, die unterschiedliche Gründe für Änderungen haben: Payment (die sich beispielsweise aufgrund neuer Geschäftspraktiken oder neuer Bankstandards ändern können) und User (vorbehaltlich interner Richtlinien, GDPR-Bedenken oder Anforderungen an Identitätsanbieter);
  • das Prinzip der Schnittstellentrennung : Sie zwingen die Clients Ihres Repositorys, die Schnittstelle von Payment und User zu kennen, auch wenn sie diese nicht benötigen (z. B. wenn es sich um einen späteren Anwendungsfall handelt) würde einen Bericht über die Summe der Zahlungen pro Tag im letzten Monat erstellen).

Ihr Ansatz scheint auch nicht mit den Prinzipien von Domain Driven Design übereinzustimmen, die ein Repository für ein einzelnes Aggregat vorschlagen:

  • In DDD identifizieren Sie Entities und gruppieren sie in unabhängige Aggregate, die Objekte sind, auf die immer über eine einzelne Aggregate Root zugegriffen werden muss.

  • In Ihrem Fall haben Sie jedoch zwei unabhängige Einheiten, die jeweils ein eigenes Aggregat bilden:

    • Es ist nicht möglich, Payment als ein Aggregat zu sehen, das ein abhängiges User enthält, da letzteres möglicherweise existiert, bevor eine Zahlung geleistet wurde.
    • Es ist auch nicht möglich, User als Aggregat mit abhängigem Payments zu betrachten, da dies bedeuten würde, dass Sie eine Zahlung nur in Bezug auf einen Benutzer identifizieren könnten, was kein realistischer Fall für die Zahlung ist Systeme.

Bearbeiten: zusätzliche Infos

Das Repository-Konzept soll eine Abstraktionsebene bereitstellen, mit der Sie persistente Objekte so behandeln können, als ob sie sich in einer Sammlung im Speicher befinden, ohne die Datenbank zu tragen.

Mit diesem Architekturmuster verweisen Sie lieber auf andere Aggregate nach Identität (Wert) . Das typische Szenario besteht darin, Payments durch Abfragen von PaymentRepository abzurufen. Dann würde das UserId der Zahlung verwendet, um den Benutzer mit UserRepostitory.getById() zu erhalten. Alternativ können Sie auch einfach PaymentId verwenden, um einen Benutzer einer Zahlung abzufragen, indem Sie UserRepostitory.getByPaymentId() aufrufen.

Der Vorteil der Identität besteht darin, dass Entitäten in sehr komplexen Modellen entkoppelt werden können: Die Übergabe aller möglichen Arten von Objekten an ein Repository (anstelle einer einfachen ID) würde zu einer Explosion der Schnittstellenabhängigkeiten führen. Wenn verwandte Objekte systematisch vom Repository geladen würden (wie zu erwarten), könnte dies einen Schneeballeffekt haben: Stellen Sie sich vor, Sie hätten Entitäten, die Knoten und Kanten eines Diagramms darstellen. Unabhängig davon, welchen Knoten Sie aus dem Repository erhalten, erhalten Sie das vollständige Diagramm im Speicher!

Davon abgesehen kenne ich weder Ihr Modell noch Ihre Einschränkungen und urteile nicht. Es liegt an Ihnen, zu entscheiden, welche Architektur am besten geeignet ist. Sie können vollkommen von den Regeln abweichen, wenn Sie gültige Argumente haben und die Konsequenzen verstehen. Übrigens könnte diese Frage über die Repository-Leistung Sie interessieren.

6
Christophe