tl; dr - brechen Sie die Regeln, wenn Sie müssen. DDD kann nicht alle Probleme lösen. Tatsächlich sind die darin enthaltenen Objektideen gute Ratschläge und ein guter Anfang, aber für einige geschäftliche Probleme wirklich schlechte Entscheidungen. Betrachten Sie es als einen Hinweis, wie man Dinge macht.
Für das Problem, alle untergeordneten Elemente (Transaktion) mit dem übergeordneten Element (Konto) zu laden - Anscheinend sind Sie auf das n + 1-Problem (etwas zu googeln) gestoßen, das viele ORMs gelöst haben.
Sie können es lösen, indem Sie die untergeordneten Elemente faul laden (Transaktion) - nur bei Bedarf.
Aber es hört sich so an, als ob Sie bereits wissen, dass Sie ein TransactionRepository verwenden können, um das Problem zu lösen.
Um diese Daten zu "verbergen", damit nur das Konto sie verwenden kann, müssen Sie sie nicht einmal dort speichern, wo andere sie nicht deserialisieren können, wie in einer öffentlichen relationalen Tabelle. Sie können es mit dem 'Dokument' des Kontos in einer Dokument-DB speichern lassen. So oder so, wenn jemand sich genug Mühe gab, konnte er die Daten immer noch sehen. Und damit arbeiten. Und wenn Sie nicht suchen, werden sie!
Sie können also Berechtigungen einrichten, müssen dann aber 'account' als separaten Prozess ausführen.
Was Sie hier wirklich erkennen, ist, dass DDD und die reine Verwendung des Objektmodells Sie manchmal in eine Ecke führen. Um ehrlich zu sein, müssen Sie natürlich nicht die 'Komposition' / Aggregatwurzel verwenden, um von den Designprinzipien von DDD zu profitieren. Es ist nur eine Sache, die Sie verwenden können, wenn Sie eine Situation haben, die in ihre Einschränkungen passt.
Jemand könnte sagen "nicht frühzeitig optimieren". Hier in diesem Fall kennen Sie jedoch die Antwort: Es wird genügend Transaktionen geben, um eine Methode zu blockieren, die sie alle für immer im Konto behält.
Die wirkliche Antwort ist, SOA aufzustehen. An meinem Arbeitsplatz haben wir uns die Udi Dahan-Videos "Distributed Computing" angesehen und nServiceBus gekauft (nur unsere Wahl). Erstellen Sie einen Dienst für Konten - mit einem eigenen Prozess, Nachrichtenwarteschlangen, Zugriff auf eine Beziehungsdatenbank, die nur angezeigt wird, und ... Viola, Sie können SQL-Anweisungen im Programm fest codieren und sogar ein paar Cobol-Transaktionsskripte einfügen (Scherz) natürlich), aber ernsthaft mehr Trennung von Bedenken, als der klügste OO / Java-Snob jemals träumen könnte.
Ich würde empfehlen, es trotzdem gut zu modellieren. Sie können hier einfach die Vorteile von Aggregat Root ohne Probleme nutzen, indem Sie den Service als mini-begrenzten Countext behandeln.
Dies hat natürlich einen Nachteil. Sie können nicht nur RPC (Webservice, SOAP oder REST) in und aus Diensten und zwischen ihnen einbinden, oder Sie erhalten aufgrund der zeitlichen Kopplung ein SOA-Antimuster namens "The Knot". Sie müssen die Umkehrung des Kommunikationsmusters verwenden, auch bekannt als "Pub-Sub", das genau wie Ereignishandler und Ereignisauslöser ist, aber (1) zwischen Prozessen (die Sie auf separate Computer stellen können, wenn diese auf einem überlastet werden).
Das eigentliche Problem ist, dass Sie nicht möchten, dass ein Dienst, der Daten von einem anderen Dienst erhalten muss, blockiert oder wartet. Sie müssen die Nachricht auslösen und vergessen und sie von einem Handler an einer anderen Stelle in Ihrem Programm abholen lassen, um die Verarbeitung abzuschließen. Dies bedeutet, dass Sie Ihre Logik anders machen müssen. nServicebus automatisiert das "Saga" -Muster, um einige dieser Probleme zu lösen. Am Ende müssen Sie jedoch einen anderen Codierungsstil entwickeln. Sie können immer noch alles tun, müssen es nur anders machen!
Das Buch "SOA Patterns" von Arnon Rotem-Gal-Oz beantwortet viele Fragen dazu. Einschließlich der Verwendung des "aktiven Dienstmusters", um Daten von externen Diensten bei Bedarf regelmäßig auf Ihre eigenen zu replizieren (viele RPCs wären erforderlich gewesen oder die Verknüpfung ist unzuverlässig / nicht im Publish / Subscribe-Ökosystem).
Nur um Vorschau, UIs Sie auf RPC in Dienstleistungen. Berichte werden aus einer Berichtsdatenbank generiert, die von den Datenbanken der Dienste gespeist wird. Einige Leute sagen, dass Berichte nicht benötigt werden und dass das Problem auf andere Weise gelöst werden sollte. Seien Sie skeptisch gegenüber diesem Gespräch.
Am Ende können jedoch nicht alle Dinge richtig in einen einzigen Dienst eingeteilt werden. Die Welt läuft nicht mit Ravioli-Code! Sie müssen also gegen Regeln verstoßen. Selbst wenn Sie es niemals müssten, werden neue Entwickler des Projekts dies tun, wenn Sie es verlassen. Aber keine Sorge, wenn Sie tun, was Sie können, machen die 85%, die den Regeln folgen, ein Programm, das weitaus wartbarer ist.
Wow, das war lang.